2009-04-18 2 views
0

Мы запускаем сайт статистики для кучи игр, но после того, как журнал опрокинул более 100 мегабайт, все начинает замедляться, поэтому нам нужно оптимизировать наши запросы.Простой 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 рядов с уважением.

Почему этот запрос занимает так много времени и как его можно оптимизировать? Должны ли мы, возможно, заглянуть в ПРИСОЕДИНЕНИЕ?

С наилучшими пожеланиями, лыка

+0

У игрока «Kills» есть ли FK для игроков, кроме gid? Кажется, что вам не хватает команды «team =» axis, если только gid недостаточно. –

ответ

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

Ницца. Но я получаю сообщение об ошибке - «near» AND p.team = «axis» AND k.k_team! = K.c_team GROUP BY p.handle ORDER BY n_ki 'в строке 1 " –

+0

Кстати, следует ли использовать индекс на каждый столбец? –

1

Вы пробовали положить индекс на kills таблицы killer колонке?

Редактировать Информация об индексах. http://www.w3schools.com/Sql/sql_create_index.asp

+0

С CREATE INDEX вы имеете в виду? Какой тип индекса? Можете ли вы быть более конкретным? –

0

Да, вы должны обязательно посмотреть на объединения. Трудно сказать из опубликованного фрагмента, но всякий раз, когда вы можете использовать соединение над подзапросом, это будет полезно для этого.

Возможно, вы также захотите рассмотреть вопрос о кешировании в другом месте в вашей базе данных; особенно если вы используете InnoDB, операция COUNT() занимает больше времени, чем просто ВЫБОР [относительно] недавнего значения из базы данных. Вероятно, вы можете легко реализовать это в коде, увеличив количество убийств на соответствующей записи или что-то в этом роде.

+0

большинство баз данных попытаются оптимизировать запрос перед его запуском Это относится и к запросам с подзапросами. – Marius

+1

Вы говорите, что нет необходимости оптимизировать ваши запросы вообще? – Calvin

+0

Нельзя полагаться на свой механизм базы данных для рефакторинга неправильного кода, оптимизация по необходимости консервативна, и база данных не всегда может убедитесь, что вы намерены. Оптимизации там, чтобы помочь заполнить пробелы, а не переписывать всю вашу программу для здравомыслия и производительности, это ваша работа. – jeffcook2150

0

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

«ОШИБКА 1052 (23000): Столбец« gid »в том месте, где предложение неоднозначно». нет «убивает» игроков. Ручка игроков хранится в «игроках», а убийства сохраняются в «убивает». –

+0

изменить предложение where на p.gid и p.team –

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

} 

Предполагая, что являются выставиться Индексы хорошо.

Смежные вопросы