在已编制索引时提高计数和总和的性能

时间:2013-01-14 23:59:35

标签: mysql sql

首先,这是我的查询:

SELECT 
    COUNT(*) as velocity_count, 
    SUM(`disbursements`.`amount`) as summation_amount 
FROM `disbursements` 
WHERE 
    `disbursements`.`accumulation_hash` = '40ad7f250cf23919bd8cc4619850a40444c5e90c978f88635a09ccf66a82ffb38e39ea51cdfd651b0ebdac5f5ca37cd7a17e0f60fea6cbce1397ccff5fa37346' 
    AND `disbursements`.`caller_id` = 1 
    AND `disbursements`.`active` = 1 
    AND (version_hash != '86b4111677294b27a1805643d193b8d437b6ddb170b4ed5dec39aa89bf070d160cbbcd697dfc1988efea8429b1f1557625bf956180c65d3dcd3a318280e0d2da') 
    AND (`disbursements`.`created_at` BETWEEN '2012-12-15 23:33:22' 
    AND '2013-01-14 23:33:22') LIMIT 1

解释延伸返回以下内容:

+----+-------------+---------------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------+------------------------------+---------+------+--------+----------+--------------------------+
| id | select_type | table         | type  | possible_keys                                                                                                                                 | key                          | key_len | ref  | rows   | filtered | Extra                    |
+----+-------------+---------------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------+------------------------------+---------+------+--------+----------+--------------------------+
|  1 | SIMPLE      | disbursements | range | unique_request_index,index_disbursements_on_caller_id,disbursement_summation_index,disbursement_velocity_index,disbursement_version_out_index | disbursement_summation_index | 1543    | NULL | 191422 |   100.00 | Using where; Using index |
+----+-------------+---------------+-------+-----------------------------------------------------------------------------------------------------------------------------------------------+------------------------------+---------+------+--------+----------+--------------------------+

实际查询大约有95,000行。如果我解释另一个达到约50行的查询,那么解释是相同的,只是估计的行数较少。

选择的索引包括依次为accum_hash,caller_id,active,version_hash,created_at,amount。

我尝试过做COUNT(id)或COUNT(caller_id),因为这些是非空字段并返回与count(*)相同的东西,但它对计划没有任何影响或实际查询的运行时间。

这也是一个繁重的插入表,基本上每个查询都会在上次运行后插入或更新一行,因此mysql查询缓存并不完全有用。

在我使用memcache或redis之类的东西进行某种类型的时间序列缓存之前,是否有一个明显的解决方案可以让它更快地运行?一个正常的~50行查询在5MS中返回,跨越90k +行的那些查询需要500-900MS,而且我真的买不起任何超过100MS的东西。

我应该指出日期是一个滚动的30天窗口,需要基本上是实时的。过期可能会在约1分钟的粒度下发生,但是在提交时需要立即看到新项目。我也使用RDS,读取IOPS基本上为0,cpu约为60-80%。当我不查询巨大的90,000多个记录项时,CPU通常会低于10%。

1 个答案:

答案 0 :(得分:0)

你可以在created_at之前尝试一个version_hash的索引(可能会更好地进行索引范围扫描......不清楚{{1}上的非等式谓词是怎样的影响计划,但我怀疑它会禁用version_hash列上的范围扫描。

除此之外,查询和索引看起来和你要获得的一样好,EXPLAIN输出显示从索引中得到满足的查询。

该语句的性能听起来并不太合理,因为它聚合了95,000多行,特别是考虑到密钥长度为1543字节。这比我通常处理的尺寸要大得多。

索引中列的数据类型是什么,群集密钥或主键是什么?

created_at

每行1543字节的95,000行大约140MB的数据。