Как обрабатывать левые соединения на больших столах? Неожиданное поведение

0

У меня проблема с моим запросом 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: Изображение 174551

Вот объяснение запроса в PROD: Изображение 174551

EDIT2: Dev индексы по цене: Изображение 174551

  • 0
    Вы используете MySQL или MS SQL Server?
  • 0
    Я использую mysql
Показать ещё 10 комментариев
Теги:
sql-server

2 ответа

0

Там может быть множество причин. Вы видите быстрый результат на своем сервере разработки, так как меньше записей, в то время как ваш живой сервер состоит из большого количества записей (см. Столбец rows в операторе объяснения).

Я рекомендую проверить все ключи и тип вашего столбца join. Каждый столбец, используемый в соединении с предложением " on ", должен иметь сходный тип, иначе он будет замедлен. Поэтому убедитесь, что столбцы int+unsigned или varchar и т.д.

Найдите в вашем выводе possible_key, key and extra столбец и попытайтесь понять по следующей ссылке, которая поможет вам найти правильное решение.

https://dev.mysql.com/doc/refman/8.0/en/explain-output.html

Также см. Раздел "ПОЯСНИТЕ ИНТЕРПРЕТАЦИЮ ВЫХОДА" по вышеуказанной ссылке

  • 0
    Спасибо mukund за этот ответ, между dev и prod одинаковое количество результатов, dev DB - это экспорт / импорт prod с точно такой же структурой и данными. Я проверил все ключи и индексы моих соединенных столбцов (таблица цен), и они совпадают. Из того, что я понимаю, глядя на объяснение, кажется, что SQL не использует индекс в запросе выбора в dev, когда он использует его в prod. Почему так?
  • 0
    Я вижу, добавлены индексы для: 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
Показать ещё 4 комментария
0

Посмотрите на запрос prod и dev объясните, на строчке p1_ для столбца 'key': в dev это NULL, в prod это search_idx.

Вывод: если вы запускаете "bin/console d: s: u --dump-sql" в среде prod и dev, вам нужно найти некоторую разницу в схеме дБ.

  • 0
    Спасибо Lasouze, но, к сожалению, структура БД точно такая же, от Dev до Prod, поэтому, почему я борюсь с этим, мне кажется, что это что-то отличается от выбора объяснения, но я не могу понять, как это исправить и изменить настройки моей БД, чтобы вести себя как на продукт. Спасибо
  • 0
    Можем ли мы заставить sql использовать индекс? Потому что я думаю, что вы правы, вот откуда возникла проблема, но по какой-то причине он не использует индекс в запросе выбора, где он должен его использовать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню