6

次の列に複数列の b ツリー インデックスを持つ非常に単純な db スキーマがあります。

PersonId, Amount, Commission

ここで、次のクエリでテーブルを選択しようとすると:

explain select * from "Order" where "PersonId" = 2 AND "Commission" > 3

Pg はインデックスをスキャンしており、クエリは非常に高速ですが、次のクエリを試してみると:

explain select * from "Order" where "PersonId" > 2 AND "Commission" > 3

インデックスが存在する場合でも、順次スキャンを実行します。このクエでも

explain select * from "Order" where "Commission" > 3 

順次スキャンを行います。理由を説明したい人はいますか?:-)

どうもありがとうございました。

アップデート

テーブルには 1 億行が含まれています。MS SQL に対する PostgreSQL のパフォーマンスをテストするためだけに作成しました。テーブルはすでに VACUUMED です。Core I5 2500k クアッド コア CPU と 8 GB の RAM を実行しています。

このクエリの Explain Analyze の結果は次のとおりです。

explain ANALYZE select * from "Order" where "Commission" BETWEEN 3000000 AND 3000010  LIMIT 20 


Limit  (cost=0.00..2218328.00 rows=1 width=24) (actual time=28043.249..28043.249 rows=0 loops=1)
  ->  Seq Scan on "Order"  (cost=0.00..2218328.00 rows=1 width=24) (actual time=28043.247..28043.247 rows=0 loops=1)
        Filter: (("Commission" >= 3000000::numeric) AND ("Commission" <= 3000010::numeric))
Total runtime: 28043.278 ms
4

1 に答える 1

9

簡単に言えば、利用可能なさまざまなプランを比較すると、構成したコスト要素と利用可能な最新の統計に基づいて、シーケンシャル スキャンが最も高速であると予想されます。あなたが提供したわずかな情報から、プランナーが正しい選択をした可能性が非常に高いようです. 3 つの単一列インデックスがある場合、特に選択する行がテーブル内の行の約 10% 未満である場合は、ビットマップ インデックス スキャンを使用できる可能性があります。

記述したインデックスを使用すると、インデックス全体をすべての行からスキャンする必要があることに注意してください"PersonId" > 2。多くの負の値がない限り"PersonId"、テーブルのほとんどになる可能性が非常に高くなります。

また、小さなテーブル (数千行以下など) がある場合、インデックスを介して行にアクセスしても、それらの数行をスキャンするよりも高速になることはめったにないことに注意してください。プランはデータ ボリュームの影響を受けやすく、行数が少ない場合のプランが、行数が多い場合のプランと同じになる可能性はほとんどありません。

実際、最速の計画を選択していない場合は、コスト要因を調整して、マシンのコストをより適切にモデル化する必要がある可能性が高くなります。もう 1 つの可能性は、自動バキューム設定をより積極的に行って、最新の統計が利用可能であることを確認する必要があるか、より細かい統計の収集を構成する必要がある場合です。

EXPLAIN ANALYZEテーブルの説明 (インデックスを含む)、クエリの出力、およびハードウェアの説明を示すと、より具体的なアドバイスを提供できるようになります。

于 2012-05-13T19:43:15.763 に答える