1. ホーム
  2. sql-server

[解決済み] GUIDを主キーとして使用する場合のベストプラクティス、特にパフォーマンスに関して教えてください。[クローズド]。

2022-03-24 06:57:30

質問

私は、ほとんどのテーブルでGUIDを主キーとして使用しているアプリケーションを持っていますが、GUIDを主キーとして使用する場合、パフォーマンスに関する問題があると読んだことがあります。正直なところ、私は何の問題も見ていませんが、新しいアプリケーションを始めようとしていて、まだGUIDを主キーとして使いたいのですが、複合主キー(GUIDと多分別のフィールド)を使おうと思っていました。

GUIDを使用しているのは、本番環境、テスト環境、開発環境など異なる環境がある場合や、データベース間のデータ移行を行う場合に、管理がしやすいからです。

私はEntity Framework 4.3を使用し、データベースに挿入する前に、アプリケーションコードでGuidを割り当てたいと思っています。(すなわち、私はSQLにGuidを生成させたくありません)。

GUIDベースの主キーを作成する際のベストプラクティスは何ですか?このアプローチに関連すると思われるパフォーマンスの低下を避けるには?

どのように解決するのですか?

GUIDはプライマリキーとして自然な選択と思われるかもしれません。しかし、私が強くお勧めするのは しないこと は、GUIDカラムを クラスタリングキー SQL Serverはデフォルトでそうなっています。

本当に2つの問題を分けて考える必要があるんですね。

  1. その 主キー は論理的な構成要素で、テーブル内のすべての行を一意的かつ確実に識別するためのキーの候補のひとつです。これは、どんなものでもよいのです。 INT , a GUID 文字列 - シナリオに最も適したものを選んでください。

  2. その クラスタリングキー (テーブル上の "クラスタ化インデックス" を定義するカラム) - これは 物理的 ストレージに関連するもので、ここでは、小さくて安定した、増え続けるデータ型が最適です - 。 INT または BIGINT をデフォルトのオプションに設定します。

デフォルトでは、SQL Serverテーブルの主キーはクラスタリングキーとしても使用されますが、そうである必要はありません。GUIDベースのプライマリ/クラスタキーを2つのキーに分割し、プライマリ(論理)キーはGUIDで、クラスタリング(順序)キーは別個の INT IDENTITY(1,1) カラムを使用します。

として キンバリー・トリップ - は、「インデックスの女王」をはじめ、多くの人が何度も述べています。 GUID なぜなら、そのランダム性により、ページやインデックスの断片化を引き起こし、一般にパフォーマンスが低下するからです。

そうなんです。 newsequentialid() SQL Server 2005 以降のバージョンでは、完全なシーケンシャルではありません。 GUID - が、ちょっとだけ目立たなくなりました。

テーブルのクラスタリングキーは、テーブル上の非クラスタリングインデックスの各エントリに追加されるため、できるだけ小さくする必要があります。一般に INT は20億行以上あれば、ほとんどのテーブルで十分なはずです。 GUID をクラスタリングのキーとして使用することで、ディスクとサーバーのメモリに数百メガバイトのストレージを節約することができます。

簡単な計算 INT vs. GUID を主キーとクラスタリングキーとして使用します。

  • 1,000,000行のベーステーブル(3.8MB vs. 15.26MB)
  • 6つの非クラスタ化インデックス (22.89 MB vs. 91.55 MB)

TOTAL: 25 MB vs. 106 MB - しかも、これはたった1つのテーブルの上での話です。

キンバリー・トリップの素晴らしい文章を読んで、もう一度読んで、消化してください。これはSQL Serverのインデックス作成に関する福音書です。

追記:もちろん、数百行や数千行を扱うだけであれば、これらの議論のほとんどはあまり影響を及ぼさないでしょう。しかし、数万行、数十万行になると、あるいは数百万行になると......。 では これらの点は、非常に重要であり、理解することが非常に重要になります。

アップデートしてください。 を使用したい場合は PKGUID カラムを主キー (ただしクラスタリングキーではない) とし、別のカラムである MYINT ( INT IDENTITY ) をクラスタリングキーとして使用します。

CREATE TABLE dbo.MyTable
(PKGUID UNIQUEIDENTIFIER NOT NULL,
 MyINT INT IDENTITY(1,1) NOT NULL,
 .... add more columns as needed ...... )

ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable
PRIMARY KEY NONCLUSTERED (PKGUID)

CREATE UNIQUE CLUSTERED INDEX CIX_MyTable ON dbo.MyTable(MyINT)

基本的に:ただ、あなたは 明示的に を伝えると PRIMARY KEY という制約があります。 NONCLUSTERED (として定義されたインデックスを作成します(そうしないと、デフォルトでクラスタ化インデックスとして作成されます)。 CLUSTERED

この方法は、既存のシステムのパフォーマンスを向上させるためのリエンジニアリングが必要な場合に有効なオプションとなります。新しいシステムで、ゼロから始める場合、そしてレプリケーションのシナリオでない場合、私は常に以下を選びます。 ID INT IDENTITY(1,1) をクラスタ化された主キーとして使用します。