Mysql запрос оптимизации - PullRequest
0 голосов
/ 01 декабря 2009

Я работаю над проектом Rails и сталкиваюсь с проблемой производительности. Вот упрощенная схема БД

table gaming_platforms ( ~5 rows)
  id

table games ( ~10k rows)
  id
  gaming_platform_id
  winner             (black or white or n/a)
  black_id           => online_players.id
  white_id           => online_players.id

table online_players ( ~1k rows)
  id
  gaming_platform_id
  username

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

Я создал 3 просмотра, чтобы избежать проблемы 1 + n.

create or replace view online_player_games as
      select online_players.id as online_player_id, count(*) as games 
      from games
      left join online_players 
      on games.gaming_platform_id = online_players.gaming_platform_id and 
      (games.black_id = online_players.id or games.white_id = online_players.id)
      group by online_players.id;

create or replace view online_player_won_games as
      select online_players.id as online_player_id, count(games.id) as games 
      from online_players 
      left join games on games.gaming_platform_id = online_players.gaming_platform_id and 
      ((games.winner = 1 and games.black_id = online_players.id) or (games.winner = 2 and games.white_id = online_players.id))
      group by online_players.id;

create or replace view online_player_lost_games as
      select online_players.id as online_player_id, count(games.id) as games 
      from online_players
      left join games on games.gaming_platform_id = online_players.gaming_platform_id and 
      ((games.winner = 2 and games.black_id = online_players.id) or (games.winner = 1 and games.white_id = online_players.id))
      group by online_players.id;

Без использования какого-либо индекса требуется более 20 секунд для запроса этих представлений. Запрос выглядит сложным. Я не уверен, какие индексы я должен создать. Любые мнения или предложения приветствуются.

Ответы [ 2 ]

1 голос
/ 02 декабря 2009

Я думаю, у вас есть некоторые общие проблемы с масштабируемостью в вашем дизайне. Когда вы добавляете игры и пользователей, то как вы подсчитываете их выигрыши / проигрыши, с точки зрения ввода-вывода станет значительно больше работы для вашей базы данных.

Я бы предложил создать таблицу с именем player_record, которая будет просто ID игрока, WINS, LOSSES. Затем создайте хранимую процедуру, которая вызывается, когда игра заканчивается. (скажем, spGameFinished(game_id, winner,..);) Эта хранимая процедура будет отвечать за выполнение любых задач, необходимых для завершившейся игры, и одна из этих задач - обновить таблицу player_record, в зависимости от того, кто объявлен победителем. Я предполагаю, что когда игра начинается, вы вводите игру с идентификаторами для двух игроков, но если вы этого не сделаете, хранимая процедура должна будет принять их и по завершении игры.

Как только это будет сделано, запросы, необходимые для сбора информации о выигрышах / проигрышах, станут тривиальными. Это также позволяет вам управлять требованиями к хранению игр отдельно от записей игроков. (то есть вы можете отбрасывать действительно старые игры, не влияя на запись пользователя)

0 голосов
/ 02 декабря 2009

Я создал новую таблицу online_player_stats со столбцами: online_player_id, games_as_black, games_won_as_black, games_lost_as_white, ...

Я также создал хранимые процы increment_online_player_stats и decment_online_player_stats, которые вызываются триггерами вставки / обновления / удаления.

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

Звучит ли это разумным решением?

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