[英]Simple MySQL-query takes ages
我們正在運行一個統計網站,用於一堆游戲,但是在日志記錄超過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行組成。
為什么該查詢需要這么長時間,並且如何進行優化? 我們也許應該考慮加入嗎?
最好的問候,拉卡
通常,MySQL執行連接的速度比子選擇更快。 要學習如何優化查詢,我建議您閱讀EXPLAIN語法。
首先,確保您的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
查看這兩個表的CREATE TABLE語句將有助於確定索引的任何問題。
您是否嘗試過在kills
table killer
列上添加索引?
是的,您絕對應該研究聯接。 很難從您發布的代碼片段中看出來,但是只要您可以在子查詢上使用聯接,這樣做將是有益的。
您可能還需要考慮在數據庫中的其他位置緩存非命中計數; 尤其是在使用InnoDB的情況下,COUNT()操作比從數據庫中選擇[相對]最近的值要花費更多的時間。 您可以通過在適當的記錄或類似的記錄上增加終止計數來在代碼中輕松實現此目的。
嘗試:
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;
以我的經驗,限制的偏移量(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!
視窗:
$i=0;
$results = array();
while($row=mysql_fetch_array($res)){
if($i<10) {
$results[] = $row;
} else {
mysql_close($db);
break;
}
$i++;
}
假設指標設置正確。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.