我们有一个包含大约25,000,000行的表,称为'events',具有以下模式:
TABLE events
- campaign_id : int(10)
- city : varchar(60)
- country_code : varchar(2)
以下查询需要很长时间(> 2000秒):
SELECT COUNT(*) AS counted_events, country_code
FROM events
WHERE campaign_id` in (597)
GROUPY BY city, country_code
ORDER BY counted_events
我们发现这是因为GROUP BY
部分。
已使用(campaign_id, city, country_code)
上的索引idx_campaign_id_city_country_code。
也许有人可以提出一个好的解决方案来加快速度?
更新:
'Explain'表明,在许多可能的索引中,MySql使用这个:'idx_campaign_id_city_country_code',对于它显示的行:'471304'和'Extra'它显示:'使用where;使用临时;使用filesort' -
以下是EXPLAIN的全部结果:
更新:
好的,我认为它已经解决了:
再次查看粘贴的查询,我意识到我在这里忘了提到SELECT中还有一个名为'country_name'的列。所以查询非常慢(包括country_name),但我只是把它留下来,现在查询的性能绝对可以。 抱歉,这个错误!
非常感谢您的所有有用的评论,我会提供所有好的答案!有一些非常有用的补充,我可能也应用(比如改变类型等)。
答案 0 :(得分:3)
没有看到EXPLAIN说它是远距离射击,无论如何:
发布整个EXPLAIN输出
答案 1 :(得分:0)
不要使用function aktif_kotak(id){
//non_aktif_kotak();
id=id.substr(2, 4);
id=parseInt(id)-1;
var kotak_aktif=document.getElementById('group-kotak').children[id];
$(kotak_aktif).addClass("kotak-aktif");
$(kotak_aktif).siblings().removeClass("kotak-aktif");
}
- 更好地使用:
IN()
afaik WHERE campaign_id = 597
OR campaign_id = 231
OR ....
非常慢。
更新:,例如 nik0lias 已注释 - IN()
比连接IN()
条件更快。
答案 2 :(得分:0)
一些想法:
鉴于表格的性质和大小,它将成为partitioned tables国家的一个很好的候选人。这样,每个国家的事件都将存储在不同的物理表中,即使它表现为虚拟大表
国家/地区代码是字符串吗?可能你有一个country_id,可以更容易排序。 (它可能会强制您创建或更改索引)
你真的在小组中使用这个城市吗?
答案 3 :(得分:0)
问题是,MySQL不使用索引进行排序。我不能说为什么,因为它应该。可能是一个错误。
执行此查询的最佳策略是扫描索引的子树,其中event_id = 597。由于索引按city_id排序,因此country_code不需要额外排序,扫描时可以计算行数。
因此索引已经是此查询的最佳选择。 MySQL没有正确使用它们。
我正在离线获取更多信息。看起来这根本不是数据库问题,但是
只要从选择列表中删除country_name,查询将恢复为仅索引扫描(在EXPLAIN输出中使用“index”)并且速度非常快。