GP索引調優測試--原理篇


說明

之前對Postgres/GP的索引測試見GP索引調優測試–基本篇.mdGP索引調優測試–排序篇,此文給出原理解釋。


原理

建議先閱讀“深入理解計算機系統(原書第2版)的第6章 存儲器層次結構”,再瞭解B樹,最後閱讀數據庫索引原理及優化,可以對索引的原理有很清楚的瞭解。

這裏給出使用索引和不使用索引時,查詢時間的複雜度,

查詢類型 無索引複雜度 有索引複雜度
特定數據(= O(n) (注:n次順序讀取) O(lgn+1) (注:lgn次查找+1次隨機讀取)
特定範圍(range) O(n)(注:n次順序讀取) O( lgn+m)(注:lgn次查找+m次隨機讀取,m爲range的範圍)
排序 O(nlgn) (注:這裏認爲排序的複雜度爲nlgn) O(lgn+n)(注:lgn次隨機讀取找到第一個值,之後往後讀取)

解釋

故之前的測試結果可以給出解釋,

1. 查找特定數據走索引,而且很快

隨機讀取雖然花費時間比較長,但次數很少,故走索引

2. 特定範圍數據,數據量小時走索引,大時並不走

數據量小時m比較小,故走索引;數據量大時,比如爲n,此時lgn+n>n,故不走索引(注意,複雜度中n爲常量,m纔是變量)!

3. 排序走索引

有索引的複雜度要低一些


附錄

查詢大量特定數據

實際上,在上述查找特定數據時,也可能是不走索引的。比如,來自高效使用PostgreSQL索引的一個例子,

從表中檢索到的行數可以基於特定的常數值的查詢檢索而變化。(我注:即不同的常量值,會導致不同的結果行數)。因此,例如,查詢計劃器對於查詢select * from foo where bar = 1使用索引可能是正確的,但對於查詢select * from foo where bar = 2卻可能不使用索引,這發生於對於bar值爲2的行有比較多的話。發生這種情況時,順序掃描實際上是最有可能比索引掃描快得多,因此,查詢計劃器實際上是判斷正確的,這時順序掃描的性能代價相比索引掃描更低。

即,實際上查詢特定值的複雜度分別爲O(n)(注:n次順序讀取)O( lgn+m)(注:lgn次隨機讀取,m爲該值重複的次數),故當該值重複較多時並不走索引,與範圍查詢類似。更深入的分析見爲什麼我在Sql Server上創建的索引用不上? - 知乎。

更多關於不走索引的情況分析見筆記–索引失效情況分析.md。

排序大量數據

實際上參見筆記–Postgres索引測試–基本篇.md,針對排序,在大量數據下使用索引反而可能變慢,參見11.4. 索引和ORDER BY,如下,

對於一個需要掃描表的大部分的查詢, 明確的排序可能要比使用索引快的多,因爲它使用順序存取模式所以需要較少的磁盤I/O。 當只需要獲取幾行時,索引是更有效的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章