1

このクエリがあります

SELECT "items".*
FROM
    "items"
    INNER JOIN
    item_mods ON item_mods.item_id = items.id AND item_mods.mod_id = 15
WHERE (items.league_id = 1) AND (items.item_type_id = 11) AND (num_sockets >= 2)
ORDER BY item_mods.total_value DESC
LIMIT 25

これは説明ですhttp://explain.depesz.com/s/dbf

"Limit  (cost=55739.84..55739.90 rows=25 width=554) (actual time=18065.470..18065.478 rows=25 loops=1)"
"  ->  Sort  (cost=55739.84..55741.90 rows=824 width=554) (actual time=18065.468..18065.471 rows=25 loops=1)"
"        Sort Key: item_mods.total_value"
"        Sort Method: top-N heapsort  Memory: 37kB"
"        ->  Nested Loop  (cost=5871.95..55716.59 rows=824 width=554) (actual time=285.806..18055.589 rows=610 loops=1)"
"              ->  Bitmap Heap Scan on items  (cost=5871.52..20356.70 rows=4339 width=550) (actual time=201.543..10028.684 rows=9945 loops=1)"
"                    Recheck Cond: ((item_type_id = 11) AND (num_sockets >= 2))"
"                    Rows Removed by Index Recheck: 4120"
"                    Filter: (league_id = 1)"
"                    Rows Removed by Filter: 1125"
"                    ->  BitmapAnd  (cost=5871.52..5871.52 rows=4808 width=0) (actual time=199.322..199.322 rows=0 loops=1)"
"                          ->  Bitmap Index Scan on index_items_on_item_type_id  (cost=0.00..289.61 rows=15625 width=0) (actual time=38.699..38.699 rows=16018 loops=1)"
"                                Index Cond: (item_type_id = 11)"
"                          ->  Bitmap Index Scan on index_items_on_num_sockets  (cost=0.00..5579.49 rows=301742 width=0) (actual time=158.441..158.441 rows=301342 loops=1)"
"                                Index Cond: (num_sockets >= 2)"
"              ->  Index Scan using index_item_mods_on_item_id on item_mods  (cost=0.43..8.14 rows=1 width=8) (actual time=0.803..0.803 rows=0 loops=9945)"
"                    Index Cond: (item_id = items.id)"
"                    Filter: (mod_id = 15)"
"                    Rows Removed by Filter: 9"
"Total runtime: 18065.773 ms"

このクエリの速度を改善するにはどうすればよいですか? インデックススキャンで9000回を超えるループがあることに注意してください

4

3 に答える 3

2

クエリが遅い理由は、データを返す方法のインデックスがないためです。

「ビットマップ インデックス スキャン」に注意してください。インデックスがあることはわかっていますが、必要な行を見つけるためにテーブル全体を調べる必要があります (したがって、行スキャンの合計は最大 301742 です!)。これはおそらく、あなたが要求した他の列の組み合わせと、適用している制約、つまり item_mods.mod_id = 15 が原因です。

試す:

  1. "items".* - すべてではなく、必要な列のみを選択します。

  2. インデックスを作成します: item_mods.item_id AND item_mods.mod_id

  3. 次のインデックスを作成します: items.league_id AND items.item_type_id AND num_sockets (num_sockets が同じテーブルにあると仮定)

パフォーマンスの違いはありますか?

于 2014-03-04T17:48:14.967 に答える
1

これは構文を短くしてきれいにするだけで、実質的に何も変更しません。

SELECT i.*
FROM   items     i
JOIN   item_mods m ON m.item_id = i.id
WHERE  i.league_id = 1
AND    i.item_type_id = 11
AND    i.num_sockets >= 2
AND    m.mod_id = 15
ORDER  BY m.total_value DESC
LIMIT  25;

このようなクエリを最適化するのは非常に困難です。Postgres は、インデックスの先頭から読み取ることはできません。の列で並べ替えているためitem_mods、最も選択的な条件がオンitemsになっているため、さらに役立つインデックスを調整することも困難です。

もちろん、どちらのテーブルでもインデックスを最適化できます。しかし、クエリにフィードする追加情報がなければ、安くはありません。Postgres が勝者を知る前に、すべての適格な行を読み取る必要があります。

dba.SE に関するこの関連する質問の下で解決策を開発しました。洗練されたもの:
空間インデックスは「範囲 - 並べ替え - 制限」クエリに役立ちますか

于 2014-03-04T23:16:01.980 に答える
0

以下のクエリは、結合前にフィルタリングが行われるため、パフォーマンスが向上するはずです。

   SELECT t.* 
   FROM
   (
     SELECT items.* FROM items
     WHERE  (items.league_id = 1) AND (items.item_type_id = 11) 
   ) t 
   INNER JOIN 
   (
      SELECT item_mods.*
      FROM item_mods
      WHERE item_mods.mod_id = 15 
   ) s
   ON s.item_id = t.id 
   WHERE (num_sockets >= 2)
   ORDER BY item_mods.total_value DESC
   LIMIT 25

num_sockets>=2属するテーブルがわかっている場合は、一部の内部クエリに含めることもできます。

パフォーマンスが良かったかどうか教えてください。

于 2014-03-04T17:41:23.680 に答える