Where var IN (…)
Mar. 27th, 2017 11:36 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Знал я что where field in (…) — довольно дорогая конструкция, но чтобы на столько!
Иногда приходится её использовать в тех случаях, когда расходы на неё совсем небольшие, а методы обхода оказываются гораздо дороже.
Была старая задача, которая генерировала сводку по нескольким таблицам. В таблицах — результаты работы измерительных программ по изменению нагрузки. Ключевые параметры — дата/время, период, объект измерения. Данные собираются по 5, 15, или часовым интервалам. И тут нужно нарисовать табличку: колонка - дата, строка - параметр. Диапазон дат — до месяца, но не подряд, а выборочно. Вот тут-то и корячится where date in (date1, …, dateN). Свинство в том, что поля date нет, а есть datetime, то есть timestamp. А значит нужно делать или date(datetime), или substr(datetime, 1, N) в тех случаях, когда группировка по другим критериям. А это тоже накладно. Потом ещё будет group by по этому полю. Но where вырастает в date(datetime) in (…) и работает, соответственно, гораааздо дольше. Пока табличка была маленькая, всё работало довольно шустро. Но вот данных за год нападало уже на 23 миллиона и запрос стал выбираться несколько секунд. А это неприятно. Пришлось брать из загашников бубен. ;)
Первым делом попытался ограничить область поиска дополнительным условием. Т.е. минимальная и максимальная даты определяют вилку, за пределами которой можно ничего не искать.
Не помогло.
Без особой надежды решил убрать in (…) вообще, благо алгоритм обработки получаемых данных был построен так, что заполнял таблицу только нужными датами, а поправить нужно было только подсчёт итоговых значений, что делается одной строчкой.
Запускаю — и удивляюсь. Вместо нескольких секунд запрос стал выполняться доли секунды.
И это при том, что из-за group by калькуляция в запросе вынуждена выполняться над лишними датами!
Ладно, думаю. Может этот период просто незаполнен и пока ещё нечего считать? Делаю запрос за прошлый год и картина почти такая-же. Значит на самом деле 8*SUM+2AVG за 20 дней (по 288 измерений) выполняется гораздо быстрее, чем то же самое с IN (date1..date20).
«Вот что крест животворящий делает»©
Иногда приходится её использовать в тех случаях, когда расходы на неё совсем небольшие, а методы обхода оказываются гораздо дороже.
Была старая задача, которая генерировала сводку по нескольким таблицам. В таблицах — результаты работы измерительных программ по изменению нагрузки. Ключевые параметры — дата/время, период, объект измерения. Данные собираются по 5, 15, или часовым интервалам. И тут нужно нарисовать табличку: колонка - дата, строка - параметр. Диапазон дат — до месяца, но не подряд, а выборочно. Вот тут-то и корячится where date in (date1, …, dateN). Свинство в том, что поля date нет, а есть datetime, то есть timestamp. А значит нужно делать или date(datetime), или substr(datetime, 1, N) в тех случаях, когда группировка по другим критериям. А это тоже накладно. Потом ещё будет group by по этому полю. Но where вырастает в date(datetime) in (…) и работает, соответственно, гораааздо дольше. Пока табличка была маленькая, всё работало довольно шустро. Но вот данных за год нападало уже на 23 миллиона и запрос стал выбираться несколько секунд. А это неприятно. Пришлось брать из загашников бубен. ;)
Первым делом попытался ограничить область поиска дополнительным условием. Т.е. минимальная и максимальная даты определяют вилку, за пределами которой можно ничего не искать.
Не помогло.
Без особой надежды решил убрать in (…) вообще, благо алгоритм обработки получаемых данных был построен так, что заполнял таблицу только нужными датами, а поправить нужно было только подсчёт итоговых значений, что делается одной строчкой.
Запускаю — и удивляюсь. Вместо нескольких секунд запрос стал выполняться доли секунды.
И это при том, что из-за group by калькуляция в запросе вынуждена выполняться над лишними датами!
Ладно, думаю. Может этот период просто незаполнен и пока ещё нечего считать? Делаю запрос за прошлый год и картина почти такая-же. Значит на самом деле 8*SUM+2AVG за 20 дней (по 288 измерений) выполняется гораздо быстрее, чем то же самое с IN (date1..date20).
«Вот что крест животворящий делает»©