У меня проблема с моим запросом SQL:
Таблица цен насчитывает миллионы строк и должна запрашиваться правильно. Все работало нормально, и загрузка страницы заняла ~ 400 мс, пока я не обновил БД (обновил ее новой БД из нашей Prod DB), и она все сломала. Теперь загрузка страницы занимает 120 секунд.
Он отлично работает в наших средах prod и pre prod, но очень медленный в моей среде разработки. Я работаю с той же версией mysql и версией php. Использование Symfony 4 с доктриной 2 ORM.
Запрос, над которым я работаю, следующий:
SELECT
c0_.id AS id_0,
c0_.ticker AS ticker_1,
c0_.name AS name_2,
p1_.id AS id_3,
p1_.rank AS rank_4,
p1_.price_usd AS price_usd_5,
p1_.1d_volume_usd AS 1d_volume_usd_6,
p1_.change_1h AS change_1h_7,
p1_.change_1d AS change_1d_8,
p1_.change_7d AS change_7d_9,
c2_.id AS id_10,
c2_.market_cap AS market_cap_11,
s3_.id AS id_12,
s3_.score_buzz AS score_buzz_13,
s3_.score_average AS score_average_14
FROM coins c0_
LEFT JOIN prices p1_ ON c0_.id = p1_.ticker_id
AND (p1_.last_updated >= ?) LEFT JOIN cmc c2_ ON c0_.id = c2_.ticker_id
AND (c2_.last_updated >= ?) LEFT JOIN scores s3_ ON c0_.id = s3_.ticker_id
AND (s3_.to_datetime >= ?)
WHERE c0_.is_active = 1 ORDER BY c0_.rank_cmc ASC, p1_.last_updated DESC, c2_.last_updated DESC, s3_.to_datetime DESC
проблема исходит из этой части:
LEFT JOIN prices p1_ ON c0_.id = p1_.ticker_id AND (p1_.last_updated >= ?)
Если я уберу эту часть, она будет работать нормально. Откуда может появиться ПБ? почему у меня 2 разных поведения (prod и dev) для одного и того же запроса? Как вы обычно обрабатываете левое соединение на больших столах?
Спасибо
РЕДАКТИРОВАТЬ: Вот объяснение запроса в DEV:
Вот объяснение запроса в PROD:
EDIT2: Dev индексы по цене:
Там может быть множество причин. Вы видите быстрый результат на своем сервере разработки, так как меньше записей, в то время как ваш живой сервер состоит из большого количества записей (см. Столбец rows
в операторе объяснения).
Я рекомендую проверить все ключи и тип вашего столбца join
. Каждый столбец, используемый в соединении с предложением " on
", должен иметь сходный тип, иначе он будет замедлен. Поэтому убедитесь, что столбцы int+unsigned
или varchar
и т.д.
Найдите в вашем выводе possible_key, key and extra
столбец и попытайтесь понять по следующей ссылке, которая поможет вам найти правильное решение.
https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
Также см. Раздел "ПОЯСНИТЕ ИНТЕРПРЕТАЦИЮ ВЫХОДА" по вышеуказанной ссылке
rank, ticker_id and last_updated
Какое здесь rank, ticker_id and last_updated
? LEFT JOIN prices p1_ ON c0_.id = p1_.ticker_id AND (p1_.last_updated >= ?)
Попробуйте добавить индекс к указанным выше столбцам id, ticker_id, last_updated
Посмотрите на запрос prod и dev объясните, на строчке p1_ для столбца 'key': в dev это NULL, в prod это search_idx.
Вывод: если вы запускаете "bin/console d: s: u --dump-sql" в среде prod и dev, вам нужно найти некоторую разницу в схеме дБ.