zai*_*ius 12 sql database postgresql indexing
我有一张约有2000万行的表.为了论证,我们可以说表中有两列 - 一个id和一个时间戳.我想要计算每天的物品数量.这就是我现在所拥有的.
SELECT DATE(timestamp) AS day, COUNT(*)
FROM actions
WHERE DATE(timestamp) >= '20100101'
AND DATE(timestamp) < '20110101'
GROUP BY day;
Run Code Online (Sandbox Code Playgroud)
没有任何索引,这需要大约30秒才能在我的机器上运行.这是解释分析输出:
GroupAggregate (cost=675462.78..676813.42 rows=46532 width=8) (actual time=24467.404..32417.643 rows=346 loops=1)
-> Sort (cost=675462.78..675680.34 rows=87021 width=8) (actual time=24466.730..29071.438 rows=17321121 loops=1)
Sort Key: (date("timestamp"))
Sort Method: external merge Disk: 372496kB
-> Seq Scan on actions (cost=0.00..667133.11 rows=87021 width=8) (actual time=1.981..12368.186 rows=17321121 loops=1)
Filter: ((date("timestamp") >= '2010-01-01'::date) AND (date("timestamp") < '2011-01-01'::date))
Total runtime: 32447.762 ms
Run Code Online (Sandbox Code Playgroud)
由于我看到了顺序扫描,我试图在日期聚合上编制索引
CREATE INDEX ON actions (DATE(timestamp));
Run Code Online (Sandbox Code Playgroud)
这将速度降低了约50%.
HashAggregate (cost=796710.64..796716.19 rows=370 width=8) (actual time=17038.503..17038.590 rows=346 loops=1)
-> Seq Scan on actions (cost=0.00..710202.27 rows=17301674 width=8) (actual time=1.745..12080.877 rows=17321121 loops=1)
Filter: ((date("timestamp") >= '2010-01-01'::date) AND (date("timestamp") < '2011-01-01'::date))
Total runtime: 17038.663 ms
Run Code Online (Sandbox Code Playgroud)
我是这个整个查询优化业务的新手,我不知道接下来该做什么.有什么线索我怎么能让这个查询运行得更快?
- 编辑 -
看起来我正在达到指数的极限.这几乎是在这个表上运行的唯一查询(尽管日期的值发生了变化).有没有办法对表格进行分区?或者创建一个包含所有计数值的缓存表?还是其他任何选择?
有没有办法对表格进行分区?
是的:http:
//www.postgresql.org/docs/current/static/ddl-partitioning.html
或者创建一个包含所有计数值的缓存表?还是其他任何选择?
当然可以创建"缓存"表.但这取决于您需要多长时间的结果以及需要的准确程度.
CREATE TABLE action_report
AS
SELECT DATE(timestamp) AS day, COUNT(*)
FROM actions
WHERE DATE(timestamp) >= '20100101'
AND DATE(timestamp) < '20110101'
GROUP BY day;
然后a SELECT * FROM action_report会及时给你你想要的东西.然后,您将安排一个cron作业来定期重新创建该表.
如果时间范围随每个查询而变化,或者该查询每天只运行一次,那么这种方法当然无济于事.
| 归档时间: |
|
| 查看次数: |
9758 次 |
| 最近记录: |