2009-04-18 16 views
0

ゲームのために統計サイトを実行していますが、ログが100メガ以上になった後、状況が減速し始めているので、クエリを最適化する必要があります。シンプルなMySQLクエリには年齢がかかります

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; 

これは、チームのいずれかの結果リストを生成します。

しかし、我々は、約1.5秒を要し、私たちが考えたことは単純なクエリだったことが判明しました。

テーブルキルとプレイヤーは、それぞれ36000と4000行で構成されています。

なぜこのクエリは時間がかかり、どのように最適化できますか?おそらくJOINを調べるべきでしょうか?

敬具、 ラカ

+0

テーブル 'キル'には、gid以外のプレーヤーにはFKがありますか? –

答えて

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文を見て。

+1

つまり、ALTER TABLEはADD INDEX( 'killer'、' gid')を殺します。 ALTER TABLEプレイヤーADD INDEX( 'handle'、' gid'); –

+0

ニース。しかし、私はあなたの質問に誤りがあります - AND "p.team =" axis "AND k.k_team!= k.c_team GROUP BY p.handle ORDER BY n_ki 'on line 1" –

+0

Btw、すべての列? –

1

あなたはkillsテーブルkiller列にインデックスを入れてみましたがありますか?

索引に関する情報。 http://www.w3schools.com/Sql/sql_create_index.asp

+0

CREATE INDEXの意味は?どのような種類のインデックスですかより具体的にできますか? –

0

はい、間違いなく結合を調べる必要があります。投稿したスニペットからはわかりにくいですが、サブクエリを介して結合を使用できるときはいつでもそうするのが有益です。

データベース内の他の場所でkill countをキャッシュすることを検討することもできます。特にInnoDBを使用している場合は、データベースから[最近の]比較的近い値を単に選択するよりも、COUNT()操作に時間がかかります。おそらく、適切なレコードのkill countをインクリメントすることで、これをコードに簡単に実装できます。

+0

ほとんどのデータベースは、実行前にクエリを最適化しようとします – Marius

+1

クエリを最適化する必要がないと言っていますか? – Calvin

+0

不適切なコードをリファクタリングするためにデータベースエンジンに依存する必要はなく、最適化は必要に応じて控えめであり、データベースは必ずしも – jeffcook2150

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; 
+0

"ERROR 1052(23000):where節でgid 'が曖昧である"というエラーメッセージが表示されます。プレイヤーのハンドルは「プレイヤー」に格納され、キルは「キル」に格納されます –

+0

where句をp.gidに変更し、 p.team –

-1

私の経験上、制限のオフセット(LIMIT 0,10)はパフォーマンスキラーです。 最初の10個のレコード行を抽出するリソースのみを制限してループしない場合は、 というクエリーが劇的に固定されます。 なぜですか?フルリソースをフェッチせず、リソースポインタをリソースの最後に移動するだけです。 最初の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はよくsettedされています。

関連する問題