インデックス調整の質問


8

私はいくつかのインデックスを調整していて、いくつかの問題があなたのアドバイスを望んでいるのを見ています

1つのテーブルに3つのインデックスがあります

dbo.Address.IX_Address_ProfileId 
[1 KEY] ProfileId {int 4}
Reads: 0 Writes:10,519

dbo.Address.IX_Address 
[2 KEYS] ProfileId {int 4}, InstanceId {int 4}
Reads: 0 Writes:10,523

dbo.Address.IX_Address_profile_instance_addresstype
[3 KEYS] ProfileId {int 4}, InstanceId {int 4}, AddressType {int 4}
Reads: 149677 (53,247 seek) Writes:10,523

1-最初の2つのインデックスは本当に必要ですか、それとも削除する必要がありますか?

2- profileid = xxxxである使用条件を実行するクエリと、profileid = xxxxおよびInstanceID = xxxxxxである他の使用条件があります。オプティマイザが1番目または2番目ではなく3番目のインデックスを選択する理由

また、各インデックスでロック待機を取得するクエリを実行しています。これらのカウントを取得している場合、このインデックスを調整するにはどうすればよいですか?

Row lock waits: 484; total duration: 59 minutes; avg duration: 7 seconds; 
Page lock waits: 5; total duration: 11 seconds; avg duration: 2 seconds; 
Lock escalation attempts: 36,949; Actual Escalations: 0.

テーブル構造は

