为什么 Postgres 不在简单的 ORDER BY LIMIT 1 上使用我的索引?
Why is Postgres not using my index on a simple ORDER BY LIMIT 1?
我有一个很大的 table(大约 11,000,000 行),我需要在给定排序条件的情况下找到第一个项目。
请注意,第 Date
列不 接受空值
为什么 Postgres 不使用索引:
CREATE INDEX track_ix_date
ON "Track"
USING btree
("Date" DESC NULLS LAST);
关于这个简单的查询:
select * from "Track" order by "Date" desc limit 1
但它确实在另一个查询中使用了它:
select * from "Track" order by "Date" desc nulls last limit 1
第二个查询实际上比第一个查询快得多。
我已经阅读了 indexes and ORDER BY 文档并说在带有 LIMIT
子句的 ORDER BY
的特殊情况下使用索引比扫描 table,因为排序需要扫描完整的 table 才能得到单个项目
Postgres 难道不应该检测到 nulls last / first
无关紧要,因为该列不接受空值并且只使用最快的方法吗?
总有一个折衷,因为让优化器更聪明也意味着让优化器变慢,这会伤害到每个人。
目前,它还不够智能,因此您必须更改索引定义或查询才能使其正常工作。
可能值得在 pgsql-hackers 邮件列表上寻求这样的改进,或者自己为它编写一个补丁并提交到那里。
因为您正在对该查询执行 "SELECT ALL ROWS"。 Postgres 不用索引。
我敢打赌,如果您添加 "WHERE date = ?" 条件,就会使用索引。
我在寻找一个非常相似的问题的答案时遇到了这个问题。我在 PostgreSQL 文档中的这篇文章中找到了答案。 https://www.postgresql.org/docs/current/indexes-ordering.html
简而言之:Limit N 是按功能排序的。当有一个索引与查询的 order by 子句匹配时,它可以使用它,否则不使用。因此,通过指定“null last”,您可以将查询的顺序与索引的顺序相匹配,使其可用。否则服务器无法确定它正在获取正确的 N 条记录。
我有一个很大的 table(大约 11,000,000 行),我需要在给定排序条件的情况下找到第一个项目。
请注意,第 Date
列不 接受空值
为什么 Postgres 不使用索引:
CREATE INDEX track_ix_date
ON "Track"
USING btree
("Date" DESC NULLS LAST);
关于这个简单的查询:
select * from "Track" order by "Date" desc limit 1
但它确实在另一个查询中使用了它:
select * from "Track" order by "Date" desc nulls last limit 1
第二个查询实际上比第一个查询快得多。
我已经阅读了 indexes and ORDER BY 文档并说在带有 LIMIT
子句的 ORDER BY
的特殊情况下使用索引比扫描 table,因为排序需要扫描完整的 table 才能得到单个项目
Postgres 难道不应该检测到 nulls last / first
无关紧要,因为该列不接受空值并且只使用最快的方法吗?
总有一个折衷,因为让优化器更聪明也意味着让优化器变慢,这会伤害到每个人。
目前,它还不够智能,因此您必须更改索引定义或查询才能使其正常工作。
可能值得在 pgsql-hackers 邮件列表上寻求这样的改进,或者自己为它编写一个补丁并提交到那里。
因为您正在对该查询执行 "SELECT ALL ROWS"。 Postgres 不用索引。
我敢打赌,如果您添加 "WHERE date = ?" 条件,就会使用索引。
我在寻找一个非常相似的问题的答案时遇到了这个问题。我在 PostgreSQL 文档中的这篇文章中找到了答案。 https://www.postgresql.org/docs/current/indexes-ordering.html
简而言之:Limit N 是按功能排序的。当有一个索引与查询的 order by 子句匹配时,它可以使用它,否则不使用。因此,通过指定“null last”,您可以将查询的顺序与索引的顺序相匹配,使其可用。否则服务器无法确定它正在获取正确的 N 条记录。