37

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

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

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

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

4

9 に答える 9

35

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

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

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

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

于 2008-11-10T11:17:40.680 に答える
26

ほとんどの場合、データベース内のすべてのテーブルにクラスター化インデックスを作成する必要があります。テーブルにクラスター化インデックスがない場合、それは「ヒープ」と呼ばれるものであり、ほとんどの種類の一般的なクエリのパフォーマンスは、クラスター化インデックス テーブルよりもヒープの方が低くなります

クラスター化インデックスを確立する必要があるフィールドは、テーブル自体と、テーブルに対するクエリの予想される使用パターンによって異なります。ほとんどの場合、クラスター化インデックスを一意の列または列の組み合わせ (代替キー) に配置する必要があります。そうでない場合、SQL は一意の値を末尾に追加します。とにかく選択したフィールド。テーブルに複数のレコードを選択またはフィルター処理するためにクエリで頻繁に使用される 1 つまたは複数の列がある場合 (たとえば、テーブルに販売トランザクションが含まれていて、アプリケーションが製品 ID ごとに販売トランザクションを頻繁に要求する場合、またはさらに良い場合は、請求書の詳細テーブル。ほとんどの場合、特定の請求書のすべての詳細レコードを取得します。

これらの列は、クラスター化インデックスの候補です。クラスター化インデックスの列の順序は重要です。インデックスで定義された最初の列は、予想されるクエリで最初に選択またはフィルター処理される列である必要があります。

このすべての理由は、データベース インデックスの内部構造を理解することに基づいています。これらのインデックスは、バランス ツリー (B ツリー) インデックスと呼ばれます。二分木に似ていますが、ツリー内の各ノードは、2 つではなく、任意の数のエントリ (および子ノード) を持つことができます。クラスター化インデックスの違いは、クラスター化インデックスのリーフ ノードが、テーブル自体の実際の物理ディスク データ ページであることです。一方、非クラスター化インデックスのリーフ ノードは、テーブルのデータ ページを単に "ポイント" します。

したがって、テーブルにクラスター化されたインデックスがある場合、テーブルのデータ ページはそのインデックスのリーフ レベルであり、それぞれがインデックス順で前のページと次のページへのポインターを持ちます (それらは二重リンク リストを形成します)。 .

したがって、クエリがクラスター化インデックスと同じ順序の行の範囲を要求する場合...プロセッサは、データの開始ページを見つけるためにインデックスを 1 回 (または 2 回) 走査するだけで済みます。必要なすべてのデータ ページを読み取るまで、次のページと次のページに移動するリンク リスト ポインター。

非クラスター化インデックスの場合、取得する行ごとに 1 回インデックスをトラバースする必要があります...

注: 編集
Guid キー列のシーケンシャルの問題に対処するには、SQL2k5 には NEWSEQUENTIALID() があり、実際には「古い」シーケンシャルな方法で Guid を生成することに注意してください。

または、クライアント側コードに実装されている Jimmy Nielsens COMB GUID アルゴリズムを調べることができます。

COMBガイド

于 2008-11-10T14:58:51.560 に答える
9

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

ただし、整数ベースのクラスター化インデックスでは、整数は通常 ( IDENTITYspec のように) 連続しているため、最後に追加されるだけで、データを移動する必要はありません。

一方、クラスター化されたインデックスは、GUID では常に悪いわけではありません...それはすべて、アプリケーションのニーズに依存します。迅速に記録できるようにする必要がある場合SELECTは、クラスター化インデックスを使用してください...INSERT速度は低下しますが、SELECT速度は向上します。

于 2008-11-10T11:12:14.093 に答える
5

通常、GUID でクラスタリングすることはお勧めできませんが、状況によっては、非クラスター化インデックスでも GUID が断片化を引き起こす可能性があることに注意してください。

SQL Server 2005 を使用している場合、newsequentialid()関数は連続した GUID を生成することに注意してください。これにより、断片化の問題を防ぐことができます。

決定を下す前に、次のような 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;
于 2008-11-10T12:21:46.497 に答える
4

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

于 2008-11-10T11:41:29.197 に答える
3

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

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

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

変更を行います。

そして、あなたが決して知らないので、テストしてください...

于 2008-11-10T12:59:08.310 に答える
1

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

于 2013-01-29T17:53:54.733 に答える
0

はい、上記の Galwegian の理由から、GUID プライマリ キーのクラスター化インデックスを削除する必要があります。アプリケーションでこれを行いました。

于 2008-11-10T11:14:37.427 に答える
0

大量の挿入を行っているか、PK による非常に迅速な検索が必要かによって異なります。

于 2008-11-10T11:16:30.573 に答える