sql - Postgresql 规划器使用了错误的索引

标签 sql postgresql

最近我将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 使用 searchs_id 上的索引。在 9.2 版本中,规划器不会不使用该索引并按 searchs_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

你会推荐什么?

最佳答案

如果 searchs_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)

如果 searchs_id 较低 cardinality然后以相反的顺序创建相同的索引

create index index_name on mentions (id, searches_id)

analyze mentions

创建索引后。

关于sql - Postgresql 规划器使用了错误的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15155369/

相关文章:

django - 连接到 PostgreSQL 时 Django 中的 "psycopg2"有什么用

mysql - 将行引用作为 MySQL 函数输入参数传递

sql - 避免 SQL 中出现太多 case 语句?

sql - 使用 select 做数学(Sqlite)

mysql - 处理 SQL 保留表名和列名

postgresql - postgres - 对列总和的约束(无触发器)

java - SQL 中的 maxdrawdown 计算

mysql:更新出现相同值的列中的行更改值

postgresql - Postgres - jsonb : Update key in column with value taken from another table

postgresql - 如何将整数转换为字符串并获取字符串的长度