简体   繁体   English

简单的MySQL查询需要很长时间

[英]Simple MySQL-query takes ages

We are running a stats site for a bunch of games, but after the log has tipped over 100 megs, things are starting to slow down, so we need to optimize our queries. 我们正在运行一个统计网站,用于一堆游戏,但是在日志记录超过100兆之后,事情开始放慢速度,因此我们需要优化查询。

However, we've found out that what we thought was a simple query, takes about 1.5 secs: 但是,我们发现我们认为这是一个简单的查询,大约需要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;

This produces a result list for one of the teams. 这将为其中一个团队生成结果列表。

Table kills and players consists of 36000 and 4000 rows respectfully. 桌杀人数由36000和4000行组成。

Why is that query taking so long and how can it be optimize? 为什么该查询需要这么长时间,并且如何进行优化? Should we perhaps look into JOIN? 我们也许应该考虑加入吗?

Best regards, Laka 最好的问候,拉卡

In general, MySQL performs joins faster than subselects. 通常,MySQL执行连接的速度比子选择更快。 To learn how to optimize queries, I suggest reading up on the EXPLAIN syntax. 要学习如何优化查询,我建议您阅读EXPLAIN语法。

First, ensure your kills table has a compound index on killer and gid, then try this join: 首先,确保您的kills表在killer和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

Seeing the CREATE TABLE statement for those two tables would help determine any issues with your indexes. 查看这两个表的CREATE TABLE语句将有助于确定索引的任何问题。

Have you tried putting an index on the kills table killer column? 您是否尝试过在kills table killer列上添加索引?

Edit Info on indexes. 编辑索引信息。 http://www.w3schools.com/Sql/sql_create_index.asp http://www.w3schools.com/Sql/sql_create_index.asp

Yes, you should definitely look into joins. 是的,您绝对应该研究联接。 It's hard to tell from the snippet you posted, but whenever you can use a join over a subquery, it will be beneficial to do so. 很难从您发布的代码片段中看出来,但是只要您可以在子查询上使用联接,这样做将是有益的。

You may also want to consider caching kill count somewhere else in your database; 您可能还需要考虑在数据库中的其他位置缓存非命中计数; especially if you're using InnoDB, a COUNT() operation takes more time than simply SELECTing a [relatively] recent value from the database. 尤其是在使用InnoDB的情况下,COUNT()操作比从数据库中选择[相对]最近的值要花费更多的时间。 You can probably implement this easily in the code by incrementing the kill count on the appropriate record, or something like that. 您可以通过在适当的记录或类似的记录上增加终止计数来在代码中轻松实现此目的。

Try: 尝试:

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;

For my experience the offset in the limitation (LIMIT 0,10) is the performance killer. 以我的经验,限制的偏移量(LIMIT 0,10)是性能的杀手。 If you do not limit and loop thru the resource only extracting the first ten record rows, then it will fasten the query dramatically. 如果您不限制并循环资源仅提取前十个记录行,那么它将极大地固定查询。 Why? 为什么? You do not fetch the full resource, just shifting the resource pointer to the end of the resource. 您不会获取完整的资源,只是将资源指针移到资源的末尾。 Only the first ten rows are affected, the others are thrown away. 仅前十行受影响,其他行被丢弃。 Does not matter how big a resource is. 不管资源有多大。 Just try it. 去尝试一下。 You 'll see! 你会看到的!

ie in PHP 即在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++;
}

Only LINUX! 只有LINUX!

WINDOWS: 视窗:

$i=0;
$results = array();
while($row=mysql_fetch_array($res)){
    if($i<10) {      
      $results[] = $row;
    } else {        
        mysql_close($db);
        break;
    }
     $i++;

}

Assuming indeces are setted well. 假设指标设置正确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM