2016-07-25 67 views
0

我正在阅读这article,并决定尝试自己的例子。指数cond没有出现在postgres查询计划

加入索引之前:

我有表BookHibernate,被hibernate生成SQL:

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)现场背后是什么?这个算法的复杂性是什么?
+0

表中是否有任何数据?你在桌子上运行“分析”吗? – jmelesky

+0

@jmelesky,是,两行/是 –

+0

对于两行,没有数据库会使用索引。 –

回答

1

表的大小非常小,因此PostgreSQL执行顺序扫描的效率要高于使用索引的效率。如果您希望PostgreSQL根本考虑索引,请在表中添加更多行。

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

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

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

+0

谢谢,我明白了这一点。我试图对1000行进行查询,Postgres决定最好过滤,然后用索引进行二分搜索。为什么发生?当索引算法是'lg(n)'时,'Filter:(price> 10)'的算法复杂度是多少? –

+0

我已经改进了答案。选择一个索引条目是'O(ln(n))',但是扫描相关部分的索引不是。 –