выполнения запросов?
cte with с предварительным select из большой таблицы либо сразу куча join в одном select дают одинаковый план выполнения
запрос1; запрос2; ...; запросN;, например. ;) В чём на самом деле вопрос? > дают одинаковый план выполнения Ну и прекрасно, IMNSHO. Т.е. зачем Вам нужно, чтобы было как-то иначе?
Имеете в виду вручную создать временную таблицу с select болбшой таблицы, а затем соединять с остальными табл в одном select?
меня тут помидорами закидают но посмотри прогу navicat там есть билдер запросов
Я имею в виду то, что этим вообще не стоит заниматься (это что, попытка втащить query hints в наш PostgreSQL?). Если нет — Вы можете, объяснить, зачем Вам это нужно?
Оптимизация, не могу или лень заполнить данными БД. Отфильтровать большую, лишь потом join-ить
Т.е. всё-таки hints, так? Оптимизация — это проблема планировщика запросов, поэтому мой совет — не заниматься подобной ерундой (это нередко плохо кончается даже у тех, кто знает, что делает).
Мне говорили что такое можно сделать только в оракл, а в постгрес никак
https://wiki.postgresql.org/wiki/OptimizerHintsDiscussion
А почему бы ни добавить хинты, которые планировщик не будет напрямую использовать, а хотя бы сравнивать с тем, что у него без хинтов получается, и брать лучший вариант их 2-ух (с хинтами и без)?
Хмм... потому что это совершенно бесполезно почти во всех случаях? Вы представляете, как работает планирование запросов в общем (в т.ч. в других СУБД) и как в него встраиваются "обычные" hints? Если да, то почему Вам кажется, что "брать лучший вариант их 2-ух" вообще может работать? Если же Вы имеете в виду какие-то необычные hints — то какие? И, опять-таки: "If you have an idea that avoids the problems that have been observed with other hint systems, that could lead to valuable discussion." А Ваше предложение как позволяет избежать этих проблем?
На самом деле -- хинты для postgres давно есть, https://osdn.net/projects/pghintplan/ Кажэтся, дажэ работают (хотя я и большой любитель хинтов -- но по факту во всех проектах пока что изнасилование costs и прочих статистик вполне давало результат, так что заморачиваться сборкой расшырения мне всегда было лень).
Или, замечу, не изнасилование костов, а переписывание запроса на несколько разделённых барьером этапов в нужной мне последовательности.
Нет, не представляю, как встраиваются хинты. На мой взгляд хинт "диктует", а я хотел бы, чтобы хинт подсказывал на альтернативный план, а что выбрать пусть PG разбирается.
Ну вот посмотрите хотя бы на https://t.me/pgsql/310070 — встраиваются хинты обычно как-то так. Суть большинства "обычных" hints в том, что они искусственно ограничивают выбор планировщика (как "наши" enable_*). Естественно, такое (в т.ч. pg_hint_plan) в core PostgreSQL не нужно, по указанным в приведённой ссылке причинам. > чтобы хинт подсказывал на альтернативный план Как "подсказывал", т.е. почему PostgreSQL должен выбрать его вместо альтернативного?
Да-да, я как раз разглядываю его сейчас. Выглядит ужасно и да, очень похоже на enable_*. Я имел ввиду не "подсказывал", а "предлагал рассмотреть". Соответственно вариант с подсказкой PG рассматривает и подсчитывает costs там. Потом смотрит на costs с подсказкой и на costs без подсказки и выбирает лучший. Имеет смысл видимо для запросов с большим количеством join-ов. В подсказке ещё нужно дать возможность указывать, что первым join-ить, а что потом. С малым числом join-ов PG итак справляется.
> Имеет смысл видимо для запросов с большим количеством join-ов. Ну вот я поэтому и написал "это совершенно бесполезно почти во всех случаях". А hints обычно хотят использовать совсем с другими целями. ;)
Понятно, т.е. редкие use case-ы как бы не рассматриваются?
Рассматриваются, но анализ выгод и затрат очевидно приводит к We are not interested in implementing hints in the exact ways they are commonly implemented on other databases. Proposals based on "because they've got them" will not be welcomed. И это же общий принцип, согласно которому отвергаются все подобные "улучшения" планировщика.
А что он должен делать с этими "предложениями"? Он и так рассматривает все разумные варианты джойнов. Единственный вариант, когда это было бы полезно - когда в запросе таблиц больше чем geqo_threshold (возможно, неправильно название параметра привёл), т.е., когда включается генетический оптимизатор.
Да, я писал про этот вариант. А другие хинты, которые не на основе costs, я вообще не понимаю, потому что можно легко придумать пример, когда они дадут неоптимальный план.
Интересно, а порядок следования таблиц в запросе не влияет на то, в какой последовательности geqo будет перебирать варианты? Если влияет, то выходит, что хинты и не нужны, достаточно перестановками добиться того, чтобы генетический алгоритм находил быстрый план. Хотя, конечно, это трудоёмкий метод.
Хм... Получается, что хинты уже есть. Спасибо)
Ещё чуть-чуть подумал и... всё-таки нет, не достаточно. Возможно будет хотеться соединять попарно разные таблицы, а потом их результаты соединять (в предположении, что результаты первых соединении содержат мало данных).
Я вот, например, сходу даже не помню (потому что таких запросов — единицы, особенно если поднять from_collapse_limit и join_collapse_limit), но необязательно перестановками удастся вообще чего-то добиться (потому что GEQO не перебирает варианты последовательно, поэтому тут как повезёт).
Если знаете, что какие-то две таблицы дадут немного данных, можете их спрятать под CTE. Собственно, у меня был опыт оптимизации запросов, написанных по беспощадной аналитике (выводим кучу полей с расшифровками, плюс довольно сложные правила доступа к данным и динамические условия отбора + сортировки), но почти всегда была возможность переписать запрос так, чтобы не попадать на geqo. За одним исключением, в котором почему-то geqo работал лучше (но, вроде, после решения проблем с условиями, селективность которых не получалось нормально оценить, его тоже упростили).
> Если знаете, что какие-то две таблицы дадут немного данных, можете их спрятать под CTE. Уже (в последних версиях) бесполезно. ;) > почти всегда была возможность переписать запрос так, чтобы не попадать на geqo При стандартных настройках на GEQO вообще невозможно "попасть", если правильно помню (в отличие от *_collapse_limit).
А разве при превышении collapse_limit не используется geqo?
> Уже (в последних версиях) бесполезно. ;) В смысле бесполезно? Не помню, чтобы отменяли материализованные CTE.
В последних версиях можно добавить слово materialize возле CTE.
Кстати, это тоже hint.
Нет, это не hint. Если бы удалось сохранить такое же поведение запросов (в смысле сохранения результатов), как до v12, в абсолютно всех случаях, никакого MATERIALIZED почти наверняка не было бы.
Звучит так, как будто бы с materialized сохраняется как по-другому иногда, не так как было до версии 12. Как может по-другому сохраняться результат?
Я знаю, что поведение по умолчанию поменяли, но сама возможность материализации осталась (и я именно этот вариант имел в виду). Кстати, даже если бы не было with materialized, можно было бы для материализации по стандартным правилам (которые включают материализацию cte, используемых более одного раза) обмануть планировщик, применив этот cte в каком-нибудь месте запроса, которое бы по факту не использовалось.
Да, добавление [NOT] MATERIALIZED может изменять результаты запроса, или приводить к тому, что запрос станет завершаться с ошибкой (или наоборот).
"Обмануть"-то всегда можно, там правил более чем достаточно для этого.
А то, что не используется, PG не будет выполнять? Такие запросы могут вводить в заблуждение. Другим будет хотеться удалить неиспользуемую часть в запросе.
Ну если при построении плана окажется, что там неявный ложный предикат в одном из подзапросов, объединённых по union all, то, вроде, должен его убрать. Что касается материализованных cte - лучше проверить. Как минимум, dml cte (insert/update/delete) выполнятся независимо от использования.
Обсуждают сегодня