TABLE [dbo].[Address](
[Id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[AddressType] [int] NULL,
[isPreferredAddress] [bit] NULL,
[StreetAddress1] [nvarchar](255) NULL,
[StreetAddress2] [nvarchar](255) NULL,
[City] [nvarchar](50) NULL,
[State_Id] [int] NOT NULL,
[Zip] [varchar](20) NULL,
[Country_Id] [int] NOT NULL,
[CurrentUntil] [date] NULL,
[CreatedDate] [datetime] NOT NULL,
[UpdatedDate] [datetime] NOT NULL,
[ProfileId] [int] NOT NULL,
[InstanceId] [int] NOT NULL,
[County_id] [int] NULL,
 CONSTRAINT [PK__Address__3214EC075E4BE276] PRIMARY KEY CLUSTERED 
(
   [Id] ASC
 )

これは例です(このクエリはhibernateによって作成されたため、奇妙に見えます)

(@P0 bigint)select addresses0_.ProfileId as Profile15_109_1_
, addresses0_.Id as Id1_20_1_
, addresses0_.Id as Id1_20_0_
, addresses0_.AddressType as AddressT2_20_0_
, addresses0_.City as City3_20_0_
, addresses0_.Country_Id as Country_4_20_0_
, addresses0_.County_id as County_i5_20_0_
, addresses0_.CreatedDate as CreatedD6_20_0_
, addresses0_.CurrentUntil as CurrentU7_20_0_
, addresses0_.InstanceId as Instance8_20_0_
, addresses0_.isPreferredAddress as isPrefer9_20_0_
, addresses0_.ProfileId as Profile15_20_0_
, addresses0_.State_Id as State_I10_20_0_
, addresses0_.StreetAddress1 as StreetA11_20_0_
, addresses0_.StreetAddress2 as StreetA12_20_0_
, addresses0_.UpdatedDate as Updated13_20_0_
, addresses0_.Zip as Zip14_20_0_ 
from dbo.Address addresses0_ 
where addresses0_.ProfileId=@P0 

ここに画像の説明を入力してください

(@P0 bigint,@P1 bigint)
select addressdmo0_.Id as Id1_20_
, addressdmo0_.AddressType as AddressT2_20_
, addressdmo0_.City as City3_20_
, addressdmo0_.Country_Id as Country_4_20_
, addressdmo0_.County_id as County_i5_20_
, addressdmo0_.CreatedDate as CreatedD6_20_
, addressdmo0_.CurrentUntil as CurrentU7_20_
, addressdmo0_.InstanceId as Instance8_20_
, addressdmo0_.isPreferredAddress as isPrefer9_20_
, addressdmo0_.ProfileId as Profile15_20_
, addressdmo0_.State_Id as State_I10_20_
, addressdmo0_.StreetAddress1 as StreetA11_20_
, addressdmo0_.StreetAddress2 as StreetA12_20_
, addressdmo0_.UpdatedDate as Updated13_20_
, addressdmo0_.Zip as Zip14_20_ 
from dbo.Address addressdmo0_ 
left outer join dbo.Profile profiledmo1_ 
on addressdmo0_.ProfileId=profiledmo1_.Id 
where profiledmo1_.Id=@P0 and addressdmo0_.InstanceId=@P1

ここに画像の説明を入力してください


完全なテーブル構造とクラスタリングキーを追加し、profileid = xxxxを検索するクエリと、profilerid = xxxxとinstanceid = xxxxを含むクエリに他の列を追加する可能性があります。これらの回答には多くの「依存する」ものがあり、その情報があると、依存するものを説明するのに役立ちます。
mskinner 2015

データに関する詳細情報が参考になります。たとえば、テーブルで統計が更新されている場合、テーブルにあるレコードの数と一意性などが含まれます。
グレンスワン

@GlenSwan、このテーブルには567644レコードがあります。統計は週に2回更新されました。火曜日と土曜日
2015

2
機能比較については、独自の調査を行ってください。いくつかのオーバーラップがありますが、フェイルオーバークラスターと可用性グループは異なる機能を持ち、異なる要件を満たしているため、どちらが優れているか一般的に尋ねることはできません。それぞれの機能を実際のビジネスニーズと比較する必要があります。また、ライセンス/コストに関する質問はここではトピックに含まれません。このメタ投稿全体を読んでください。
アーロンバートランド

回答:


6

質問1の回答:

投稿したものから最初の2つのインデックスを削除できます。3番目のインデックスは言及したすべてのクエリをカバーし、クエリオプティマイザーは(投稿したプランに基づいて)クエリプランを構築するときにもそれを確認します。

質問2の回答:

2つの追加のインデックスキー(InstanceId and AddressType)が追加されたインデックスに既に多くのデータがあるため、常に3番目のインデックスを使用しています。これにより、SQLは、クエリを満たすためにInstanceIdおよびAddressTypeを主キー(実行プランのキールックアップ部分)からプルする必要がなくなります。

最初の2つのインデックスを削除し、クエリで要求されている他の列をカバーするためにインクルード列を使用して3番目のインデックスを再構築することをお勧めします

Create index IX_Address_profile_instance_addresstype 
on dbo.address  (ProfileId, InstanceId, AddressType) 
include(<put in the remaining columns comma delimited>) 
with (drop_existing=on,sort_in_tempdb=on)

これはクエリに役立ち、クエリプランからキー参照を削除する必要があります。

これらの変更後にロックが低下するかどうかを確認します。低下しない場合は、さらに深く掘り下げることができます。


私はあなたがお勧めしたことをしました、そしてそれ以上のキー検索はありません。私はロックを監視しています..これらのカウントについてはまだ説明が必要です。行ロック待機:484; 合計時間:59分。平均継続時間:7秒。ページロック待機:5; 合計時間:11秒。平均継続時間:2秒。ロックのエスカレーションの試行:36,949; 実際のエスカレーション:0.
sebeid

@sebeidアドレステーブルで挿入/更新/削除が行われたときに、他のテーブルも同じバッチリクエストによって変更されていますか?もしそうなら、バッチはすべての変更ステートメントのトランザクションをバッチで明示的に開始し、バッチの最後でのみコミットまたはロールバックしますか?
アーロン

わからない。どこからこの情報を入手できるか。ありがとう
sebeid

2
@sebeidすべてがhibernateから生成されたステートメントである場合、それが最も簡単なアプローチであると開発者に尋ねます。そうでない場合は、拡張イベントをトレースまたはセットアップして、呼び出しをトラップしてトラップし、何が入っているのかを確認する必要があります。バッチステートメント。拡張イベント プロファイラーの例
アーロン

3

ない規定の問題が、より良いクエリとのより良い問い合わせ計画を得ることができます
あなたはどこで左の外側を殺している
profiledmo1_.Id=@P0がに参加することを変わるところ

最初の2つだけのインデックス

select addressdmo0_.Id as Id1_20_
     , ...
     , addressdmo0_.Zip as Zip14_20_ 
  from dbo.Address addressdmo0_ 
  join dbo.Profile profiledmo1_ 
    on addressdmo0_.ProfileId = profiledmo1_.Id 
   and profiledmo1_.Id = @P0 
   and addressdmo0_.InstanceId = @P1

参加することは、それがプロファイルにあることを確認することだけですが、プロファイルから何も報告し
ておらず、それはどうですか?

select addressdmo0_.Id as Id1_20_
     , ...
     , addressdmo0_.Zip as Zip14_20_ 
  from dbo.Address addressdmo0_ 
 where addressdmo0_.ProfileId  = @P0 
   and addressdmo0_.InstanceId = @P1

2

インデックス3には必要なすべての情報(列)が含まれているため、インデックス1と2を削除できるようです。別のインデックスが、主キーを表すクラスター化インデックスとして理にかなっている可能性があります。

この限られた情報から、私たちは推測することができます。さらにヒントが必要な場合は、完全なテーブル構造(テーブル、インデックス、キーなど)、クエリ、実行計画などの詳細情報を投稿してください。


1
または、主キーを表さないクラスター化インデックス。これら2つは互いに密接に関連していることが多く、主キーはデフォルトでクラスターとして作成されますが、同じものではありません(同じである必要はありません)。
アーロンバートランド

もちろんそうです。:-)
Josh Alvo、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.