SQL主キーとインデックス


106

データベースにID行(int)が主キーとして設定されているとしましょう。IDを照会することが多い場合は、IDにインデックスを付ける必要がありますか?または、それが主キーであることは、すでに索引付けされていることを意味しますか?

私が尋ねる理由は、MS SQL ServerではこのIDにインデックスを作成できるためです。これは、前述のとおり、これが私の主キーです。

編集:追加の質問-主キーをさらにインデックス化することは害を及ぼしますか?

回答:


72

そうです、SQL Serverでは同じフィールドに重複したインデックスを作成できるので混乱しています。しかし、別のものを作成できるという事実は、PKインデックスもまだ存在していないことを示しているわけではありません。

追加のインデックスは役に立ちませんが、唯一の害(非常に小さい)は追加のファイルサイズと行作成のオーバーヘッドです。


39
未使用のインデックスの損傷は確かに非常に有害です。一つには、インデックスはストレージを消費します。また、書き込みと更新が遅くなります。使用しないインデックスは必ず削除してください。
パセリエ2012

50

他の誰もがすでに言ったように、主キーには自動的にインデックスが付けられます。

主キー列に追加のインデックスを作成することは、主キーと他の特定の列を使用するクエリを最適化する必要がある場合にのみ意味があります。主キー列に別のインデックスを作成し、それを他のいくつかの列に含めることにより、クエリに必要な最適化を実現できます。

たとえば、多くの列を持つテーブルがありますが、クエリするのはID、名前、住所の列だけです。IDを主キーとして、IDに基づいて作成され、Name列とAddress列を含む次のインデックスを作成できます。

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

したがって、このクエリを使用する場合:

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Serverは、作成したインデックスのみを使用して結果を提供し、実際のテーブルからは何も読み取りません。


28

注:この回答は、エンタープライズクラスの大規模開発に対応しています。

これはSQL ServerだけでなくRDBMSの問題であり、その動作は非常に興味深いものになる可能性があります。1つは、主キーが自動的に(一意に)インデックス付けされることは一般的ですが、絶対的なものではありません。 主キーを一意にインデックス付けしないことが不可欠な場合があります。

ほとんどのRDBMSでは、一意のインデックスがまだ存在しない場合は、主キーに自動的に作成されます。したがって、主キーとして宣言する前に、主キー列に独自のインデックスを作成できます。その後、主キー宣言を適用するときに、データベースエンジンはそのインデックスを使用します(受け入れ可能な場合)。多くの場合、主キーを作成して、そのデフォルトの一意のインデックスを作成し、その列に独自の代替インデックスを作成して、デフォルトのインデックスを削除できます。

ここでおもしろいことに、一意の主キーインデックスが必要ないのはいつですか?テーブルが十分なデータ(行)を取得してインデックスのメンテナンスにコストがかかりすぎる場合は、1つは必要なく、1つは許容できません。これは、ハードウェア、RDBMSエンジン、テーブルとデータベースの特性、およびシステム負荷によって異なります。ただし、通常は、テーブルが数百万行に達すると表示され始めます。

重要な問題は、行の挿入または主キー列の更新のたびに、一意性を確保するためのインデックススキャンが発生することです。その一意のインデックススキャン(またはRDBMSでの同等のスキャン)は、テーブルのパフォーマンスを支配するまで、テーブルが大きくなるにつれてはるかに高価になります。

20億行ものテーブル、8 TBのストレージ、1日あたり4,000万行の挿入で、この問題に何度も対処しました。一意の主キーインデックスを実際にステップ1として削除することを含む、関連するシステムを再設計する必要がありました。実際、本番環境では、再設計に近づく前に、停止から回復するためだけにそのインデックスを削除する必要がありました。その再設計には、主キーの一意性を確保し、データへの迅速なアクセスを提供する他の方法を見つけることが含まれていました。


キーがintまたはbigintの自動インクリメントキーである場合はどうなりますか?この場合、SQL Serverは一意のインデックススキャンを実行しないほどスマートですか?
キルブレーカー、2013年

1
@quillbreaker:IDENTITYフィールドが一意であるとは限りません。結局のところ、ユーザーはを使用してIDENTITY_INSERTいる場合、重複する値を挿入できます。

