簡體   English   中英

用於BETWEEN和ORDER BY的Postgresql多列索引

[英]Postgresql multicolumn index for BETWEEN and ORDER BY

我有一個具有以下結構的大表(100M條記錄)。

  length   |          created_at
-----------+-------------------------------
 506225551 | 2018-12-29 02:08:34.116618
 133712971 | 2018-10-19 21:20:14.568936
 608443439 | 2018-12-14 03:22:55.141416
 927160571 | 2019-01-30 00:51:41.639126
 407033524 | 2018-11-16 21:26:41.523047
 506008096 | 2018-11-17 00:07:42.839919
 457719749 | 2018-11-12 02:32:53.116225
  • 0 < length < 1000000000
  • '2017-01-01' < created_at < '2019-02-01'
  • 數據按lengthcreated_at均勻分布。

我想運行這樣的查詢

SELECT * FROM tbl WHERE length BETWEEN 2000000 and 3000000 ORDER BY  created_at DESC

在2000000至3000000之間有100K個結果,因此我想使用索引進行選擇和排序。

我已經嘗試過這些方法

1.簡單的BTREE索引

create index on tbl(length);

這對於短距離的length效果很好,但是我不能使用此索引來訂購記錄。

2.多列BTREE指數

 create index on tbl(length, created_at);

該索引我只能用於這樣的查詢

 SELECT * FROM tbl WHERE length = 2000000 ORDER BY  created_at DESC

3.帶有btree_gist擴展名的GIST索引。 我希望該索引可以正常工作。

create index on tbl using gist(length, created_at);   

但事實並非如此。 即使對於這樣的簡單查詢,我也無法使用此索引。

test=# explain analyze select * from gist_test where a = 345 order by c desc;

                                                                QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
 Sort  (cost=25706.37..25730.36 rows=9597 width=12) (actual time=4.839..5.568 rows=10000 loops=1)
   Sort Key: c DESC
   Sort Method: quicksort  Memory: 853kB
   ->  Bitmap Heap Scan on gist_test  (cost=370.79..25071.60 rows=9597 width=12) (actual time=1.402..2.869 rows=10000 loops=1)
         Recheck Cond: (a = 345)
         Heap Blocks: exact=152
         ->  Bitmap Index Scan on gist_test_a_b_c_idx  (cost=0.00..368.39 rows=9597 width=0) (actual time=1.384..1.384 rows=10000 loops=1)
               Index Cond: (a = 345)
 Planning time: 0.119 ms
 Execution time: 6.271 ms

我只能在一個列上將它用作簡單的BTREE。

那么,我該如何解決這個問題呢?

也許沒有SQL數據庫可以處理這種查詢?

我認為這是不可能的(至少在香草postgresql中,我不知道可以對此有所幫助的擴展名)。 僅因為索引已生成排序的記錄,才可以跳過對記錄進行排序的步驟。
然而:

  1. 文檔中所述,只能將B樹索引用於排序(這很有意義,它是使用搜索樹實現的)。
  2. 您的whereorder by與B樹索引不兼容:
    • 由於同時具有這兩個子句,因此您需要在索引(A, B)放入2列
    • 索引中的數據按(A, B)排序,因此也按A排序(這就是為什么postgresql僅當whereA時才能夠對表進行快速索引掃描),因此,它是排序B在索引(它是由排序B僅在每個子集,其中A是恆定的,但不是在整個表)。
    • 如您可能已經知道的那樣,由於where僅對B進行索引將無濟於事。

提供的示例2顯示了針對單個A值進行過濾的情況,PostgreSQL的優化。

如果對2列(A, B)進行排序是不可接受的,那么恐怕您不應該期望超過此值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM