我们正在为一堆游戏运行统计网站,但是在日志超过100兆之后,事情开始变慢,所以我们需要优化我们的查询。
但是,我们发现我们认为是一个简单的查询,需要大约1.5秒:
SELECT handle,
(
SELECT COUNT(*)
FROM kills
WHERE killer=p.handle
AND k_team != c_team
AND gid=p.gid
) AS kills
FROM players as p
WHERE gid="3245"
AND team="axis"
ORDER BY kills DESC LIMIT 0, 10;
这会为其中一个团队生成结果列表。
表格杀戮和玩家分别包含36000和4000行。
为什么这个查询花了这么长时间才能进行优化?我们应该考虑加入吗?
祝你好运, 拉卡
答案 0 :(得分:3)
通常,MySQL执行连接的速度比子选择快。要了解如何优化查询,建议您阅读EXPLAIN语法。
首先,确保您的kills表具有杀手和gid的复合索引,然后尝试此连接:
SELECT p.handle, COUNT(*) AS n_kills FROM players p JOIN kills k ON p.handle = k.killer AND p.gid = k.gid WHERE p.gid = 3245 AND p.team = "axis" AND k.k_team != k.c_team GROUP BY p.handle ORDER BY n_kills DESC LIMIT 0,10
查看这两个表的CREATE TABLE语句将有助于确定索引的任何问题。
答案 1 :(得分:1)
您是否尝试在kills
表killer
列上添加索引?
答案 2 :(得分:0)
是的,你一定要考虑加入。从您发布的代码片段中很难判断,但是只要您可以在子查询中使用联接,这样做会很有用。
您可能还想考虑在数据库中的其他位置缓存kill count;特别是如果你使用的是InnoDB,COUNT()操作比简单地从数据库中选择一个[相对]最近的值需要更多的时间。您可以通过在相应的记录上增加kill count来轻松地在代码中实现这一点。或者类似的东西。
答案 3 :(得分:0)
尝试:
SELECT handle, count(*) as kills
FROM players as p
JOIN Kills as k ON k.gid = p.gid
WHERE gid="3245"
AND team="axis"
ORDER BY kills DESC LIMIT 0, 10;
答案 4 :(得分:-1)
根据我的经验,限制中的偏移(LIMIT 0,10)是性能杀手。 如果您不限制并循环通过资源仅提取前十个记录行, 那么它将大大加快查询。 为什么?您不会获取完整资源,只需将资源指针移动到资源的末尾即可。 只有前十行受到影响,其他行被丢弃。资源有多大并不重要。就试一试吧。你会看到!
即。用PHP
$res=mysql_query("SELECT handle,
(
SELECT COUNT(*)
FROM kills
WHERE killer=p.handle
AND k_team != c_team
AND gid=p.gid
) AS kills
FROM players as p
WHERE gid="3245"
AND team="axis"
ORDER BY kills DESC;");
$i=0;
$results = array();
while($row=mysql_fetch_array($res)){
if($i<10){
$results[] = $row;
}
$i++;
}
只有LINUX!
WINDOWS:
$i=0;
$results = array();
while($row=mysql_fetch_array($res)){
if($i<10) {
$results[] = $row;
} else {
mysql_close($db);
break;
}
$i++;
}
假设indeces设置得很好。