2016-07-25 66 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))',但是掃描相關部分的索引不是。 –