【问题标题】:Index cond did not appear in postgres query plan索引 cond 未出现在 postgres 查询计划中
【发布时间】:2016-07-25 12:46:35
【问题描述】:

我正在阅读此article,并决定自己尝试示例。

添加索引之前:

我有表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)

为什么我的期望失败了?

更新:

有人告诉我这是因为桌子很小。这听起来很合理,而且是真的。但是我尝试了对 1000 行表的查询。

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

【问题讨论】:

  • 你的表里有数据吗?你在桌子上跑analyze了吗?
  • @jmelesky,是的,两行 / 是的
  • 对于两行,任何数据库都不会使用索引。
  • @a_horse_with_no_name,我更新了我的问题。谢谢!
  • 条件删除了多少行?为 1000 行的表添加使用 explain (analyze, verbose) select ... 的执行计划。

标签: postgresql indexing sql-execution-plan


【解决方案1】:

表的大小是如此之小,以至于 PostgreSQL 执行顺序扫描比使用索引更有效。如果您希望 PostgreSQL 完全考虑索引,请向表中添加更多行。

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

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

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

【讨论】:

  • 谢谢,我明白了。我尝试对 1000 行运行查询,Postgres 决定最好先过滤然后使用带索引的二进制搜索。为什么会这样?当索引算法为lg(n) 时,Filter: (price > 10) 的算法复杂度是多少?
  • 我已经改进了答案。选择单个索引条目是O(ln(n)),但不是扫描索引的相关部分。
猜你喜欢
  • 2017-01-06
  • 1970-01-01
  • 1970-01-01
  • 2012-12-26
  • 1970-01-01
  • 2015-01-18
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多