Ускорение аналитических запросов с опцией Database In-Memory
Марк Ривкин, руководитель группы баз данных технологического консалтинга Oracle в России и СНГ
Она позволяет радикально ускорить выполнение аналитических запросов. Для этого требуется лишь задать размеры in-memory кэша и указать таблицы, которые там можно размещать.
Для хранения данных в СУБД различных производителей используются два основных метода – традиционный построчный и поколоночный. Аналитические запросы и подсчет агрегатов быстрее выполняются при поколоночном хранении. Однако, обычные OLTP-запросы, когда требуется доступ к небольшому набору строк либо модификация одной строки таблицы, при таком представлении работают медленно. При построчном хранении все ровно наоборот. На практике большинство приложений – смешанные, т.е. они поддерживают и OLTP, и аналитические запросы, и сложные вычисления.
Технология Oracle Database In-Memory решает эту проблему. Данные в базе данных на диске хранятся в построчном формате, что позволяет применять традиционные механизмы хранения и ввода/вывода. Но в оперативной памяти для заданных таблиц (или частей таблиц) хранятся два представления этих данных: построчное — в буферном кэше и поколоночное — в новом In-Memory кэше (рис 1).
При поступлении нового запроса к СУБД SQL-оптимизатор Oracle определяет, как он будет лучше выполняться, на каком кэше (на построчном или колоночном), и строит соответствующий план выполнения запроса. Аналитические запросы при этом могут ускориться в десятки раз. Это достигается, в том числе, за счет того, что операции с колонками (векторами значений) выполняются с использованием векторных операций процессора (Single Instruction Multiple Data, SIMD). Одно ядро процессора способно сканировать миллиарды строк в секунду, т.е. за одну команду процессора можно, например, провести поиск значений в колонке.
Даже такие тяжелые и сложные операции, как соединение таблиц, Oracle Database умеет преобразовать в набор векторных операций. В версии 20с появилась возможность и некоторые простые операции соединения выполнять с использованием векторных операций без преобразования – In-Memory Vector Join. Например, если таблицы «Продажи» и «Пункты продаж» нужно соединить по ключу «Код заказа», значения колонок «Код заказа» этих таблиц загружаются в два векторных регистра и за один такт процессора формируется матрица соответствия этих столбцов (практически результат соединения таблиц). Это на порядок ускоряет многие операции соединения. При векторной обработке также реализуются новые алгоритмы ускорения построения агрегированных отчетов.
Размер оперативной памяти ограничен, поэтому специальная утилита In-Memory Advisor анализирует запросы и выдает рекомендации, какие таблицы следует поместить в In-Memory кэш, а также помогает это сделать. Чтобы сэкономить память, кэшировать можно части таблиц (секции), не все колонки, при этом кэшируемые данные можно сжимать. Начиная с версии Oracle Database 19с данные автоматически подкачиваются в кэш на место давно не используемых. А в версии 20с будут применяться In-Memory алгоритмы, даже если часть таблиц запроса хранится в In-Memory кэше, а часть – только в буферном кэше.
Данные всегда сначала обновляются в буферном кэше, а затем кэши синхронизируются специальным фоновым процессом. Опция In-Memory может использоваться и с резервной базой данных, открытой на чтение (опция Active Data Guard), где выполняются аналитические запросы и строятся отчеты. При этом в основной и резервной базах в кэш могут помещаться разные таблицы.
В ячейках Oracle Exadata используются флеш-память и энергонезависимая память (persistent memory). В них данные могут кэшироваться в том же формате, что и в In-Memory кэше. Поэтому на ячейках хранения Exadata тоже применимы алгоритмы векторной обработки.
В Oracle Database 18c значительно повышена производительность многих In-Memory операций. Например, несколько колонок таблиц можно сканировать одновременно. Значения числовых (number) колонок преобразуются при этом в памяти в бинарный формат процессора, что ускоряет выполнение векторных вычислений. Часто используемые выражения на основе колонок таблицы могут автоматически вычисляться заранее и храниться в памяти в виде дополнительных колонок, т.е. вычисления не производятся каждый раз.
В последних версиях СУБД Oracle Database технология In-memory используется не только для реляционных данных, но и для колонок с геоинформацией, текстом и JSON. Она используется и при работе с внешними таблицами (external table).
Дополнительным бонусом опции In-Memory является ускорение в 2-3 раза OLTP-запросов. Обычно для ускорения аналитических запросов приходится строить множество дополнительных индексов для таблиц. Каждое изменение данных таблицы вызывает также и изменение всех индексов, что замедляет работу. Теперь же дополнительные индексы можно удалить и получить ускорение OLTP-операций за счет технологии Oracle Database In-Memory, поскольку отсутствуют накладные расходы на сопровождение дополнительных индексов.
Таблицы с оптимизацией для обработки в памяти
СУБД Oracle теперь умеет ускорять еще два типа приложений со специфическими запросами. Это работа с таблицами типа ключ-значение, где по ключу надо быстро получить запись, и работа с таблицами для интернета вещей (IoT), где требуется непрерывная вставка записей в таблицу (например, поток телеметрии с датчиков). Для этого используются так называемые таблицы с оптимизацией для обработки в памяти (memory optimized), для которых применяются специальные алгоритмы обработки.
Если надо быстро извлекать данные типа ключ-значение из таблицы по ключу, то достаточно просто объявить таблицу как Memoptimize for read и задать размер кэша Memoptimized для таких таблиц. При этом таблица загружается в кэш при первом обращении к ней и для нее в памяти строится хэш-индекс. При запросе записи по ключу Oracle Database в обход традиционных механизмов и без блокировок просмотрит этот индекс и сразу извлечет из памяти нужные строки. Алгоритм использует новый клиентский протокол с низким временем отклика и обеспечивает прямой доступ к ядру СУБД, минуя SQL-уровень. Это дает ускорение до 4 раз.
В случае таблицы, например, для интернета вещей, куда нужно быстро и непрерывно вставлять новые записи достаточно объявить ее Memoptimize for write. При добавлении записей в такую таблицу строки вначале быстро вставляются в специальный буфер в памяти, а затем буферизованные данные пакетами записываются на диск в фоновом режиме. Добавление записей ускоряется при этом до 2 раз.
Шардинг
Обычно таблица хранится в одной базе данных на одном сервере и ее обработкой занимается либо сервер, либо группа узлов RAC. Но если таблица велика, а нагрузка очень большая и обработка отдельных частей таблицы допускает распараллеливание, то разумно разрезать таблицу на части (шарды) и разместить их на разных серверах. На каждом будет своя база данных, в которой будет находиться часть таблицы (или группа связанных частей связанных таблиц). Каждый сервер будет обрабатывать свои шарды. Это позволяет осуществить горизонтальное масштабирование для высоконагруженных, хорошо распараллеливаемых задач (например, в поисковых системах).
Таблицы нарезаются на части по ключу шардинга, который можно явно указывать в SQL-запросах или при открытии сессии. Специальный координатор (шард-директор) по ключу определяет, какому серверу передать обработку. Если же в запросе ключ не указан, координатор выполняет запрос на всех шардах (кросс-шардинг), но это будет работать медленно. Все операции языка описания данных (Data Definition Language, DDL) с множеством узлов выполняются централизованно через координатор.
Новые узлы можно легко добавлять на лету. Это позволяет увеличивать мощность системы и переносить на них часть шардов (делать решардинг). Часть баз шардированного приложения может быть реализована в виде PDB (Pluggable Database) или размещена в облаке. Таким образом, шардинг не только ускоряет обработку, но и повышает отказоустойчивость системы: при выходе из строя узла недоступной оказывается лишь часть данных. Для надежности база данных каждого узла может иметь свою резервную копию.
В базе данных узла можно помещать не только часть одной таблицы, но и связанные по ключам части нескольких таблиц (семейство таблиц, table family tree) или несколько семейств. Кроме того, в эти базы для ускорения помещаются копии справочных таблиц, чтобы вся обработка выполнялась на узле
Начиная с версии Oracle Database 19с в одной CDB (Container Database) могут находиться PDB для шардов одной или разных шардированных баз данных. Если при работе с шардами в узлах используются последовательности (sequence) для генерации уникальных значений, то генерируемые значения можно сделать уникальными как в шарде, так и для их группы. Утилита Sharding Advisor помогает выбрать способ разбиения базы данных на шарды.
Sharded RAC. Горизонтально масштабировать базу данных можно двумя способами – с помощью RAC и шардинга (и отчасти standby c Active Data Guard). Первый работает с одной базой (или CDB) и распараллеливает обработку (процессоры и память), а второй делит базу на несколько (каждая со своими процессорами и областями памяти). Начиная с версии 18с доступен еще один вариант – шардированный RAC (виртуальный шардинг). При этом база данных остается единым целым, но данные делятся на виртуальные шарды и привязываются к узлам кластера RAC. Запросы с ключом шарда перенаправляются к узлу/узлам кластера, обслуживающим этот шард. Это улучшает использование кэша базы и уменьшить пересылку блоков данных между узлами (Рис. 3).
Повышение надежности СУБД
Oracle позволяет реализовать архитектуру максимальной надежности и доступности (Maximum Availability Architecture, MAA). Она обеспечивается с помощью таких механизмов как RAC, резервная база данных, шардинг, мультиарендность, Sharded RAC, Application Continuity, автономные базы данных. Сегодня автономная БД может обеспечить уровень надежности 99,995 – это всего 30 мин плановых и неплановых простоев в год! Однако для некоторых применений и этого может быть недостаточно, поэтому в очередных версиях СУБД Oracle появились новые средства повышения надежности. Например, много изменений было сделано в механизме работы резервной (standby) БД.
DML в Standby. Первоначально резервная база данных служила только для подмены основной в случае ее сбоя. С появлением опции Active Data Guard (ADG) резервную базу стало возможно открывать на чтение. Это позволило разгрузить основную базу и освободить ее от операций построения отчетов, аналитики и бэкапирования. Однако менять данные в standby БД было нельзя. Но очень часто при построении большого сложного отчета требуется изменить некоторые данные в таблицах. Например, записать диапазон дат, за которые строится отчет, или сохранить информацию о времени последнего построения отчета. Теперь, начиная с версии 19с, это можно сделать.
Подобные небольшие изменения вносятся следующим образом. При запросе оператор DML (Update, Delete, Insert) автоматически перенаправляется с резервной базы данных на основную и выполняется там. После его завершения изменения передаются на резервную БД. При этом сессия на резервной базе данных ждет, пока изменения не поступят. До фиксации транзакции изменения не видны другим транзакциям, т.е. поддерживается транзакционность. Этот механизм полезен для приложений, которые часто читают данные, но редко их изменяют.
Синхронный Flashback. Другой полезный новый механизм – синхронный откат (flashback) основной и резервной баз данных одной командой. При откате назад основной базы резервная откатывается автоматически.
Multi-Instance Recovery Apply (MIRA). При большом объеме изменений в основной базе данных поток изменений, передаваемых на резервную, тоже очень велик. Ранее резервная база данных могла не справляться с такой нагрузкой, что увеличивало ее «отставание» от основной. Теперь если обе системы используют RAC, изменения, передаваемые от узла/узлов основной базы данных, могут параллельно применяться на различных узлах RAC резервной базы. При этом порядок выполнения транзакций сохраняется, но за счет распараллеливания нагрузки основная и резервная базы данных синхронизируются гораздо быстрее.
Нежурналируемые операции (Nologging) и Standby. Большинство операций основной базы данных записываются в журнал (redo log), передаются на резервную и там выполняются. Однако журналирование замедляет работу, порождает дополнительные накладные расходы и увеличивает объем передаваемой на резервную БД информации. Поэтому для некритичных операций администраторы баз данных отключают журналирование (режим nologging), что чревато рассинхронизацией основной и резервной баз данных.
Новая команда Validate/Recover Nologging Block позволяет выявить и синхронизировать такие рассинхронизированные объекты данных. А команда Recover Standby Database from Service – быстро восстановить резервную базу данных напрямую из основной. Это очень удобно при большом отставании резервной базы от основной. Конфигурации обеих баз можно также одной командой сравнить .
Начиная с версии 18c поддерживается передача изменений при nologging-операциях непосредственно по сети, минуя фазу записи изменений в журнал транзакций. Это позволяет снизить нагрузку на дисковую подсистему и увеличить скорость передачи изменений.
Сохранение сессий. Ранее, при переводе резервной базы данных в режим основной, все ее открытые сессии терялись и их надо было открывать заново. Теперь их контекст не теряется, просто они из режима чтения переводятся в режим чтения/записи. Это уменьшает время переключения и упрощает процесс.
Авторский вариант статьи опубликован в журнале «Открытые системы.