2

最近、Postgresqlを9.1から9.2バージョンにアップグレードしました。新しいプランナーが間違ったインデックスを使用し、クエリの実行時間が長すぎます。

クエリ:

explain SELECT mentions.* FROM mentions WHERE (searches_id = 7646553) ORDER BY id ASC LIMIT 1000

9.1バージョンで説明:

Limit  (cost=5762.99..5765.49 rows=1000 width=184)
->  Sort  (cost=5762.99..5842.38 rows=31755 width=184)
    Sort Key: id
    ->  Index Scan using mentions_searches_id_idx on mentions  (cost=0.00..4021.90 rows=31755 width=184)
          Index Cond: (searches_id = 7646553)

9.2バージョンでの説明:

Limit  (cost=0.00..450245.54 rows=1000 width=244)
->  Index Scan using mentions_pk on mentions  (cost=0.00..110469543.02 rows=245354 width=244
    Index Cond: (id > 0)"
    Filter: (searches_id = 7646553)

正しいアプローチは9.1バージョンで、plannerはsearches_idのインデックスを使用します。9.2バージョンでは、plannerはそのインデックスを使用せず、searchs_idで行をフィルタリングします。

ORDER BY idを使用せずに9.2バージョンのクエリを実行すると、plannerはsearchs_idのインデックスを使用しますが、idで並べ替える必要があります。

また、サブクエリで行を選択し、2番目のクエリで並べ替えようとしましたが、plannerは通常のクエリと同じように動作することを説明しています。

select * from (
SELECT mentions.* FROM mentions WHERE (searches_id = 7646553))
AS q1
order by id asc

あなたは何をお勧めします?

4

2 に答える 2

2

search_id #7646553 行がテーブルの数パーセントを超える場合、テーブル スキャンが高速になるため、その列のインデックスは使用されません。する

select count(*) from mentions where searches_id = 7646553 

合計行と比較します。

それらがテーブルの数パーセント未満である場合は、試してください

with m as (
    SELECT *
    FROM mentions
    WHERE searches_id = 7646553
)
select *
from m
order by id asc

(PostgreSQL v12 以降では、 を使用する必要がありますwith ... as materialized。)

または、複合インデックスを作成します。

create index index_name on mentions (searches_id, id)

search_id のカーディナリティが低い場合は、同じインデックスを逆の順序で作成します

create index index_name on mentions (id, searches_id)

行う

analyze mentions

インデックス作成後。

于 2013-03-01T11:54:03.263 に答える