Postgresql

為什麼 PostgreSQL 9.5 不使用我最新的 ORDER BY 索引,即使它使用類似的索引就好了?

  • August 17, 2017

(從這篇文章跟進:為什麼我在子查詢中 ORDER BY 時沒有使用我的 PostgreSQL 表達式索引?

PostgreSQL 9.5。

我不能透露全部細節,但table有 22 列和 5 個索引:

  1. 主鍵 (‘pk’), text(btree)
  2. 另一個text(btree)
  3. 一個timestamp with time zone(btree)
  4. 一個tsvector(杜松子酒)
  5. 我最新的一個bigint(btree)

(從上一篇文章中你知道我試圖避免創建這個額外的列,而只是使用表達式索引——將兩integer列加在一起——沒有成功。bigint這裡的列可能只是“整數”,但我做了一個創建它時出錯;添加列、填充它並重新索引大約需要一個小時,所以我希望這無關緊要,但以防萬一。)

除了tsvector.

以下查詢都只需要 12ms 並且只使用一個Index Scan

  1. SELECT pk FROM table ORDER BY pk DESC LIMIT 10
  2. SELECT pk FROM table ORDER BY text_column DESC LIMIT 10
  3. 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(儘管它是一個不可為空的列。)

在中,不能使用PostgreSQLis 的索引來滿足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 排序到哪一端可能很重要。

引用自:https://dba.stackexchange.com/questions/183478