MySQL очень медленный запрос при изменении одного, где поле, несмотря на отсутствие индекса/ключа

dba.stackexchange https://dba.stackexchange.com/questions/3780

  •  16-10-2019
  •  | 
  •  

Вопрос

Это довольно запутанная проблема для меня. У меня есть база данных, полная статистики бейсбола. Запуск этого запроса:

SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN games ON games.gameName = hits.gameName
WHERE games.type = 'R'
LIMIT 50

Возвращает:

/* 0 rows affected, 50 rows found. Duration for 1 query: 0.218 sec. */

Но запустить этот запрос:

SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN games ON games.gameName = hits.gameName
WHERE games.leagueLevel = 'mlb'
LIMIT 50

Висит долго. Индекс на игровом столе - только games.gameName и ничего больше.

Выберите «Отличный тип» от игр дает 8 одноразовых строк (varchar 1), включая один нуль.

Выберите отдельный LeagueLvel из игр, дает 6 треххамерных рядов (Varchar 5), включая один нуль.

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

Спасибо за вашу помощь.

Это было полезно?

Решение

Точка зрения № 1: вам нужно взглянуть на популяцию стоимости столбца

SELECT COUNT(1) rowount,type FROM games GROUP BY type WITH ROLLUP;
SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;

Из вашего вопроса я собираю две вещи:

  1. Количество строк в играх с типом = 'r' должно быть низким числом против количества строк в таблице игр.
  2. Количество строк в играх с LeaGueLevel = 'MLB' должно быть большим количеством (больше 5% таблицы) против количества строк в таблице игры. (5%-это число правил, которое в глазах оптимизаторов запросов)

Точка зрения № 2: Вам может потребоваться рефакторировать этот запрос

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

SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN (SELECT * FROM games WHERE leagueLevel = 'mlb') games
ON games.gameName = hits.gameName
LIMIT 50;

Точка зрения № 3: Получить только те столбцы, которые вам действительно нужны

Я вижу, у вас есть выбор *, и у вас есть четыре стола (хиты, стадионы, игроки, игры). У вас будет много дубликатов данных, чтобы перетащить запрос, особенно при перетаскивании столбца имени GameName из всех четырех таблиц.

Вы должны реорганизовать запрос, чтобы принести только одну колонку GameName:

SELECT hits.gameName,hits.*,players.*,staduims.*,games.* FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN (SELECT * FROM games WHERE leagueLevel = 'mlb') games
ON games.gameName = hits.gameName
LIMIT 50;

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

Другими словами, в качестве примера, если вам нужно только имя PlayerName из таблицы игроков, вам не нужен игрок.* В выборе. Вам понадобится просто Player.playername.

Точка зрения № 4: Вам может потребоваться индексировать столбец Leaguelevel

Вам нужно будет сделать следующее, чтобы сделать необходимый индекс:

ALTER TABLE games ADD INDEX (leagueLevel);

Прежде чем сделать это, запустите это

SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;

Любое значение для LeagueLvel, чье количество превышает 5% таблицы, приведет к оптимизатору запроса MySQL не использовать индекс.

Другие советы

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

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

Вам нужно научиться использовать имеющиеся у вас инструменты, начиная с explain а также explain extended. Анкет Дайте нам знать, как вы поступаете ...

Вам просто повезло, что первый запрос вернется быстро. Я согласен с @jack Douglas, используйте объяснить, добавить необходимые индексы и повторять, пока оба запроса не улучшатся намного лучше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top