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 版本中,规划器在 search_id 上使用索引。在 9.2 版本中,规划器不使用该索引并通过 search_id 过滤行。

当我在没有 ORDER BY id 的情况下执行 9.2 版本查询时,规划器使用 searchs_id 上的索引,但我需要按 id 排序。

我还尝试在子查询中选择行并在第二个查询中对其进行排序,但解释表明,规划器在正常查询中执行相同的操作。

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 回答
0

对我来说,我有索引,但它们都基于 3 列,而且我没有调用索引中的列之一,所以它正在对整个事物进行 seq 扫描。可能的修复:更多索引但使用更少的列(和/或切换列顺序)。

我们看到的另一个问题是我们有正确的索引,但显然它是一个“无效”(创建不良的 CONCURRENT?)索引。所以删除它并创建它(或重新索引它)并开始使用它。

有哪些可用选项可以识别和删除 Postgres 中的无效对象(例如:损坏的索引)

另见http://www.postgresql.org/docs/8.4/static/indexes-multicolumn.html

于 2015-03-23T17:01:46.123 回答