OLTP в Зазеркалье

         

Удаление компонентов Shore


В табл.1 резюмируются свойства и характеристики современных систем OLTP (левый столбец), позволяющие удалить из СУБД некоторые функциональные возможности. Эти оптимизации использовались авторами в качестве руководства по модификации Shore. Из-за тесной интеграции всех менеджеров Shore было невозможно точно разделить все компоненты, чтобы их можно было удалять в произвольном порядке. Наилучшим возможным подходом было удаление функциональных возможностей в порядке, диктуемом структурой кода, что обеспечивало некоторую гибкость. Это порядок был следующим:

  1. удаление журнализации;
  2. удаление блокировок ИЛИ защелок;
  3. удаление защелок ИЛИ блокировок;
  4. удаление кода, относящегося к менеджеру буферов.

Таблица 1. Возможный набор оптимизаций для OLTP



Свойства OLTP и новые платформы Модификация СУБД
архитектуры без поддержки журнала удаление журнализации
разделение, коммутативность удаление блокировок (когда это возможно)
поочередное выполнение транзакций однопотоковый режим выполнения, удаление блокировок, удаление защелок
хранение в основной памяти удаление менеджера буферов
нетранзакционные базы данных устранение учета транзакций

Кроме того, авторы обнаружили, что в любой точке процесса удаления компонентов возможны следующие оптимизации:

  • ускорение и жесткое кодирование логики сравнения ключей B-деревьев, как это делается в большинстве коммерческих систем;
  • ускорение поиска в каталогах;
  • увеличение размера страницы для устранения потребности в частом распределении памяти (это предполагается указанным выше Шагом 4);
  • удаление транзакционных сессий (начала транзакции, фиксации, различных проверок).

Далее описывается подход, примененный авторами для реализации упомянутых действий. Вообще говоря, для удаления из системы некоторого компонента либо добавлялись условные операторы, которые позволяют избежать выполнения кода, относящегося к этому компоненту, либо, если добавление условного оператора приводило к ощутимым накладным расходам, методы переписывались целиком для полного устранения вызовов удаляемого компонента.


Удаление журнализации. Удаление журнализации состоит из трех шагов. Первый шаг заключается в устранении генерации запросов ввода-вывода, а также тех точек работы системы, которые ассоциированы с выполнением этих запросов (позже, на рис. 7 эта модификация называется устранением «дисковой журнализации» («disk log»)). Это достигается путем установки режима групповой фиксации транзакций и увеличения размера буфера журнала в такой степени, чтобы он не выталкивался в течение экспериментов. Потом «закомментированию» подвергаются все функции, используемые для подготовки и записи в буфер журнальных записей (на рис. 7 это называется «журнализацией в основной памяти» «main log»). Последний шаг состоит в добавлении условных операторов в разных местах кода для устранения обработки LNS.
Удаление блокировок (а также и защелок). В ходе своих экспериментов авторы обнаружили, что можно безопасно чередовать порядок удаления блокировок и защелок (если уже удалена журнализация). Поскольку защелки используются и внутри кода обработки блокировок, устранение одного механизма снижает уровень накладных расходов другого. Для удаления блокировок авторы, прежде всего, поменяли все методы менеджера блокировок таким образом, чтобы сразу после обращения из них происходил возврат, как если бы запрос блокировки был успешно обработан, и все проверки блокировок были удовлетворены. После этого они модифицировали методы чтения записей, поиска их в каталоге и доступа к ним через B-дерево. В каждом случае удалялся код, относящийся к неудовлетворенным запросам блокировок.
Удаление защелок (а также и блокировок). Удаление защелок было похоже на удаление блокировок. Сначала код реализации мьютексов был изменен таким образом, чтобы все запросы немедленно удовлетворялись. Затем в код были добавлены условные операторы, позволяющие избежать запросов защелок. Потребовалось заменить методы B-дерева на такие, в которых не используются защелки, поскольку добавление условных операторов вызвало бы существенные накладные расходы по причине тесной интеграции кода защелок в методах B-дерева.


Удаление вызовов менеджера буферов. Наиболее пространной модификацией выполненной авторами, являлось удаление методов менеджера буфера, притом что журнализация, блокировки и защелки уже не действовали. Для создания новых записей авторы отказались от механизма выделения страниц Shore и вместо этого воспользовались стандартной библиотекой malloc. Malloc вызывается для каждой новой записи (записи больше не располагаются в страницах), и для будущего доступа используются указатели. Потенциально распределение памяти может производиться более эффективно, в особенности, если заранее известны размеры размещаемых объектов. Однако дальнейшая оптимизация распределения основной памяти является следующим этапом сокращения накладных расходов, и авторы оставили эту работу на будущее. Оказалось, что невозможно полностью удалить страничный интерфейс к буферным фреймам, поскольку его удаление привело бы к несостоятельности большей части оставшегося кода Shore. Вместо этого авторы ускорили отображение между страницами и буферными фреймами, сократив накладные расходы до минимума. Аналогично, чтение и модификация записи по-прежнему проходит через уровень менеджера буферов, хотя и очень тонкий (на рис. 7 этот набор модификаций называется «страничным доступом» («page access»)).
Прочие оптимизации. Выполнены еще четыре вида оптимизации, которые можно производить в любой точке процесса удаления упомянутых выше компонентов. Они состоят в следующем.

  1. Ускорение выполнения кода пакета B-дерева путем ручного кодирования сравнения ключей для того распространенного случая, когда ключи являются несжатыми целыми числами (эта оптимизация называется «ключами B-дерева» («Btree keys») на рис. 5-8).
  2. Ускорения поиска в каталоге за счет использования единого кэша для всех транзакций (эта оптимизация на рис. 7 называется «поиском в каталоге» («dir lookup»)).
  3. Увеличение размера страницы от 8 до 32 килобайт, что является предельно возможным размером в Shore (на рис. 7 эта оптимизация называется «небольшие страницы» («small page»)).


    Более крупные страницы, хотя и непригодны для систем баз данных OLTP с хранением баз данных на дисках, могут помочь в системе с хранением баз данных в основной памяти за счет уменьшения числа уровней в B-деревьях (из-за укрупненных узлов), а также позволяют сократить частоту выделения страниц для вновь создаваемых записей. Альтернативным подходом было бы уменьшение размера узла B-дерева до размера блока кэша, как это предлагалось в [RR99], но тогда потребовалось бы отказаться от того, что размер узла B-дерева совпадает с размером страницы Shore, или сделать размер страницы Shore меньшим одного килобайта (что в Shore не допускается).
  4. Устранение накладных расходов на подготовку и завершение сессии для каждой транзакции, а также на соответствующее отслеживание выполняемых транзакций путем объединения всех транзакций в одну сессию (на рис. 7 это называется «Xactions»).

Полный набор изменений/оптимизаций, произведенных авторами над Shore, а также набор эталонных тестов и документация по организации экспериментов доступны на сайте проекта H-Store.
В следующем разделе авторы переходят к обсуждению вопросов производительности.

Содержание раздела