Комментарии 11
стало понятным, зачем 19 лет назад в Oracle 11i добавили sql repair advisor https://oracle-base.com/articles/11g/sql-repair-advisor-11g 🙂 Идея была такой: если запрос (select) выполнялся без ошибки, а на новой версии стал выдавать ошибку вместо данных, то sql repair advisor перебирал оптимизации (их сотни, у каждой номер), отключал эти оптимизации, выполнял запрос. Если на какой-то отключенной оптимизации ошибка исчезала, то создавался sql patch, который на лету применялся к запросу в виде хинта. В PostgreSQL для новшества в планировщике добавляют параметр конфигурации, чтобы можно было отключить новшество типа enable_something_pushdown . Но у оракл планировщик это алгоритим с логикой тысяч if then else и идентификаторов оптимизаций сотни. Разработка «на потоке» - нашли какой-нибудь запрос, исследовали как поправить его план и создают оптимизацию вставляя признаки такого запроса. Дешево, надежно и практично. В параметры выносили только то, что имело смысл вручную включать/отключать (типа параметра конфигурации star_transformation_enabled).
Возможно, разработчики Oracle, когда делали 11 версию, добавляли оптимизации по типу описанных в статье, сталкивались с ошибками. Создали внутренний инстумент и решили сделать из него advisor, так как адвайзеров было мало. Я не слышал, чтобы sql repair advisor кому-то пригодился, скорее всего, все ошибки выловили и исправили до релиза.
Встречал такие случаи в работе, приходилось выкручиваться материализацией:
with q as materialized (
select raw_data.val
from temp.raw_data
join temp.numbers using (id)
)
select q.val
from q
where cast(q.val as integer) > 0;Однако, такое работает только с Postgres >12 и только в случае, если используются CTE, а не подзапрос. Так что необходимость в переписывании всё равно остается.
Очень интересно, спасибо!
А на сколько claude помогает/ускоряет написание таких фич как sort pushdown?
Это вопрос на полноценный разговор. Если совсем просто - то помогает настолько, насколько разработчик знает, что он делает и имеет представление о нюансах предметной области.
С одной стороны, Claude хорош, когда нужно сделать похожий код - см. pg_track_optimiser, где после трех метрик, сделанных под руководством, остальные пять он уже делал сам с минимальными правками. Также, дурацкие баги он часто видит лучше.
С другой стороны, он на голубом глазу часто предлагает резетнуть MemoryContext или использовать что-то из контекста одной транзакции в другой, или использует функцию не так, как это предусмотрено. - по всему видать, что это вопрос вычислительной мощности, он же не может копаться во всем. А контекст его опыта достаточно невелик, чтобы триггерить инсайты, которые заставляют опытного инженера копать здесь а не там.
ну и главное - такие фичи часто до момента разработки не имеют конкретных очертаний - их цель недостаточно ясна и возможность реализации непонятна. Даже корректное название фичи приходит уже после окончания работы, когда начинаешь понимать, что оно по-факту делает, что уж тут говорить про понятный промпт :))).
Спасибо!
Особенно за стиль письма. Бывает простецкую вещь человек описывает и ничего не понятно. А тут хоть и многа букав а все-равно все понял.
Тема квартернаной логики не раскрыта, как мне показалось.
Если реально запоминать факт ошибки и обрабатывать дальше запрос, то действительно можно выбрасывать ошибку пользователю, если она не отфильтровалась.
Правда в примере с пушем предиката на нижний уровень, механизм тернарной логики не был бы задействован: на уровнях выше нет выражений/фильтров, зависящих от упавшего приведения типа. Нужно было бы запомнить все таплы с прикрепленными к ним ошибками (по одной на каждый тапл), отсортировать их, поджойнить, и только после лимита смотреть, не попался ли результирующий тапл с прикрепленной ошибкой.
Самое противное, что у каждого тапла может быть своя ошибка, и её текст нужно вернуть пользователю. А значит, придётся материализовать все ошибки. Что несёт большой оверхед.
Второй противный момент, что фильтр перестаёт работать: нужно проталкивать наверх все таплы с ошибками.
Может быть, имеет смысл перехватывать ошибки? (CAST(val as int) RESCUE false) или (CAST(val as int) RESCUE SKIP)
Может я что-то не то говорю. Комент ведь генерила белковая нейросеть, а её возможности ограничены.
Ну, четвертое измерение в логике функций имеет скорее отношение к пользовательскому (административному) опыту - стабильность фреймворка/приложения при апгрейдах и всё в таком духе. Поэтому я только подсветил проблему - раз уж SQL Server тоже это описывал.
С точки зрения реляционой алгебры, стандарта SQL, консистентности или транзакционности тут вопросов нет, как и универсального решения. Мой поинт в том, чтобы по-простому дать возможность регулировать подобное поведение: ведь не у каждого есть возможность переписать под себя платформу 1С или даже приложение - а пофиксить нестабильность prosupport функциями - это просто.
Бинарная, тернарная или всё-таки кватернарная логика в функциях Postgres?