大表频繁count的改进
当大表频繁需要count的查询,考虑使用汇总表。
比如,某个日志表记录了某个页面的点击记录,执行count可以得到总的点击数,由于数据量已经2.3亿条,每次count都要耗时6秒:
SELECT COUNT_BIG(1) FROM bigtable
SQL Server 执行时间:
CPU 时间 = 14 毫秒,占用时间 = 6002 毫秒。
根据时间字段InsertTime统计发现,当天数据仅16852行,而历史数据约2.3亿。
SELECT COUNT_BIG(1) FROM bigtable WHERE inserttime < '2020-01-01 00:00:00'
--行数 234287003SELECT COUNT_BIG(1) FROM bigtable WHERE inserttime >= '2020-01-01 00:00:00'
--行数 16852
这种情况下,我们可以创建一个汇总表:
CREATE TABLE bigtable_summary(id int, dtime datetime, summ bigint)
第一次需要初始化数据,比如把2019年12月31日之前的数据全部初始化为一条记录:
DECLARE @cnt bigint
SET @cnt = (SELECT COUNT_BIG(1) FROM bigtable WHERE inserttime <= '2019-12-31 23:59:59')
INSERT INTO bigtable_summary(dtime, summ) VALUES('2019-12-31 59:59:59',@cnt)
以后每天00:00(比如2020-01-02)插入一条前一天的汇总记录,语法参考如下:
DECLARE @cnt bigint
SET @cnt = (SELECT COUNT_BIG(1) FROM bigtable WHERE inserttime >= '2020-01-01 00:00:00' AND inserttime < '2020-01-02 00:00:00')
INSERT INTO bigtable_summary(dtime, summ) VALUES('2020-01-01 00:00:00',@cnt)
这样可以大表的count就可以改为:汇总表sum汇总记录 + 大表当天的count记录,由于大表InsertTime字段有索引,只查询当天的数据,效率自然很高。
$cnt1 = SELECT SUM(cnt) FROM bigtable_summary WHERE dtime < '2020-01-02 00:00:00'
$cnt2 = SELECT COUNT(1) FROM bigtable WHERE inserttime >= '2020-01-02 00:00:00'
$cnt = $cnt1 + $cnt2