首先,这是我的查询:
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%。
答案 0 :(得分:0)
你可以在created_at
之前尝试一个version_hash
的索引(可能会更好地进行索引范围扫描......不清楚{{1}上的非等式谓词是怎样的影响计划,但我怀疑它会禁用version_hash
列上的范围扫描。
除此之外,查询和索引看起来和你要获得的一样好,EXPLAIN输出显示从索引中得到满足的查询。
该语句的性能听起来并不太合理,因为它聚合了95,000多行,特别是考虑到密钥长度为1543字节。这比我通常处理的尺寸要大得多。
索引中列的数据类型是什么,群集密钥或主键是什么?
created_at
每行1543字节的95,000行大约140MB的数据。