為什麼 PostgreSQL 9.5 不使用我最新的 ORDER BY 索引,即使它使用類似的索引就好了?
(從這篇文章跟進:為什麼我在子查詢中 ORDER BY 時沒有使用我的 PostgreSQL 表達式索引?)
PostgreSQL 9.5。
我不能透露全部細節,但
table
有 22 列和 5 個索引:
- 主鍵 (‘pk’),
text
(btree)- 另一個
text
(btree)- 一個
timestamp with time zone
(btree)- 一個
tsvector
(杜松子酒)- 我最新的一個
bigint
(btree)(從上一篇文章中你知道我試圖避免創建這個額外的列,而只是使用表達式索引——將兩
integer
列加在一起——沒有成功。bigint
這裡的列可能只是“整數”,但我做了一個創建它時出錯;添加列、填充它並重新索引大約需要一個小時,所以我希望這無關緊要,但以防萬一。)除了
tsvector
.以下查詢都只需要 12ms 並且只使用一個
Index Scan
:
SELECT pk FROM table ORDER BY pk DESC LIMIT 10
SELECT pk FROM table ORDER BY text_column DESC LIMIT 10
SELECT pk FROM table ORDER BY timestamp_column DESC LIMIT 10
但是,如果我嘗試將我的新
bigint
索引用於ORDER BY
:
SELECT pk FROM table ORDER BY bigint_column DESC LIMIT 10
…它需要 2.7 秒並使用
Limit -> Sort -> Seq Scan
.我的“作弊”方法似乎是最接近使用索引的方法:
SELECT pk FROM table WHERE bigint_column > 1000000 ORDER BY bigint_column DESC LIMIT 10
這需要 12 毫秒並使用
Limit -> Sort -> Bitmap Heap Scan (bigint_column > 1000000) -> Bitmap Index Scan (bigint_column > 1000000)
.這是
VACUUM ANALYZE
在添加索引之後。我覺得奇怪的是我的表情索引沒有被用在另一個問題中。現在它只是一個普通的舊專欄(我什至沒有添加實際走這條路的必要觸發器。)
當其他三個“正常”工作時,為什麼不使用我的最新索引?(正如在https://dba.stackexchange.com/a/183290/28774的評論中指出的那樣,僅索引掃描會更好。我不明白為什麼所有這些查詢都至少不使用索引掃描,更不用說僅索引掃描,而不是完整的 Seq 掃描。)
索引定義有
DESC NULLS LAST
(儘管它是一個不可為空的列。)
在中,不能使用
PostgreSQL
is 的索引來滿足which is (包括排序,因為這意味著)。即使列定義為 也是如此。DESC NULLS LAST``ORDER BY``DESC NULLS FIRST``DESC``NULLS FIRST``NOT NULL
您可以重建索引,或者(因為您知道該列不為空)您可以添加
NULLS LAST
到查詢ORDER BY
中以使其與現有索引匹配。請注意,它
PostgreSQL
確實知道如何向後跟踪索引,因此預設索引(隱式ASC NULLS LAST
)也能夠滿足您的DESC NULLS FIRST
查詢。因此,在索引中指定 DESC 並不重要,但指定 NULLS 排序到哪一端可能很重要。