web-dev-qa-db-ja.com

主キーと外部キーを含むクエリは、主キーのみを含むクエリよりも速く実行されますか?

SELECT something FROM table WHERE primary_key = ?

vs.

SELECT something FROM table WHERE primary_key = ? AND other_key = ?

これがother_keyを含めても結果セットが変更されないシナリオであるとします。 2番目のクエリは実際には高速ですか?または、複数のデータベースが提供されている場合、データベースは単一の最適なキーを使用しますか?

3
rococo

クエリ

SELECT something FROM table WHERE primary_key = ?

これが最速のフォームです。 any他の述語を追加すると、速度が遅くなるだけです。理論的には。

エキゾチック例外が適用されます。たとえば、PKインデックスが何らかの理由で肥大化した場合、PK列が比較的大きい場合、または複数列のPKの場合、インデックスがはるかに大きい一方で、other_keyに追加された述語のインデックスは小さくなります。次に、Postgresは追加された述語のインデックスを使用し、ヒープにアクセスし、primary_key = ?filterにアクセスすることを決定します。可能性は低いですが、可能です。

追加された述語がTRUE以外の値に評価される場合、行は得られません-異なる結果なので、公平な比較は行われませんが、主張したとおりではありません。

FOREIGN KEY制約は、読み取りパフォーマンスに直接影響しません。参照する列は、(参照される列とは対照的に)インデックスを付ける必要さえありません。

最高の読み取りパフォーマンスのためのカバリングインデックス

重要なサイズのテーブルで書き込みアクティビティが多すぎない場合は、(primary_key, something)multicolumn indexを追加してを許可することを検討してくださいインデックスのみのスキャンPostgres 10以前では、少なくとも2つのインデックスが作成されます(追加の書き込み/メンテナンス/スペースコストがかかります)。

  1. 明らかに、(primary_key)のPKインデックス。
  2. (primary_key, something)のプレーン(または冗長なUNIQUE)インデックス。

Postgres 11(現在ベータ版)は真の covering indexを導入しますINCLUDE を追加すると、PRIMARY KEYで非キー列somethingを便乗させることができます。

CREATE TABLE tbl (
   primary_key bigint GENERATED ALWAYS AS IDENTITY
 , other_key   integer NOT NULL REFERENCES other_tbl
 , something   text
 , PRIMARY KEY (primary_key) INCLUDE (something)  -- here's the magic
);

primary_keyother_keyよりもはるかに広い列である場合(bigintintの例のように修飾されない)、その列のインデックスでsomethingを便乗させることもできます。

CREATE INDEX other_idx ON tbl(other_key) INCLUDE (something);

どちらのソリューションでも特定のクエリの読み取りパフォーマンスを最適化できますが、somethingを取得しない他のクエリでは、より大きなインデックスを使用する必要があります。したがって、メリットとコストを比較検討してください(インデックスを作成するときは常にそうです)。

Michael Paquierからの詳細を含む関連ブログエントリ:

3

いいえ、主キーは一意であるため、PKルックアップは単一のレコードを見つけます。したがって、レコードの検索には主キーのみが使用されます。両方のクエリに同じアクセスプランが表示されます。

ほとんどの場合、2つのインデックスの使用は最適ではありません。しかし、最適なインデックスが複数のレコードを見つけた場合、2番目のインデックスを使用してビットマップスキャンを実行できます。

1
Jasen

まず、キーは論理的な概念であり、それ自体はパフォーマンスとはほとんど関係がありません。ただし、一意の制約(主キー)は、私が知っているすべてのDBMSにあり、UNIQUEインデックスを使用して実装されているため、間接的にパフォーマンスに影響を与えます。一部のDBMS(PostgreSQLについては不明)では、FOREIGN KEYSのインデックスが自動的に作成されます。ここでも、FOREIGN KEY自体がSELECTステートメントに与える影響は非常に小さいものです(検証が必要なため、挿入/更新/削除に影響します)。したがって、FOREIGNキーはSELECTのパフォーマンスに間接的に影響を与える可能性があります。

あなたの場合、通常、外部キーインデックスはパフォーマンスに影響しません[1]。行は、主キーによって既に一意に識別されています。これは、私たちが期待できる最高のものです。

[1]通常、主キーインデックスの統計が現実と一致しない場合は、テーブルスキャンを選択できます。この状況では、外部キーの2番目のインデックスがあると役立ちますが、これは考慮すべき事項ではありません。

1
Lennart