6

SQL Serverデータベース(2005および2008)であるレガシーデータベースがあります。

テーブル内のすべての主キーはUniqueIdentifiersです。

現在、テーブルにはクラスター化インデックスが作成されておらず、75万レコードしかないテーブルでパフォーマンスの問題が発生しています。これは私が唯一の主キーとして一意の識別子を使用して作業した最初のデータベースであり、SQLサーバーがデータを返すのにこれほど遅いのを見たことがありません。

一意の識別子にクラスター化されたインデックスを作成したくないのは、それらがシーケンシャルではないため、データの挿入に関してアプリの速度が低下するためです。

リモートサイトレコードのID管理の目的で使用されているため、uniqueidentifierを削除することはできません。

テーブルに大きな整数のID列を追加し、この列にクラスター化インデックスを作成し、一意のID列を含めることを考えていました。

すなわち

intidentity-挿入速度を維持する最初の列一意の識別子-アプリケーションが期待どおりに動作し続けることを保証します。

目標は、IDクエリと結合テーブルクエリのパフォーマンスを向上させることです。

Q1:これにより、データベースのクエリパフォーマンスが向上しますか、それとも遅くなりますか?

Q2:私がリストしていないこれに代わるものはありますか?

ありがとうピート

編集: パフォーマンスの問題は、特に「トランザクション/変更」テーブルのいくつかが一緒に結合されている場合、selectステートメントを介してデータをすばやく取得することです。

編集2:テーブル間の結合は、通常、すべて主キーと外部キーの間です。外部キーを持つテーブルの場合、よりカバーするインデックスを提供するために、非クラスター化インデックスに含まれます。

すべてのテーブルには、適切なクラスター化インデックスを提供する他の値はありません。

高負荷の各テーブルにID列を追加し、クラスター化インデックス内に現在のGuid PK列を含めて、最高のクエリパフォーマンスを提供することに傾倒しています。

編集3:クエリの80%は、データアクセスメカニズムを介して主キーと外部キーのみで実行されると推定します。通常、データモデルには、アクセス時にクエリを実行する遅延読み込みオブジェクトがあります。これらのクエリは、オブジェクトIDとPK列を使用します。タイプXの基準に基づくフィルターとして外部キー列を使用する、ユーザー主導のデータ除外/包含クエリが大量にあり、次のIDを除外します。残りの20%は、列挙型(int)列または日付範囲列のwhere句であり、システムで実行されるテキストベースのクエリはごくわずかです。

可能であれば、最も重いクエリをカバーするためにカバーインデックスをすでに追加しましたが、それでもパフォーマンスには失望しています。bluefootedが言うように、データはヒープとして保存されています。

4

4 に答える 4

4

テーブルにクラスター化インデックスがない場合は、bツリーではなくヒープとして格納されます。SQL Serverではヒープデータアクセスは絶対にひどいので、クラスター化インデックスを追加する必要があります。

特にNEWSEQUENTIALID()を使用する機能がないため、GUID列はクラスタリングには不適切であるという分析に同意します。必要に応じて新しい人工整数キーを作成できますが、クラスター化インデックスとして意味のある別の列または列の組み合わせがある場合は、それでも問題ありません。

範囲スキャンに頻繁に使用されるフィールドはありますか?結合に使用される列はどれですか?GUID以外の行を一意に識別する列の組み合わせはありますか?データモデルのサンプルを投稿すると、クラスタリングの適切な候補を提案するのに役立ちます。

于 2010-08-21T02:13:59.733 に答える
2

GUIDがどこから来たのかはわかりませんが、GUIDが挿入中に生成されている場合は、SQL ServerでNEWID()の代わりにNEWSEQUENTIALID()を使用すると、挿入中の断片化の問題を回避できます。

クラスター化されたインデックスの選択に関して、キンバリーL.トリップはここで次のように述べています。INTまたはBIGINTと比較した場合、GUIDは狭い要件を満たしていません。

Kimberlyには、主キーおよび/またはクラスタリングキーとしてのGUIDに関する優れた記事もあります。

于 2010-08-20T21:31:04.870 に答える
1

私には100%明確ではありません:GUIDまたは他の列によってテーブルをクエリするためのあなたの一番のアクセスパターンはありますか?また、他のテーブルに結合する場合、どの列(およびデータ型)が最も頻繁に使用されますか?

これらのGUIDがどのように使用されているかを理解するまで、確かな推奨事項を提供することはできません。それらが主キーであるとおっしゃっていたと思いますが、それはクエリまたは結合の主条件として使用されることを保証するものではありません。

アップデート

もう少し知ったので、私はクレイジーな提案があります。これらのテーブルをGUIDでクラスター化しますが、フィルファクターを60%に設定します。これにより、ページ分割の問題が改善され、これらの子犬に対するクエリのパフォーマンスが向上します。

Guid.NewGuid()の使用に関しては、結局C#で順次GUIDを実行できるようです。私はここSOで次のコードを見つけました:

[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);

public static Guid SequentialGuid()
{
    const int RPC_S_OK = 0;
    Guid g;
    if (UuidCreateSequential(out g) != RPC_S_OK)
        return Guid.NewGuid();
    else
        return g;
}

newsequentialID()は、実際にはUuidCreateSequentialの単なるラッパーです。これをクライアントで直接使用できない場合は、サーバーにすばやくラウンドトリップして、そこから新しいシーケンシャルIDを取得する方法を見つけることができると確信しています。おそらく、「ディスペンサー」テーブルとジョブを実行するためのストアドプロシージャ。

于 2010-08-21T02:57:07.387 に答える
0

パフォーマンスの問題が何であるかを示すものではありません。パフォーマンスが最も悪いアクションがINSERTである場合は、ソリューションが正しい可能性があります。それが他の何かであるなら、私はクラスター化されたインデックスがそれをどのように助けることができるかを見るでしょう。

テーブル上の既存のインデックスとそれらを使用するクエリを確認できます。INSERTをわずかに低下させながら、現在のパフォーマンスの問題領域に大きなメリットをもたらすインデックスを選択できる場合があります。

于 2010-08-20T21:44:31.870 に答える