1

私はマルチモジュールのC#/ SQL Serverベースのアプリケーションを設計しています。私の設計は、KeyTypeValuesと呼ばれるテーブル内のすべての汎用ルックアップ値を保持することです。この表は、どのタイプのデータであるかを定義するKeyTypesに関連しています。例えばパフォーマンスの問題を引き起こす問題のデータベース設計

oms.KeyTypes 
------------ 
Id   INT NOT NULL IDENTITY(1,1) PRIMARY KEY 
KeyTypeName VARCHAR(40) NOT NULL 
... 

oms.KeyTypeValues 
----------------- 
Id     INT NOT NULL IDENTITY(1,1) PRIMARY KEY 
KeyTypeId   INT NOT NULL (FOREIGN KEY to oms.KeyTypes Id) 
KeyTypeValueMeaning VARCHAR(80) NOT NULL 
... 

oms.KeyTypesサンプルデータ:

Id KeyTypeName   KeyTypeDescription 
-- -----------   ------------------ 
1 RES_MFGS   Resource Manufacturers 
2 RES_OWNERSHIP_TYPES Resource Ownership Types 
... 

oms.KeyTypeValuesサンプルデータ:

Id KeyTypeId KeyTypeValueMeaning 
-- --------- ------------------- 
1 1   Ford 
2 1   Chevrolet 
3 2   Owned 
4 2   Leased 
... 

だから、アイデアは私が持っていないということです別途ManufacturersOwnershipTypeModelなどのテーブルを作成するその値以外のこれらの値に関する追加の情報は実際には必要ありません。現在、私は約88を既に定義しており、デザインはうまく機能しています。

res.ResourceItemsというテーブルから参加する際にパフォーマンスの問題を引き起こす問題のクエリに取り組んでいます。私はそれをKeyTypeValuesテーブルに6回ずつ異なるルックアップに参加させなければなりません。 ResourceItems定義の

パート:

res.ResourceItems 
----------------- 
Id    INT NOT NULL IDENTITY(1,1) PRIMARY KEY 
OwnsershipTypeId INT NOT NULL 
ManufacturerId INT NOT NULL 
... 

私は私の問題キータイプ(RES_OWNERSHIP_TYPES)を除去した場合、私は大きく開く、それを実行することができ、それは約17秒で70の以上の列に〜112,000行を引き戻します。パフォーマンスは素晴らしいことではありませんが、私は9つの追加テーブルに参加しなければならないと考えています。ただし、結合を追加してRES_OWNERSHIP_TYPESを取得すると、実行時間は45秒にジャンプします。 RES_OWNERSHIP_TYPESキータイプはこの時点で3つの可能な値しか持たず、oms.KeyTypeValuesには合計レコードが約3,000しかありません。それは、構築されているシステムにもっと多くを追加するにつれ、時間の経過とともにゆっくりと成長し続けます。

オーナーシップタイプを引き出し、代わりにを作成すると、オーナーシップタイプが存在しない可能性があるため、これを処理するより効率的な方法です。しかし、私はそのような劇的なパフォーマンスヒットがある全体的なデザインに懸念しています。

すべてのID値に対して、res.ResourceItemsからoms.KeyTypeValuesまでの外部キーの関係があります。 oms.KeyTypeValues.Id列にNon-Unique、Non-Clusteredインデックス設定もあります。私は断片化を解消するためにそれらを再構築しました。

はテストとして、私は私の resスキーマ内の別の KeyTypesKeyTypeValuesテーブルを作成しただけで RES_OWNERSHIP_TYPES値をロードし、それに結合され、そして実行時間は約17秒に戻りました。私はむしろ、私の目的を打ち負かしたり、より大きな問題にバンドエイドを入れているように見えるので、これを実行してはいけません。

私はなぜそのような大きなヒットがあるのか​​を判断できず、誰かが私が見落としているかもしれないことについての洞察を得ることを望んでいたと思います。必要に応じて、より多くのデータベース設計を分かち合うことができます。

+0

[カバーインデックス](http://www.dbadiaries.com/sql-server-covering-index-and-key-lookup/)の使用を検討してください。 SQL Server 2005以降のバージョンでは、[included columns](http://msdn.microsoft.com/en-us/library/ms190806.aspx)と複合インデックスがサポートされています。 – HABO

答えて

0

3つのレコードを持つテーブルに結合を追加することは、パフォーマンスに大きな影響を与えている場合、その結合を追加することでクエリプランが大幅に変化することを意味します。

試してみるとすばらしいことは、sp_updatestatsを一度実行して問題が解決するかどうかを確認することです(それは可能性が高いと思います)。これにより、SQL Serverはすべてのテーブルとインデックスの統計を更新し、クエリプランを使用してより良い選択をするように指示します。

より完全な解決策は、の理由を理解するために2つのバリエーションの実行計画を比較することです。つまり、のパフォーマンスが低下します。これにより、パフォーマンスを向上させる方法が明らかになります。私はテーブルを削除してコード専用の列挙型にすることはお勧めしません。事態が正しく機能している場合は、余分なテーブルに参加する際のパフォーマンスの違いは認識できません。

+0

あなたと@FLICKERの両方の提案をしてくれて助けました。 'sp_updatestats'を実行するだけで最大のインパクトがあり、20秒以下に戻りました。追加のインデックスを追加してサブクエリを使用すると、数秒後に消滅するため、両方のクエリが実質的に同じになります。 – bassrek

1

私たちは、実際のデータとドンを持っていないしかし、ルックアップテーブルが速くJOIN

よりも動作しますsub-query、(自分のルックアップテーブルのように)小さい場合は、時には代わりJOIN

sub-queryを使用することをお勧め実行計画があるので、提案とは異なる答えを試して、どちらがあなたのために働くのかを見てください。

これがうまくいかない場合は、参照フィールド(参照フィールドに加えて)にインデックスを追加してみてください。

私はあなたのデザインが悪いとは思わない。私は多くの異なるシステムでそのようなルックアップテーブルを見てきました。

+0

ありがとうございます - あなたと@Timの両方を回答としてマークしたいと思います。しかし、統計を更新することが最大の原因と思われた。私はサブクエリと追加インデックスを試したので、数秒余分に削られました。デザインにコメントしてくれてありがとう - 私はこのタイプのデザインをさまざまなシステムで使いました。それはかなり良いと思います。 – bassrek

+0

統計情報を常に最新の状態に保つことは常に良いことです。アップ投票ありがとう:) – FLICKER

関連する問題