8

私はint型でbtreeインデックスを持つカラムcを持つテーブルtを持っています。PostgreSQL:この単純なクエリでインデックスが使用されないのはなぜですか?

次のクエリでこのインデックスが使用されないのはなぜですか?

explain select c from t group by c; 

私が得る結果は次のとおりです。

HashAggregate (cost=1005817.55..1005817.71 rows=16 width=4) 
    -> Seq Scan on t (cost=0.00..946059.84 rows=23903084 width=4) 

インデックスの私の理解は限られているが、私は、このようなクエリはインデックスの目的と思っていました。

答えて

4

クエリでは必ずインデックスを使用できます。あなたの特定のケースでそうでない理由は、データの特定のサイズと分布に依存します。調べるにはSET enable_seqscan TO offを使用できます。

+2

インデックスを使用しないとどのような状況で報われないのでしょうか?私は、この例のサイズについて話しているときには、少なくともディストリビューションを想像することはできません。 – David

+0

@David:全インデックススキャンは、テーブルの順次スキャンよりもはるかに高価です。インデックスは通常、テーブルの小さなサブセットを選択した場合にのみ有効です。 –

+1

これは間違っています。 'SELECT DISTINCT x FROM t;'のようなクエリは '(x)'にインデックスを使うことができます。索引全体を読むことは、表全体を読むことよりも安価でなければなりません。しかし、Postgresは私が知っている限りでは実装していません。[Loose Indexスキャン](https://wiki.postgresql.org/wiki/Loose_indexscan) –

3

テーブル全体をスキャンする必要があるため、インデックスを介して行うことは効果がありません。 ( "Covering indices"は、MVCC実装のためにPostgreSQLのパフォーマンステクニックとしては役に立たない)。

+0

PostgreSQL 9.2には、インデックスのみのスキャンが付属しています:http://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.2#Index-only_scans – qerub

5

このクエリは、ルースインデックススキャンと呼ばれる最適化を使用して実行できます。しかし、PostgreSQLはまだこの最適化を実装していないので、代わりにテーブルスキャンを使用します。

私が知っている限り、主要なデータベースのうち、MySQL has implemented loose index scan(たぶんオラクル?)だけです。 PostgreSQL hasn'tはこの機能を実装しました。

+0

Postgresqlのアーキテクチャは、現在でもテーブルを使用していますインデックス。それはとにかくすべての行を打つ必要があるときははるかに高価です。私はmysqlでエンジンが適切に動作するようにインデックスをカバーする必要があると仮定していますが、mysqlについてよく分かりません。 –

+3

@Scott Marlowe:しかし、主なポイントは、ゆるいインデックススキャンを使用することができれば、すべての行にヒットする必要はないということです。このため、MySQLは、PostgreSQLよりも数百倍または数千倍高速です(非常に大きなテーブルでは、 'c'の値が非常に少ないため)。これは、スキーマ設計の単純な変更(新しいテーブルの導入)が問題を解決するため、優先度の低い機能リクエストです。 –

+1

*インデックスのみスキャン*とも呼ばれ、Oracle、SQL Server、およびDB2もこれを実装します。しかし、何千倍も高速にクエリを作成することは疑問です。早く、はい。しかし、それほど大きなものではありません(しかし、Postgresにはそれがないのは本当に残念です)。 –

関連する問題