Задавайте вопросы, мы ответим
Вы не зашли.
До недавнего времени был искренне убежден, что запросы вида
Отредактированно klow (26.12.2016 16:04:17)
Неактивен
у вас было правильное убеждение
опыт, указывает на то, что где-то грабли зарыты, например, в запросах отличается список выбираемых полей, в результате первый отдает сотни мегабайт, а второй десятки килобайт.
в общем нужно копать частный случай, чтобы понять на какие грабли наткнулись.
в целом так быть не должно
Неактивен
Меняю только LEFT и больше ничего не трогаю!
Запросы не привожу, так как они достаточно сложные и основаны на многих таблицах.
Отредактированно klow (26.12.2016 20:49:44)
Неактивен
скорее всего оптимизатор изменил порядок соединения таблиц и в результате выбрал гораздо худший план.
Неактивен
Да, глянуть бы на explain обоих запросов. В частности, если подсунуть в join-запрос STRAIGHT_JOIN.
Неактивен
STRAIGHT_JOIN выполняется за 9 секунд, еще одна странность.
Планы запросов во вложении
Отредактированно klow (26.12.2016 20:59:31)
Неактивен
Есть еще одна странность. Когда запрос, с учетом параметров, обрабатывает меньше количество строк - выполняется медленнее чем на больших объемах данных.
Так для 15 тыс локаций он отрабатывает за 2 сек, для 3 локаций за 6. Результат для LEFT JOIN.
Неактивен
klow написал:
STRAIGHT_JOIN выполняется за 9 секунд, еще одна странность.
ничего странного:
left join -- 2 сек
join -- 26
STRAIGHT_JOIN похож на left, но все отличается, нужно больше подсказок оптимизатору (например, тех же STRAIGHT_JOIN)
я понимаю почему вы не стали выкладывать сами запросы
это вы такое руками пишите или они всё-таки генерятся?
ещё можно посмотреть на профайлинг, может там время расходуется на составление самого плана.
Неактивен
Пишу руками, но нужно учитывать, что 2 самых сложных запроса оформлены к качестве View и используются несколько раз в самом запросе. Иначе запрос перерос бы в невообразимого монстра.
Одна вьюха нужна для таблицы, которая ссылается сама на себя и там использую UNION до 8 раз. К сожалению MySql нет инструментов для работы с рекурсивными запросами.
Во второй вью идет предварительная выборка нужных ID и дат, а после на ней-же использую конструкцию
Отредактированно klow (27.12.2016 10:29:53)
Неактивен
Отредактировал сообщение, так как написал изначально неправильно. Спасибо vasya за упоминание. Правильно так:
JOIN - поиск строк, соответствующих левой таблице по условию. LEFT JOIN - поиск строк, соответствующих левой таблице + строк левой таблицы, для которых в правой таблице соответствий нет. JOIN дает дополнительную гибкость оптимизатору, так как может выполняться и слева направо (как STRAIGHT_JOIN или LEFT JOIN) и справа налево. Если оптимизатор ошибается, то может выбирать неоптимальный вариант для JOIN.
Неактивен
То есть утверждение, что JOIN быстрее LEFT JOIN в общем случае не корректно. Все зависит от оптимизатора. Ок.
Но почему если "детей" меньше или нет вовсе время выполнения тоже увеличивается? Или оптимизатор и тут тоже строит разные планы запроса и, возможно, ошибается?
Отредактированно klow (27.12.2016 12:39:46)
Неактивен
klow написал:
Но почему если "детей" меньше или нет вовсе время выполнения тоже увеличивается? Или оптимизатор и тут тоже строит разные планы запроса и, возможно, ошибается?
Это в общем случае звучит странно, а в частном случае может произойти по ряду причин. Может быть оптимизатор строит план исполнения в другом порядке, предпочитает полный скан или еще что-то.
Неактивен
klow написал:
К сожалению MySql нет инструментов для работы с рекурсивными запросами.
Будут в MySQL 8 и MariaDB 10.2, а пока есть возможность имитировать обобщенные табличные выражения с помощью хранимой процедуры.
Посмотрите, может окажется полезным:
WITH RECURSIVE и MySQL
Неактивен
Как мне не нравится Oracle, но его операторы CONNECT BY и PRIOR мне бы очень упростили жизнь.
Статью читал, но не смог ее применить для своего случая. Например как возвратить в SELECT результаты процедуры, когда возвращается много строк? Как в View сделать ссылку на саму себя?
Когда еще будут MySQL 8 и MariaDB 10.2, а работать нужно уже сегодня (вчера). Тем более, насколько я понял, PRIOR даже не планируется в MySql (MariaDB).
Неактивен
klow написал:
Поэтому наново привожу планы и профайлинг запроса удалив вспомогательные таблицы.
1. Вы проверяли, что временные таблицы создаются в памяти, а не на диске?
2. На таких сложных запросах оптимизатор может легко ошибиться. Экспериментально, вы знаете более выгодный план и в случае JOIN нужно с помощью подсказок добиться такого же плана.
Неактивен
Исправил сообщение #10, а то в нем была путаница. Все дело только в плане запроса, иначе JOIN должен быть быстрее, чем LEFT JOIN.
Неактивен
vasya написал:
1. Вы проверяли, что временные таблицы создаются в памяти, а не на диске?
Не проверял. Подскажите, пожалуйста, как это сделать?
Неактивен
Неактивен
Спасибо!
До
Created_tmp_disk_tables 0
Created_tmp_files 676
Created_tmp_tables 126
После
Created_tmp_disk_tables 0
Created_tmp_files 676
Created_tmp_tables 137
Я так понял, что на диск временные таблицы не скидываются.
Неактивен
Да, не сбрасываются.
Тогда нужно смотреть есть ли возможность сократить объем записываемой во временные таблицы информации за счет усложнения запроса. Например, на промежуточных этапах выбирать как можно меньше - только идентификаторы и необходимые для связей поля, а после всех действий (условия, группировки, сортировки, лимиты) подтягивать нужные данные дополнительными join. В некоторых случаях такая стратегия дает выигрыш производительности.
Неактивен
Спасибо! Еще раз проведу анализ с учетом предложений.
Неактивен
Вставлю и я свои 5 копеек .
Для хранения деревьев существует ведь несколько способов.
Подробнее рекомендую почитать в это книге (да, я нагло пиарю Билла Карвина ), там посвящена деревьям целая глава
http://www.ozon.ru/context/detail/id/7598812/
Раз Вам 8 уровней в глубину нужно - посмотрите различные методы хранения
Adjacency List («список смежности»)
Materialized Path («материализованный путь»)
Nested Sets («вложенные множества»)
Closure Table («таблица связей»)
Тут презентация от того же Карвина
http://www.slideshare.net/billkarwin/mo … hical-data
Неактивен
Спасибо! Почитаю. Хотя уже много на эту тему читал статей.
Но рекурсия это смежная тема. В основном меня удивило, что left join выполняется быстрее обычного join.
8 уровней это сейчас, а вообще это переменная величина и зависит только от пользователей.
Для меня сейчас более важно получить смежные строки. Вот проблема. На это в основном (90-97%) тратятся ресурсы, но, к сожалению, более приемлемого метода, чем описал выше, не нашел.
Неактивен