Здравствуйте, vdimas, Вы писали:
V>Твоя "локальная информация" имеет строгую иерархическую природу.
(facepalm)/
V>Так КАК она будет хранится?
Это как раз неважно.
S>>И их там как бы дофига, потому что потенциально orders o join manager m on o.managerId = m.id порождает бездну вариантов исполнения.
V>В указанном виде? ))
Конечно.
S>>Грубо говоря, мы можем использовать любой из 5-6 индексов по Manager, потому что а вдруг там в where что-то особенно селективное написано
V>Прикольный залет, причём, ты уже вроде бы 3-й раз одинаково залетаешь.
Это не залёт, это невнимательность с твоей стороны.
V>Ведь не "вдруг", а на руках полная комбинация всех where.
Это в
конкретном запросе. С
конкретными значениями параметров. А мы же вроде бы хотели что-то там повторно использовать, нет?
V>Эти where часто образуют иерархию, например, where x>100, а потом еще where x>100 and x<1000 и т.д.
Вот это место не имеет физического смысла. Даже если у нас есть много предикатов на один и тот же атрибут, то никакой иерархии они не образуют.
V>За 10-15 индексов по order положено расстреливать, ну пусть даже 10-15 индексов.
Твои представления о том, за что положено расстреливать, а за что — увольнять, выдают малый опыт в обсуждаемой теме.
V>Сколько всего таблиц навроде "order" в средней системе?
Смотря что считать "средней системой".
S>>Итого получаем от полусотни до сотни вариантов исполнения этого join.
V>И это для самой индексированной таблице, аналогов которой единицы штук даже в самых крупных учётных системах.
Это мы говорим про 1 джойн. В самой средней учётной системе мы регулярно имеем запросы с 5-10 джойнами.
Потому как схемы высоконормализованные
И как раз обычно в них ровно одна такая "самая индексированная" таблица.
V>При том, что про полусотню враки — большая часть вариантов откидываются как заведомо худшие еще на этапе построения всего набора планов.
(facepalm) с чего бы это они будут отброшены? Для каждого из них бывает такая комбинация параметров запроса и набора данных в таблице, когда именно этот вариант плана выиграет.
V>Это если плавать в предмете, сорри.
Сорри, нет.
V>Если на основании предикатов exists, any/all, not in и т.д. — то та же херня что join, вид сбоку, они все через join выразимы.
Отож.
V>А если на основании агрегирующих математических ф-ий — то кол-во вариантов планов падает на порядок-другой сразу, бо опять же получается иерархия исполнения всех (сколько бы ни было уровней вложенности) подзапросов.
Возрастает. На порядок возрастает. Потому что возникают варианты "сначала join, потом агрегация", либо "агрегация, потом join".
V>Всё, я сдаюсь.
V>Коллега, ну это уже упоротость какая-то. ))
Нет, это близкое знакомство с предметом.
V>План запроса не хранится в виде данных.
V>Он хранится как код, как ф-ия с параметрами.
V>Для этого всё и затевалось.
Очень хорошо.
V>Иерархичность тут проявляется в иерархии вызовов подпрограмм собсно исполнения планов запросов (а не их тупорылой динамической интерпретации, как оно есть сейчас). Итого, вся эта куча подпрограмм вдоль всей иерархии вызова — она многократно повторно используема.
(facepalm).
V>Степень повторного использования можно регулировать через связывания аргументов с константами, т.е. еще на этапе бета-редукции.
V>При минимальном связывании будет минимальный бинарник, но макимальное кол-во параметров у каждой ф-ии, при максимальном связывании — наоборот.
Нам не так важно, как это хранится. SQL-сервер хранит это в виде дерева физических операций, при исполнении — интерпретирует.
Ок, мы можем "улучшить" ситуацию путём генерации не объектов-описаний, а, к примеру, Expression<>. Или байткода в стиле MSIL, LLVM, или Java.
Или сразу вообще скомпилировать бинарь. Это повлияет только на скорость исполнения этого плана. На место, которое он занимает, это повлияет в плохую сторону.
V>Взял бы ручками да раписал планы вокруг одной и той же комбинации join.
V>Ты ведь никогда этого не делал, верно?
Зачем? Мне их сервер выписывал, когда я занимался оптимизацией SQL.
V>Я тебя понял.
V>Улыбнуло.
V>При исполнении плана дерево тут строго в другую сторону растёт — от примитивных листьев-операций к конкретной сложной операции.
V>То бишь, каждый лист (в том числе параметрический) принадлежит куче "деревьев"-конкретных планов.
В том-то и дело, что нет, не принадлежит. Вот у нас лист: index scan. Он "прибит" к конкретному индексу. И у него есть конкретный аргумент where — тот, который достался ему от "большого" запроса. От одного, конкретного "большого" запроса. Примерно так: index scan(ix_manager_region) where (regionId = @regionID)
Мы можем его скомпилировать — т.е. вместо унылой интерпретации у нас внутри getNext() будет прямо бинарный код, который более-менее оптимально сканирует страницы индекса в поисках искомого аргумента.
В другом запросе у нас этот индекс будет сканироваться с другим предикатом, и повторно использовать этот лист не выйдет.
V>Экономия во-первых не будет нулевой хотя бы потому, что не будет динамики.
Речь шла об экономии размера. Напомню: практики (я и Иван) считают, что статический список планов будет неприемлемо велик. Ты с наивностью неофита решил, что планы можно хранить "компактно".
V>Во-вторых, отбросив разницу статики и динамики у нас не будет экономии только тогда, когда каждый индекс каждой таблицы использован только раз в реальных запросах. Не знаю что там говорит твой опыт, но мой говорит строго обратное — индексы вводятся для популярных сценариев доступа к таблице.
Индекс используется в каждом запросе по-своему.
V>ИМХО, это может зависеть от конкретной реализации.
В практических реализациях — так.
V>Или, например, будет ли это так для параметрического запроса, где выбор конкретного плана зависит от значения параметра?
Да. Оптимизатор никогда не сохраняет планы, которые не были выбраны для исполнения.
V>Насос из пальца, однако.
V>Для сравнения, есть среднейго размера программа на JS, в этой программе куча похожих мест, но все они компилятся движком v8 уникальным образом. После всевозможного джита бинарник в памяти занял порядка 15 метров. Такая же точно программа после нейтивной оптимизации имеет размер сегмента .text порядка 350 KB, т.е. разница примерно в 50 раз.
Интересное наблюдение. Увы, оптимизатору программы на JS не надо хранить все возможные пути исполнения.
S>>А для тех запросов, где вариантов немного, их и хранить особо незачем — проще построить их на ходу.
V>Проще чем что?
Чем строить заранее.
S>>И вот всё это как бы очевидно людям, которые реально занимались оптимизацией реальных SQL запросов как full-time job, а не только единожды сдали 32х часовой курс реляционной алгебры 20 лет назад.
V>Я и сам посвятил несколько лет своей жизни довольно-таки внушительным учётным системам, наелся этого достаточно.
Видимо, нет.
V>Или вот даже коллега IB "удивил" меня тем, что, оказывается, уже лет 10 движки БД умеют распознавать "похожие" некоторые запросы, которые отличаются лишь константой в предикате. И на полном серьёзе думал, что убил этим, даже гнался там за мной и оскорблял. )) При том, что мы как раз обсуждали систему, которая ради именно такой операции и создавалась.
V>Т.е. должна делать ровно то же самое, но не для "некоторых" запросов, а потенциально для всех.
Опять полное непонимание проблематики налицо. Когда мы говорим по 2000-8000 разных запросов, речь не об одном запросе с параметром, который может принимать 2000-8000 разных значений, а о структурно разных запросах.
Для них повторно использовать в планах не получится почти что ничего. Ну там — какой-нибудь clustered index seek разве что.
Схлопывание, про которое говорит Иван, это подстилка для криворуких прикладников, которые запросы пишут при помощи конкатенации строк. Некурящие программисты передают параметры в виде параметров, и оптимизатор может сразу же обнаружить план в кэше просто поиском строки. Для нормальной системы, в которую дебилов не пускают, это не нужно.
А вот "расхлопывание" планов запросов — штука принципиальная, её на стороне прикладного разработчика делать нельзя.
Так вот, по-прежнему 2000 структурно разных запросов потребуют 2000 разных планов. Минимум. А если мы попробуем заранее их подготовить, то придётся статически скомпилировать десятки тысяч вариантов планов.
V>Чувак даже не потрудился включить голову и сообразить, что раз это МОЖНО делать в статике (я же ему предлагаю именно так делать), то можно попытаться это сделать и в динамике (как перешли от интерпретации p-Code к JIT). Правда, со всеми присущими динамике ограничениями на пережовываемую сложность. И со сложностью в динамике большие бока — в код для динамики нужно обязательно вставлять счётчики сложности, чтобы суметь вовремя остановиться, т.к. фи-ей оптимизации всё-равно выступает минимальное время выполнения запроса, т.е. эта техника принципиально способна покрыть лишь ничтожное кол-во сценариев. Статика же ничем не ограничена.
(facepalm).
V>И вот я такой читаю самого здешнего мэтра по MS SQL и вижу серьёзный такой косяк, что у него даже на шаг вперёд подумать не получается. Зато пафоса и нервозности хоть отбавляй.
Он просто думает на
два шага вперёд. Вот ты сам же пишешь про то, какие ограничения на это всё в динамике. Ну, вот там всё так и есть — не глупее тебя люди движок писали.
S>>ровно потому, что он весь ход твоей мысли уже в голове воспроизвёл, получил результаты, прикинул их к реальности, и видит заблуждения, допущенные на самом начальном этапе.
V>Скажем так, он физически этого сделать не может, потому что не владеет материалом, банально отсутствуют как теоретическое понимание, так и практический опыт по обсуждаемой тематике.
))
Если бы он хотя бы раз написал (пусть небольшую) программу, которая строит дерево перебора вариантов последовательностей выражений РА из исходного РИ (небольшую, потому что кол-во операций РИ пусть будет ограничено), он бы всей этой ереси не писал. И ты бы тоже не писал, сорри. Вы оба плохо представляете процесс перевода РИ в РА, хотя для овладения этим материалом вовсе не надо 32 часа. Особенно человеку с техническим ВО. Я был дал 5-10 часов, этого должно хватить. Дело за желанием.
Да мы-то как раз представляем
А вот ты в каждом посте пишешь чушь, из которой сразу видно, что весь "теоретический опыт и практические знания" исчерпываются парой учебных примеров. Оттого и непонятно, почему планов запроса потенциально может быть много (а не один-два), и что "склеить" их никуда не получится. Конечно, это не означает, что существующим СУБД некуда расти, но чтобы их улучшать, надо понимать, где и что там плохо устроено.