私はこれが古いトピックであることを知っていますが、1つのインデックスの一意性スキャンがどのようにシステムにかかる負荷になるかはわかりません。B +ツリースキャンはO(log n)* vである必要があります。ここで、vはインデックスの断片化、不完全なツリーバランスなどの制約されたオーバーヘッドです。したがって、20億行は2,000,000,000(約31シーク)回のログベース2になります。 2または3または10です。1日あたり4,000万回の挿入は約462 /秒、1回の挿入あたり約100 IOです...ああ...ああ。そうですか。そして、これはSSDが普及する前のことでした。
Charles Burns

一意性制約を削除しない限り、一意性について各行をチェックするオーバーヘッドははるかに大きくなりませんか?
Max Candocia 2017年

20

主キーには、デフォルトで常にインデックスが付けられます。

SQL Server Management StudioまたはTransact-SQLを使用して、SQL Server 2012で主キーを定義できます。主キーを作成すると、対応する一意のクラスター化インデックスまたは非クラスター化インデックスが自動的に作成されます。

http://technet.microsoft.com/en-us/library/ms189039.aspx


9

ここからMSDNからの一節:

テーブルにPRIMARY KEY制約を指定すると、データベースエンジンは、主キー列に一意のインデックスを作成することにより、データの一意性を適用します。このインデックスにより、クエリで主キーが使用されているときにデータへの高速アクセスも可能になります。したがって、選択する主キーは、一意のインデックスを作成するためのルールに従う必要があります。


8

非クラスター化を指定しない限り、PKはクラスター化インデックスになります


3

PRIMARY KEYor UNIQUE制約を宣言すると、SQL Serverが自動的にインデックスを作成します。

一意のインデックスは制約に一致せずに作成できますが、一意のインデックスがなければ制約(主キーまたは一意)は存在できません。

ここから、制約を作成すると、次のことが行われます。

  • 同じ名前のインデックスを作成します
  • 作成されたインデックスがないと制約が存在することはできないため、作成されたインデックスの削除を拒否します

同時に、制約を削除すると、関連するインデックスも削除されます。

だから、間の実際の差があるPRIMARY KEYかはUNIQUE INDEX

  • NULL値はでは許可されていませんPRIMARY KEYが、UNIQUEインデックスでは許可されています。そして、セット演算子(UNION、EXCEPT、INTERSECT)と同様に、ここNULL = NULLでは、2つNULLのがお互いの重複として検出されるため、1つの値しか持てないことを意味します。
  • PRIMARY KEYテーブルごとに1つしか存在できませんが、999の一意のインデックスを作成できます
  • PRIMARY KEYの制約が作成されたクラスタ化されたとしてそこにクラスタ化インデックスは、テーブルの上にすでにあるかない限り、それが作成されNONCLUSTERED、その定義に使用されています。ときUNIQUE、インデックスが作成されると、それが作成されNONCLUSTERED、あることが特定されていない場合を除きCLUSTEREDまだ存在していないと、このような。

2

これを主キーにすると、そのインデックスも自動的に作成されます。


1

SQL Serverでは、通常、主キーに自動的にインデックスが作成されます。これは事実ですが、クエリの高速化は保証されていません。主キーは、主キーとして1つのフィールドしかない場合に優れたパフォーマンスを提供します。ただし、主キーとして複数のフィールドがある場合、インデックスはそれらのフィールドに基づいています。

例:フィールドA、B、Cが主キーであるため、WHERE CLAUSEの3つのフィールドに基づいてクエリを実行するとパフォーマンスは良好ですが、WHERE CLAUSEにCフィールドのみを使用してクエリを実行する場合は、良いパフォーマンスが得られません。したがって、パフォーマンスを向上させるには、Cフィールドに手動でインデックスを付ける必要があります。

ほとんどの場合、100万件を超えるレコードにヒットするまで、問題は発生しません。


0

(個別の)インデックスのない巨大なデータベースがあります。

主キーでクエリを実行するときはいつでも、すべての集中的な目的で結果が即座に得られます。


PKは、クラスタ化インデックス、クエリプランを見ているためです
SQLMenace

0

主キーには自動的にインデックスが付けられます

使い方に応じてpkを使用して追加のインデックスを作成できます

  • インデックスzip_code、idは、zip_codeとidで頻繁に選択する場合に役立ちます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.