Комментарии 16
Интересно, что пользователи используют такую конструкцию IN (VALUES(1),(2)...) и видят замедление запроса, и пытаются это понять, но это им не очевидно. Это из реальных вопросов программистов. То, что IN - это два разных оператора в случае массива справа и набора данных из одного поля справа - это не очевидно. Соответственно, не очевидно, что надо запрос переделать на более оптимальный.
Хм, я думал, программисты Дейта читают - он вроде в универе был основным учебником. Там он в каждой книге талдычит эту особенность, описывая реляционную модель данных, плешь уже проел в мозгу. С другой стороны, если бы было так, то и этот пост был бы ни к чему ;)
Может быть об этом надо дополнительно сказать в документации к IN. Тем более, что оба оператора IN описываются в двух разных разделах. Пока на грабли не наступят, не обратят на это внимание. Как из вопросов про английский:"Иногда вижу has, иногда had - никак не пойму разницу, почему буква на конце разная"
Сейчас фича проходит испытания. Учитывая, что зависимости от версии ядра минимальны - структура query tree достаточно стабильна, и нет причин модифицировать код, то она может использоваться в Postgres версии 10, а может быть даже и ранее.
Очень похоже, что конкретно эта тема не пройдет, хотя сама идея автоисправления подозрительных запросов любопытна.
Но, насколько я могу судить, общая тенденция все-таки в сторону оптимизаций планировщика под запрос, а не наоборот - хотя и там не все идет гладко.
Хм, по ссылке совсем другая имплементация. Я посмотрел в нее - она выглядит слегка наркомански с точки зрения архитектуры Postgres - Том ещё очень мягкий ответ написал. Мы меняем уже query tree - оно в системный каталог не попадет, апгрейды не сломает и позволяет пройти проверки на допустимость преобразования, как я писал в тексте. Ну и библиотека затем, чтобы можно было использовать на настоль старых системах, насколько хватит фантазии.
Тенденция пока непонятная. Коммиттеры пока уклоняются от прямого ответа и, как следствие, пересмотра консенсуса. Но вода камень точит, посмотрим.
Есть вариант посередине: проверку на такие преобразования запускать асинхронно с низким приоритетом после отработки запроса, или батчем по запросу пользователя анализировать логи запросов. Результатом будут рекомендации где что переписать, или почему запрос медленный. И запросы не тормозим, и помогаем исправлять проблему.
А насчёт делать ли анализ по умолчанию: зависит от пользователей. Я больше OLAP занимаюсь, там пользователи аналитики, а не программисты, и запросы часто одноразовые. В результате вопрос не стоит, это необходимая фича, плохих запросов большинство. Если пользователи программисты и запрос пишется один раз а исполняется раз в минуту - то наверное проверять его каждый раз не стоит. С другой стороны, тут кеш запросов должен амортизировать время потраченное на анализ запросов.
У доп преобразований основная проблема даже другая - в их неоднозначности. Иногда выхлоп может быть позитивный, иногда нет. Поэтому тут вопрос даже больше технологический - нужно либо альтернативные планы тащить до места, где станет понятно, что в итоге лучше, либо какое-то перепланирование части дерева запроса научиться делать, если получили что-то не идеальное.
А не может быть причиной то, что VALUES были в SQL всегда, а массивы появились в PostgreSQL значительно позднее? Традиционно PostgreSQL считает, что VALUES - это один из видов отношений, и обрабатывает его сразу, как отношение. IN ( rowset) на раннем этапе планирования преобразовывается в JOIN, и после этого момента константный VALUES поздно оптимизировать (функции и константные выражения обрабатываются позднее). Думаю, разумнее, чтобы такие вещи делал все-таки сервер, а не программисту DB разбираться в особенностях планировщика - у программиста DB своих проблем на своем уровне хватает.
Традиционно PostgreSQL считает, что VALUES - это один из видов отношений
А куда ему родному деваться-то? Так реляционная алгебра постулирует.
разумнее, чтобы такие вещи делал все-таки сервер, а не программисту DB разбираться в особенностях планировщика
На это уже давненько ответил Том Лэйн. Он весьма обоснованно заметил, что здесь мы ущемим права тех, кто таки оптимизирует запросы и хочет выжимать максимум за счет своего интеллекта. Так что скорее в энтерпрайзах такое можно ожидать.
А куда ему родному деваться-то? Так реляционная алгебра постулирует.
Тут даже более приземленно - для планировщика это одно из отношений (с типом VALUES) и он ничего не знает о его содержимом, так как его окончательное содержимое выдаст экзекьютор, выполнив этот узел.
Пока parser отдельно не выделяет константные VALUES (без условий, сортировок и LIMIT), планировщик ничего не сможет сделать
На самом деле, апстрим умеет преобразовывать одно-элементный VALUES в просто константу. Просто для более одного элемента там возможны варианты, и только в случае выражения ANY его корректно преобразовывать.
Насчет парсера я не понял - мы делаем преобразование не в парсинге, а непосредственно перед оптимизацией - поскольку хочется затронуть и параметры, и иммютабельные функции - по-максимуму преобразовать, что возможно, в константу. Ну и при желании, можно расширить для ситуации с подзапросом - когда там не просто VALUES, а еще по нему вычисляется нетривиальное выражение А(x) - плюс сортировки, лимиты... Фантазия ограничена только вычислительными ресурсами :)
Про парсер - я имею в виду, что парсер создал для VALUES двумерный массив выражений (строка-столбец). Эти выражения могут давать константный результат, то это не известно - для этого надо вычислить значения этих элементов. На этапе парсера и на этапе начала планирования нельзя сказать, из константных элементов состоит VALUES или там есть переменные. А когда уже можно сказать, то уже поздно что-то менять. Интересно, а mssql как делает планирование таких VALUES. У меня под рукой его нет.
Ок, понятно. Поэтому мы и делаем преобразование на пре-оптимизационной стадии в планнере. Таким образом, мы разрешаем даже функции и параметры (см. патч в хакерсах).
Про MSSQL действительно, хотелось бы иметь хотя бы простую машину под рукой, чтобы сравнивать.
А вот, кстати, и вариант для тестирования https://sqlize.online/sql/mssql2017/2fed3c7e1c23a573e04630837f8f82a8/
Пробовал я много онлайн-движков. У них примерно одинаковые проблемы: 1) не позволяют прогнать что-то более-менее существенное по размеру базы. нагрузке и 2) Крайне ограничены в анализе - нужно что-то вроде инстанса БД на azure, чтобы была возможность гибко конфигурить систему, добавлять.удалять индексы, статистики, удобно варьировать запрос ... Иначе очень долго получается.
PostgreSQL 'VALUES -> ANY' transformation: должна ли СУБД делать работу за пользователя?