2014-02-06 31 views
0

表+ LIMIT +卦:說明有關索引+ ORDER BY在PostgreSQL的9.1

CREATE TABLE msp_adm_munic_complet_g_01 
(
    nom_tri character varying(64), 
    ogc_fid serial NOT NULL 
) 

指數:

CREATE INDEX idx_gist_msp_adm_munic_complet_g_nom_tri 
    ON msp_adm_munic_complet_g_01 
    USING gist 
    (nom_tri COLLATE pg_catalog."default" gist_trgm_ops); 

查詢:

select * from msp_adm_munic_complet_g_01 
ORDER BY 'potato'<->nom_tri 
LIMIT 25; 

問題:

爲什麼它通過梳子通過指數ORDER BY + LIMIT的初始化,而不是當查詢只包含ORDER BY時?

當然,指數也增加了查詢的速度

我發現的唯一的解釋是在這裏: http://www.postgresql.org/docs/9.1/static/indexes-ordering.html

但缺乏細節

編輯#1:

帶限制的查詢計劃:

Limit (cost=0.00..19.27 rows=25 width=590) 
    -> Index Scan using idx_gist_msp_adm_munic_complet_g_nom_tri on 
msp_adm_munic_complet_g_01 (cost=0.00..2784.49 rows=3612 width=590) 
     Order By: ((nom_tri)::text <-> 'potato'::text) 

查詢計劃沒有限制:

Sort (cost=1847.59..1856.62 rows=3612 width=590) 
    Sort Key: (('potato'::text <-> (nom_tri)::text)) 
    -> Seq Scan on msp_adm_munic_complet_g_01 (cost=0.00..682.15 rows=3612 width=590) 
+0

請向我們展示您的查詢的執行計劃('explain analyze')(理想情況下上傳到http://explain.depesz.com) –

+0

另外,請解釋*爲什麼*您認爲它應該使用索引。你認爲執行者應該採取哪些精確的步驟?嘗試並向他們提出一些估計的成本 - 如果您不知道某些步驟的相對成本,請不要擔心。即使數字與現實不符,仔細思考它也是有用的。 –

+0

當我閱讀您所引用的PG文檔中的解釋時,爲什麼在這種情況下不使用索引對我有意義。你可能必須解釋爲什麼你認爲這個解釋缺乏細節。 – harmic

回答

0

當然,指數會增加查詢

的速度,我認爲這是問題的要點。關於它當然沒有「當然」。

想象一下,你有一本大書。該書在後面有一個索引,列出了它們出現的不同術語和頁碼。

你的老闆找到你說:「我希望你按照字母順序列出書中前10個詞彙,並且寫下他們的一切」。您可以從索引開始,然後轉到您找到的前10個術語列出的每個頁面。這不會花很長時間。特別是與閱讀整本書並嘗試在頭腦中排序的替代方法相比,後者找到前10個。

接下來,您的老闆向您介紹並說他希望您列出書中的所有術語他們的定義,按字母順序。天真地,你決定使用相同的方法。你會不斷翻閱本書,重複訪問每一頁。這將需要永遠。

到你完成的時候,你會讀完整個索引並多次訪問書中的每一頁。如果你閱讀這本書的時候,閱讀本書的時候會更快一些,包括封面,按照內容分類(尤其是如果你是一個數據庫,它比人類的短期記憶大得多,並且可以很容易地在內存中對大型列表進行排序)。

這正是數據庫中發生的情況。計算機依次讀取磁盤文件效率更高,因爲它不需要太多地來回尋找磁盤頭。它一次讀取整個頁面。它與我們這裏的人類相比具有一些優勢 - enourmouse短期記憶意味着它可以同時保存數千頁的記憶。但是一張大桌子和/或繁重的工作量將會打敗這一局面。

因此,數據庫在執行它之前分析每個查詢。它會嘗試估計表中返回什麼比例,連同它所知道的隨機訪問頁面的成本與其他表的統計數據有關。有一點可以說,掃描整個表格並忘記索引會更高效。

您可能認爲這種過分簡單的比喻不適用於三元組索引,但它確實如此。索引不是字母,但構建排序列表的機制是相同的 - 除非並非所有索引類型都適合在任何情況下返回已排序的行。許多索引類型允許您快速查找某些內容,但不保持鍵的順序。在內置索引類型中,只有b-tree適用於返回排序數據。我實際上對三撇子指數可用於此有些詫異。但它取決於ORDER表達式 - 我猜這個索引確實會返回< - >順序的數據。

如果以排序順序遍歷行是該表上的常見操作,則可以採取一些措施使其更快。

如果您使用Postgresql 9.2,則可能可以使用index-only掃描。在你的查詢中,你正在選擇所有的列,這意味着它不能使用僅索引掃描,並且無論如何我不認爲你能夠使用帶有trigram索引的只索引掃描。

您可以使用CLUSTER命令按照與索引相同的順序排列表(儘管在插入或更新數據時不會保持這種方式,因此需要定期在表中執行經常更新)。

您可能會發現該表格可以通過微調正在保存的statistics而受益。更多的統計數據可能會讓它更頻繁地使用索引。

您可以調整計劃程序用來估計順序讀取數據的相對成本與隨機訪問數據相比的參數。你可以切換到使用固態硬盤而不是舊式旋轉磁盤。

當然,更多的內存永遠不會傷害數據庫。