2009-04-18 251 views
0

我们正在为一堆游戏运行一个统计站点,但是在日志已经超过100MB后,事情开始放缓,所以我们需要优化我们的查询。简单的MySQL查询需要很长的时间

然而,我们发现,我们认为是一个简单的查询,需要大约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行恭敬地。

为什么这个查询需要这么长时间,它如何优化?我们应该看看JOIN吗?

最好的问候, 拉卡

+0

表'杀死'是否有GID以外的玩家FK?看起来你缺少'team ='axis'join,除非gid足够。 – 2009-04-18 18:53:23

回答

3

一般情况下,MySQL的执行比加入快子查询。要了解如何优化查询,我建议阅读EXPLAIN语法。

首先,确保你的杀敌表有杀手和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语句这两个表将帮助确定您的索引的任何问题。

0

是的,你应该看看连接。很难从你发布的代码片段中知道,但是只要你可以在子查询上使用连接,那么这样做会有好处。

您可能还想考虑缓存kill count在数据库的其他地方;特别是如果你使用的是InnoDB,COUNT()操作比从数据库中选择[相对]最近的值需要更多的时间。您可以通过在适当的记录上增加kill count或类似的东西,在代码中轻松实现这一点。

+0

大多数数据库会在运行之前尝试优化查询。这适用于有子查询的查询。 – Marius 2009-04-18 17:46:12

+1

你是说根本不需要优化你的查询吗? – Calvin 2009-04-18 18:02:51

+0

不应该依靠他的数据库引擎来重构不适当的代码;优化是必要的保守,数据库不能总是确定你的意图,优化有助于填补空白,而不是重写你的整个程序的理智和表现;这是你的工作 – jeffcook2150 2009-04-18 18:06:29

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; 
-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被设置好的良好。