索引条件没有出现在 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 的查询。

  1. 为什么 Postgres 决定使用过滤?为什么它更受欢迎?
  2. Filter: (price > 10)的幕后黑手是什么?这个算法的复杂度是多少?

table大小太小了,PostgreSQL执行顺序扫描比使用索引效率更高。如果您希望 PostgreSQL 完全考虑索引,请向 table.

添加更多行

不仅table大小,条件的选择性也会影响优化器决定是否使用索引。 如果许多书的 price 大于 10,则使用索引扫描的效率较低,因为这涉及随机 I/O(索引页未按顺序存储在磁盘上)。在那种情况下,顺序扫描总是更有效。

有几个 PostgreSQL 配置参数会影响 PostgreSQL 选择索引的可能性,最重要的是 random_page_cost

您可以通过设置 enable_seqscan = off 然后 运行 您的 EXPLAIN 查询来测试您的索引是否符合条件。 使用此设置,PostgreSQL 将尽可能使用索引扫描。