[英]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'
length
和created_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中,我不知道可以对此有所帮助的扩展名)。 仅因为索引已生成排序的记录,才可以跳过对记录进行排序的步骤。
然而:
where
和order by
与B树索引不兼容:
(A, B)
放入2列 (A, B)
排序,因此也按A
排序(这就是为什么postgresql仅当where
在A
时才能够对表进行快速索引扫描),因此,它是不排序B
在索引(它是由排序B
仅在每个子集,其中A
是恒定的,但不是在整个表)。 where
仅对B
进行索引将无济于事。 提供的示例2显示了针对单个A
值进行过滤的情况,PostgreSQL的优化。
如果对2列(A, B)
进行排序是不可接受的,那么恐怕您不应该期望超过此值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.