3

同じテーブルに 2 つの同一 (倍精度) の列があり、2 つの同一のインデックスが 2 つの同一のクエリを実行しています。それでも、一方は他方よりもほぼ 10 倍速く実行されます。これは何が原因ですか?

1) SELECT MIN("reports"."longitude") AS min_id FROM "reports" WHERE (area2 = 18)

2) SELECT MIN("reports"."latitude") AS min_id FROM "reports" WHERE (area2 = 18)

28 ミリ秒で 1 回実行、300 ミリ秒以上で 2 回実行

ここに「説明」があります:
1)

Result  (cost=6.07..6.08 rows=1 width=0)"
InitPlan 1 (returns $0)"
  ->  Limit  (cost=0.00..6.07 rows=1 width=8)"
      ->  Index Scan using longitude on reports  (cost=0.00..139617.49 rows=22983 width=8)"
            Index Cond: (longitude IS NOT NULL)"
            Filter: (area2 = 18)"

2)

Result  (cost=5.95..5.96 rows=1 width=0)"
InitPlan 1 (returns $0)"
  ->  Limit  (cost=0.00..5.95 rows=1 width=8)"
      ->  Index Scan using latitude on reports  (cost=0.00..136754.07 rows=22983 width=8)"
            Index Cond: (latitude IS NOT NULL)"
            Filter: (area2 = 18)"

ここで要求されたのは、説明分析の出力です...

1)

Result  (cost=6.07..6.08 rows=1 width=0) (actual time=10.992..10.993 rows=1 loops=1)"
InitPlan 1 (returns $0)"
    ->  Limit  (cost=0.00..6.07 rows=1 width=8) (actual time=10.985..10.986 rows=1 loops=1)"
          ->  Index Scan using longitude on reports  (cost=0.00..139617.49 rows=22983 width=8) (actual time=10.983..10.983 rows=1 loops=1)"
                Index Cond: (longitude IS NOT NULL)"
                Filter: (area2 = 18)"
Total runtime: 11.033 ms"

2)

 Result  (cost=5.95..5.96 rows=1 width=0) (actual time=259.749..259.749 rows=1 loops=1)"
InitPlan 1 (returns $0)"
    ->  Limit  (cost=0.00..5.95 rows=1 width=8) (actual time=259.740..259.740 rows=1 loops=1)"
          ->  Index Scan using latitude on reports  (cost=0.00..136754.07 rows=22983 width=8) (actual time=259.739..259.739 rows=1 loops=1)"
                Index Cond: (latitude IS NOT NULL)"
                Filter: (area2 = 18)"
Total runtime: 259.789 ms"
---------------------

何が起こっている?2 番目のクエリを適切に動作させ、すばやく実行するにはどうすればよいですか? 私が知る限り、両方の設定は同じです。

4

2 に答える 2

3

まず、インデックスがクエリを高速化するという保証はありません。次に、パフォーマンスを考慮する場合、各クエリを複数回実行する必要があります。クエリの長​​さに影響を与える可能性のあるキャッシュへのインデックスの読み込みとページの読み込みにはオーバーヘッドがあります。

私は Postgres の専門家ではありませんが、これについて考えてみると、それほど驚くことではありません。

クエリ プランはインデックスをループして、area2 = 18 に一致する対応する行を見つけ、最初の行で停止することを願っています (インデックスを使用しているため、最小値から開始して上に移動できます)。これは、それがどのように機能しているかについての憶測です。Postgresがこれを正確に行っているかどうかはわかりません。

いずれにせよ、何が起こっているかというと、この領域は緯度インデックスの開始よりも経度インデックスの開始にはるかに近いということです。そのため、最初に一致するレコードが最初に検索されます。この説明が正しければ、データベース内の他のものと比較して、この地域は相対的に西側 (経度が低い) と相対的に北側 (緯度が高い) にあることが示唆されます。

ちなみに、エリアがたくさんあると仮定すると、Area2 にインデックスを付けた方が良い結果が得られるかもしれません。

于 2012-07-11T16:32:32.473 に答える
2

インデックス スキャンを取得していますが、検査されるレコードの数は、条件に一致するためにリストのどこまで行かなければならないかによって異なりますarea2

area2 の分布が異常でない限り、このクエリを最適化するには、 と に複合インデックスを配置する必要が(area2, latitude)あり(area2, longitude)ます。<10ミリ秒になると思います。area2PG は、ビットマップ ヒープ スキャン機能を使用して、複合インデックスの代わりに、別のインデックスを既存のインデックスと組み合わせることもできます。

于 2012-07-11T18:13:17.737 に答える