При оценке баз данных или механизмов вычисления данных вы могли бы наткнуться на такие термины, как поддержка векторизации, запросы времени компиляции или генерация кода, подходящие в соответствии с запросом. Но что они означают? Они что-то значат? Давайте разберемся.

Прежде чем перейти к тому, что, давайте сначала спросим, ​​почему. Зачем нужны векторизованные или скомпилированные запросы? Чтобы ответить на этот вопрос, давайте посмотрим, кто был предшественником векторизованных и скомпилированных запросов. Это будет модель итератора вулкана. . .

Модель итератора вулкана

Представьте себе вулкан, он похож на конус или, по крайней мере, его рисуют так большинство детей, в том числе и я :). Нижеследующее определенно не нарисовано ребенком.

Поскольку форма вулкана предполагает, что лавы (данных) слишком много у основания, и ее дымится из нее очень мало.

Вот определение не-забавной вики:

Модель вулкана (первоначально известная как модель итератора) представляет собой «классическую» стратегию оценки аналитического запроса СУБД: каждый реляционно-алгебраический оператор создает поток кортежей, а потребитель может выполнять итерацию над своими входными потоками. Интерфейс потока кортежей по существу: «открыть», «следующий» и «закрыть»; все операторы предлагают одинаковый интерфейс, и реализация непрозрачна. Каждый вызов «next» создает новый кортеж из потока, если он доступен. Чтобы получить результат запроса, один оператор «следующий-следующий-следующий» в последнем операторе RA; что один, в свою очередь, будет использовать «next» на своих входах для извлечения кортежей, позволяя ему создавать выходные кортежи и т.д. Некоторые «next» будут занимать очень много времени, так как многие «next» для предыдущих операторов потребуются перед они испускают любой вывод. Пример: ВЫБРАТЬ max (v) FROM t; может потребоваться пройти через все t, чтобы найти этот максимум.

Проще говоря для мозга:

Это цепочка итераторов, и данные проходят через них, когда самый верхний итератор вызывает next () на итераторе под ним. Это приводит к распространению вызовов .next () до вызова самого нижнего итератора. Каждый итератор может применять какой-либо предикат или другие операторы. И при визуализации в виде вулкана данные могут уменьшаться по мере продвижения вверх по цепочке итератора.

Что с этим не так?

Ну, на первый взгляд ничего, пока люди не поняли, что это вызывает много промахов кеша инструкций.

Что такое пропуски инструкций в кеше?

Что это за безумие, в которое ты только что вызвался?

Итак, представьте, что ваша база данных использует модель итератора вулкана. Ваши данные находятся на диске, откуда ваш диспетчер дисков считывает их и записывает в основную память по запросу диспетчера буферов. Эта часть информации из основной памяти затем будет загружена в кэш-память (L1 и L2). Из этих кешей информация будет перемещена в регистры, где будут выполняться операции. Однако и данные, и инструкции сборки должны быть загружены в кэш-память.

Итак, у вас есть инструкции и данные, хранящиеся в кеше. Но что, если у вас слишком много инструкций? Ваш запрос был большим, как и сгенерированный код выполнения, который транслировался в большее количество инструкций по сборке. А общий код выполнения запроса привел к большему количеству ветвлений, что привело к увеличению количества бесполезных инструкций в кеше. Но подожди секунду.

Что вы подразумеваете под общим кодом выполнения запроса?

Представьте, что вы пишете код, который поддерживает все виды запросов и все типы данных. Написание такого кода потребует правильного количества абстракций, а также большого количества if-then для обработки различных типов данных.

Пример: написание оператора "больше чем" для механизма выполнения запросов.

Оператору "больше, чем" необходимо знать тип данных. Дата, строки и целые числа приведут к другому ожидаемому поведению и сгенерированным инструкциям по сборке.

Операторы ветвления, как правило, приводят к загрузке инструкций, которые не нужны, потому что эти инструкции никогда не будут выполнены, если условие не выполняется.

Что, если я не напишу общий код, поддерживающий все? Что, если я напишу достаточно кода для моего собственного запроса? Что, если мой механизм выполнения запросов сгенерирует достаточно кода для моего собственного запроса?

Это были вопросы, которые приходили в голову людям, которые впервые задумались о возможности составных запросов.

А что, если такие пропуски кеша инструкций происходят для каждой строки?

В модели вулкана действует каждая строка за раз.

Итак, у нас есть две альтернативы:

  • Скомпилированные запросы. Создавайте инструкции с меньшим количеством ветвлений, специфичные для запроса.
  • Векторизованные запросы. Допускается пропуск кэша, но не для каждой строки, возможно, для пакета строк.

Итак, теперь мы понимаем, почему были необходимы скомпилированные запросы и векторизованные запросы. Вот и все, а пока мы обсудим векторизованные запросы в части 2, а затем скомпилированные запросы в части 3.

Если вам есть что добавить или вы заметили ошибку в моем сообщении, не стесняйтесь обращаться ко мне, я буду рад внести изменения и кое-что узнать.