web-dev-qa-db-ja.com

Guid列のクラスター化インデックスを削除する必要があります

私は通常、主キーとしてGUIDを使用するデータベースに取り組んでいます。

デフォルトでは、SQLServerはクラスター化インデックスを主キー列に配置します。これはGUID列のばかげた考えであり、非クラスター化インデックスの方が優れていることを理解しています。

あなたはどう思いますか-すべてのクラスター化インデックスを取り除き、それらを非クラスター化インデックスに置き換える必要がありますか?

SQLのパフォーマンスチューナーがこれを推奨として提供しないのはなぜですか?

34
cbp

クラスター化インデックスの大きな理由は、特定の列の値の範囲の行を頻繁に取得する場合です。データは物理的にこの順序で配置されているため、行を非常に効率的に抽出できます。

GUIDのようなものは、主キーには優れていますが、挿入に追加のコストがかかり、選択に目に見えるメリットがないため、パフォーマンスにプラスの悪影響を与える可能性があります。

そうです、GUIDでインデックスをクラスター化しないでください。

なぜそれが推奨として提供されないのかについては、チューナーがこの事実を認識していることをお勧めします。

31
Mike Woodhouse

GUIDフィールドのクラスター化インデックスの問題は、GUIDがランダムであるため、新しいレコードを挿入するときに、レコードを挿入するためにディスク上のデータの大部分を移動する必要があることです。テーブルの真ん中。

ただし、整数ベースのクラスター化インデックスでは、整数は通常シーケンシャルであるため(IDENTITY仕様の場合のように)、最後に追加されるだけで、データを移動する必要はありません。

一方、クラスター化インデックスはGUIDで常に悪いとは限りません...それはすべてアプリケーションのニーズに依存します。 SELECTレコードをすばやく実行できるようにする必要がある場合は、クラスター化インデックスを使用します... INSERTの速度は低下しますが、SELECTの速度は向上します。

6
Galwegian

GUIDでのクラスタリングは通常は悪い考えですが、状況によってはGUIDが発生する可能性があることに注意してください 非クラスター化インデックスでも断片化が発生します

SQL Server 2005を使用している場合、 newsequentialid() 関数はsequentialGUIDを生成することに注意してください。これは、断片化の問題を防ぐのに役立ちます。

次のようなSQLクエリを使用して、決定を行う前に断片化を測定することをお勧めします(ANSI以外の構文を使用してください)。

SELECT OBJECT_NAME (ips.[object_id]) AS 'Object Name',
       si.name AS 'Index Name',
       ROUND (ips.avg_fragmentation_in_percent, 2) AS 'Fragmentation',
       ips.page_count AS 'Pages',
       ROUND (ips.avg_page_space_used_in_percent, 2) AS 'Page Density'
FROM sys.dm_db_index_physical_stats 
     (DB_ID ('MyDatabase'), NULL, NULL, NULL, 'DETAILED') ips
CROSS APPLY sys.indexes si
WHERE si.object_id = ips.object_id
AND   si.index_id = ips.index_id
AND   ips.index_level = 0;
5
HTTP 410

NewId()を使用している場合は、NewSequentialId()に切り替えることができます。それは挿入パフォーマンスを助けるはずです。

4
Greg Dean

はい、ランダムな値にクラスター化インデックスを設定しても意味がありません。

おそらく、データベースのどこかにクラスター化インデックスが必要です。たとえば、「Author」テーブルと「Author」への外部キーを持つ「Book」テーブルがあり、アプリケーションに「select ... from Book where AuthorId = ..」というクエリがある場合です。 "、それならあなたは本のセットを読んでいるでしょう。それらの本がディスク上で物理的に隣り合っていると、ディスクヘッドがセクター間を行き来して、その著者のすべての本を収集する必要がないため、より高速になります。

したがって、アプリケーション、つまりデータベースにクエリを実行する方法について考える必要があります。

変更を加えます。

そして、あなたが決して知らないので、テストします...

2
Corey Trager

ほとんどの人が述べているように、クラスター化インデックスでランダムな識別子を使用することは避けてください。クラスタリングのメリットは得られません。実際には、遅延が増加します。それらすべてを取り除くことは確かなアドバイスです。また、newsequentialid()は、マルチマスターレプリケーションシナリオで非常に問題になる可能性があることに注意してください。データベースAとBの両方がレプリケーションの前にnewsequentialid()を呼び出すと、競合が発生します。

1
Daeron Lockett

はい、上記のガルウェジアンの理由により、GUID主キーのクラスター化インデックスを削除する必要があります。これは、アプリケーションで実行しました。

0
alexmac

多くの挿入を行っているかどうか、またはPKによる非常に迅速なルックアップが必要かどうかによって異なります。

0
GeekyMonkey