質問

私は、順次GUIDが通常のGUIDよりも優れたパフォーマンスを理解しようとしています。

それは、通常のGUIDを使用すると、インデックスがGUIDの最後のバイトを使用してソートするためですか?ランダムなので、新しいデータを挿入するためにデータを別のページに移動することが多いため、断片化とページの分割がたくさんありますか?

シーケンシャルガイドサインそれは、ページの分割と断片化を大いに減らします。

私の理解は正しいですか?

誰かがこのテーマにもっと光を当てることができれば、とても感謝しています。

ありがとうございました

編集:

シーケンシャルGUID = newSequentionID()、

通常のguid = newid()

役に立ちましたか?

解決

あなたはあなたの質問でそれをすべて言った。

シーケンシャルGUID /プライマリキーを使用すると、テーブルの端に新しい行が一緒に追加され、SQLサーバーにとって簡単になります。比較すると、ランダムなプライマリキーは、新しいレコードをテーブルのどこにでも挿入できることを意味します - テーブルがキャッシュにある最後のページの可能性はかなりありそうです(それがすべての読み取りが進んでいる場合)が、キャッシュ内にあるテーブルの中央にあるランダムなページはかなり低いため、追加のIOが必要です。

その上、テーブルの中央に行を挿入すると、余分な列を挿入するのに十分なスペースがない可能性があります。この場合、SQL Serverはレコードの余地を作成するために追加の高価なIO操作を実行する必要があります。これを回避する唯一の方法は、データの間にギャップが散らばっており、追加のレコードを挿入できるようにすることです(充填要因)、それ自体がパフォーマンスの問題を引き起こします。これは、データがより多くのページに広がっているため、テーブル全体にアクセスするためにより多くのIOが必要です。

他のヒント

私はこのトピックに関するキンバリー・L・トリップの知恵に延期します。

しかし、クライアントで生成された値(.NETを使用)またはnewID()関数によって(SQL Serverで)生成されるようなシーケンシャルではないガイドは、主に恐ろしく悪い選択です - 主に断片化のために、ベーステーブルで作成されますが、サイズのためにも作成されます。それは不必要に幅が広いです(INTベースのIDの4倍です。これにより、20億(実際、40億)のユニークな列を提供できます)。また、20億以上が必要な場合は、いつでもBigint(8バイトINT)を使用して263-1列を取得できます。

続きを読む: http://www.sqlskills.com/blogs/kimberly/post/guids-as-s-primary-keys-andor-the-clustering-key.aspx#ixzz0wdk6cee

全体像を視覚化します utilという名前 オストレス 使用される可能性があります。たとえば、2つのテーブルを作成できます 正常 PKとしてのGUID、シーケンシャルガイドを備えた別のGUID:

-- normal one
CREATE TABLE dbo.YourTable(
   [id] [uniqueidentifier] NOT NULL,
   CONSTRAINT [PK_YourTable] PRIMARY KEY NONCLUSTERED (id)
);
-- sequential one
CREATE TABLE dbo.YourTableSeq(
   [id] [uniqueidentifier] NOT NULL CONSTRAINT [df_yourtable_id]  DEFAULT (newsequentialid()),
   CONSTRAINT [PK_YourTableSeq] PRIMARY KEY NONCLUSTERED (id)
);

次に、特定のユーティを使用すると、インデックスの断片化に関する統計を選択した挿入物を数回実行します。

ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTable VALUES (NEWID()); SELECT count(*) AS Cnt FROM dbo.YourTable; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTable';" -oE:\incoming\TMP\ -n1 -r10000

ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTableSeq DEFAULT VALUES; SELECT count(*) AS Cnt FROM dbo.YourTableSeq; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTableSeq';" -oE:\incoming\TMP\ -n1 -r10000

次に、ファイルe: encoming tmp query.outで統計が見つかります。私の結果は次のとおりです。

"Normal" GUID:
Records    AvgPageFragmentation     PageCounts           
---------------------------------------------- 
1000       87.5                     8                    
2000       93.75                    16                   
3000       96.15384615384616        26                   
4000       96.875                   32                   
5000       96.969696969696969       33                   
10000      98.571428571428584       70                   


Sequential GUID:
Records    AvgPageFragmentation     PageCounts           
---------------------------------------------- 
1000       83.333333333333343       6                    
2000       63.636363636363633       11                   
3000       41.17647058823529        17                   
4000       31.818181818181817       22                   
5000       25.0                     28                   
10000      12.727272727272727       55       

挿入された順次GUIDが挿入されていることでわかるように、挿入操作が新しいページの割り当てがまったくなくなるため、インデックスはそれほど断片化されていません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top