索引条件没有出现在 postgres 查询计划中
Index cond did not appear in postgres query plan
我正在阅读此 article,并决定自己尝试示例。
添加索引前:
我有 table BookHibernate
,sql 是由 hibernate
生成的:
CREATE TABLE bookhibernate
(
book_id bigint NOT NULL,
bought boolean,
genre character varying(255),
name character varying(255) NOT NULL,
price integer NOT NULL,
author_id bigint,
CONSTRAINT bookhibernate_pkey PRIMARY KEY (book_id),
CONSTRAINT fk_hlepqn9vy6biuo6vn47jo5ewx FOREIGN KEY (book_id)
REFERENCES authorhibernate (author_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk_r9o6704wcbcawmruyqojj4nab FOREIGN KEY (author_id)
REFERENCES authorhibernate (author_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
所以我打电话给explain analyze
:
explain analyze select * from bookhibernate where bookhibernate.price > 10
它给了我:
"Seq Scan on bookhibernate (cost=0.00..1.02 rows=1 width=1053) (actual time=0.007..0.008 rows=2 loops=1)"
" Filter: (price > 10)"
"Planning time: 0.054 ms"
"Execution time: 0.021 ms"
添加索引后:
create index my_index on bookhibernate(price);
添加索引并执行相同的 explain analyze
后,我看到 execution plan
没有改变,我看到 Filter: (price > 10)
注册,但我希望看到 Index cond: (price > 10)
。
为什么我的预期失败了?
更新:
有人告诉我这是因为 table 尺寸小。听起来很有道理,也确实如此。但是我尝试了对 1000 行 table 的查询。
- 为什么
Postgres
决定使用过滤?为什么它更受欢迎?
Filter: (price > 10)
的幕后黑手是什么?这个算法的复杂度是多少?
table大小太小了,PostgreSQL执行顺序扫描比使用索引效率更高。如果您希望 PostgreSQL 完全考虑索引,请向 table.
添加更多行
不仅table大小,条件的选择性也会影响优化器决定是否使用索引。
如果许多书的 price
大于 10,则使用索引扫描的效率较低,因为这涉及随机 I/O(索引页未按顺序存储在磁盘上)。在那种情况下,顺序扫描总是更有效。
有几个 PostgreSQL 配置参数会影响 PostgreSQL 选择索引的可能性,最重要的是 random_page_cost
。
您可以通过设置 enable_seqscan = off
然后 运行 您的 EXPLAIN
查询来测试您的索引是否符合条件。
使用此设置,PostgreSQL 将尽可能使用索引扫描。
我正在阅读此 article,并决定自己尝试示例。
添加索引前:
我有 table BookHibernate
,sql 是由 hibernate
生成的:
CREATE TABLE bookhibernate
(
book_id bigint NOT NULL,
bought boolean,
genre character varying(255),
name character varying(255) NOT NULL,
price integer NOT NULL,
author_id bigint,
CONSTRAINT bookhibernate_pkey PRIMARY KEY (book_id),
CONSTRAINT fk_hlepqn9vy6biuo6vn47jo5ewx FOREIGN KEY (book_id)
REFERENCES authorhibernate (author_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fk_r9o6704wcbcawmruyqojj4nab FOREIGN KEY (author_id)
REFERENCES authorhibernate (author_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
所以我打电话给explain analyze
:
explain analyze select * from bookhibernate where bookhibernate.price > 10
它给了我:
"Seq Scan on bookhibernate (cost=0.00..1.02 rows=1 width=1053) (actual time=0.007..0.008 rows=2 loops=1)"
" Filter: (price > 10)"
"Planning time: 0.054 ms"
"Execution time: 0.021 ms"
添加索引后:
create index my_index on bookhibernate(price);
添加索引并执行相同的 explain analyze
后,我看到 execution plan
没有改变,我看到 Filter: (price > 10)
注册,但我希望看到 Index cond: (price > 10)
。
为什么我的预期失败了?
更新:
有人告诉我这是因为 table 尺寸小。听起来很有道理,也确实如此。但是我尝试了对 1000 行 table 的查询。
- 为什么
Postgres
决定使用过滤?为什么它更受欢迎? Filter: (price > 10)
的幕后黑手是什么?这个算法的复杂度是多少?
table大小太小了,PostgreSQL执行顺序扫描比使用索引效率更高。如果您希望 PostgreSQL 完全考虑索引,请向 table.
添加更多行不仅table大小,条件的选择性也会影响优化器决定是否使用索引。
如果许多书的 price
大于 10,则使用索引扫描的效率较低,因为这涉及随机 I/O(索引页未按顺序存储在磁盘上)。在那种情况下,顺序扫描总是更有效。
有几个 PostgreSQL 配置参数会影响 PostgreSQL 选择索引的可能性,最重要的是 random_page_cost
。
您可以通过设置 enable_seqscan = off
然后 运行 您的 EXPLAIN
查询来测试您的索引是否符合条件。
使用此设置,PostgreSQL 将尽可能使用索引扫描。