Как я могу оптимизировать этот запрос MySQL? - PullRequest
2 голосов
/ 30 июля 2009

Я использую следующий запрос MySQL в сценарии PHP для базы данных, которая содержит более 370 000 000 (да, триста семьдесят миллионов) строк. Я знаю, что это чрезвычайно ресурсоемкий процесс, и для выполнения этого запроса требуются годы. Кто-нибудь знает, как я могу оптимизировать запрос или получить информацию другим способом, который быстрее?

Таблица информации:

games | longint, unsigned, Primary Key
win   | bit(1)
loss  | bit(1)

Запрос:

SELECT MID(<code>game</code>,{$len},1) AS <code>move</code>,
       COUNT(*) AS <code>games</code>,
       SUM(<code>win</code>) AS <code>wins</code>,
       SUM(<code>loss</code>) AS <code>losses</code>
FROM <code>games</code>
WHERE <code>game</code>>{$something} AND <code>game</code><{$something_else}
GROUP BY <code>move</code>

Заранее спасибо за помощь!

Ответы [ 7 ]

5 голосов
/ 30 июля 2009

Единственное, что я могу сделать, - это использовать таблицу для предварительного расчета всех подсчетов и сумм для каждой игры и обновлять ее, когда таблица игра изменяется с использованием триггер.

1 голос
/ 10 августа 2009

С самого начала я бы прекратил использовать запрос MID () как в выражении SELECT, так и в GROUP BY. В зависимости от условий вашего запроса, MySQL не обязательно будет кэшировать это внутри одного выражения во время синтаксического анализа, поэтому, по крайней мере, попробуйте это:

SELECT MID(game,{$len},1) AS move,
   COUNT(*) AS games,
   SUM(win) AS wins,
   SUM(loss) AS losses
   FROM games WHERE game LIKE '{$game}%' GROUP BY move;

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

0 голосов
/ 09 августа 2009

Функция mid () убивает этот запрос. MySQL должен создать временную таблицу в памяти для работы с функцией mid () и выполнить сортировку файлов в этой таблице из-за группировки по.

Я предполагаю, что $ game - это тип игры. (шашки, шахматы, крестики-нолики)

Я бы повесил другой стол для игры. Это позволяет вашей группе использовать индекс, который будет намного быстрее.

Я предлагаю что-то вроде:

[game]
game bigint unsigned
win bit
loss bit
game_type_id bigint unsigned

[game_type]
game_type_id bigint unsigned
game_type_desc varchar(13)

Будьте осторожны с инструкциями alters на такой большой таблице. Всегда делайте резервную копию, прежде чем вводить изменения.

0 голосов
/ 30 июля 2009

Вы можете «купить скорость», пожертвовав местом для хранения или сохраняя место для хранения, но получив худшую производительность. Поскольку ваша проблема в скорости, вам понадобятся некоторые предварительные расчеты. И да, некоторое профилирование запроса.

Кстати, у «больших» были разные конфиги (разные аппаратные средства и настройки) для OLTP (для обслуживания реальных транзакций в реальном времени) и DW (для анализа больших объемов данных).

0 голосов
/ 30 июля 2009

Похоже, вы могли бы денормализовать это и создать таблицу «ходов», записывая статистику за «ход», а не только за «игру».

0 голосов
/ 30 июля 2009

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

0 голосов
/ 30 июля 2009

Я бы попробовал начать с EXPLAIN запроса или профилирования .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...