Блоки. Внутреннее устройство файла базы данных Caché

Не так давно на хабре в блоге InterSystems были выложены статьи о том, что собой представляет глобал в Caché, с чем его готовят и как подают (часть 1 и часть 2). Это всё, конечно, интересно, удобство работы с любыми моделями данных, какие только пожелает разработчик. Но что обеспечивает хорошую скорость обращения с этими глобалами?

5a4b19a27bf64db4b6df1777baa42d56.png

Теория


База данных Caché представляет собой каталог с названием базы, в котором содержится файл CACHE.DAT. На *nix-системах, в качестве базы данных может выступать раздел на диске.

Данные в Caché хранятся в блоках, а те, в свою очередь, организованы в виде сбалансированного B*-дерева. Если вспомнить, что мы храним глобалы в виде дерева в упрощённом понимании, ветками в таком дереве будут сами индексы глобала, а листьями – значения индекса глобала. Отличие сбалансированного B*-дерева от обычного B-дерева в том, что ветви имеют правые связи, помогающие (в нашем случае с глобалами) обходить индексы достаточно быстро с помощью функций $Order и $Query, без необходимости подниматься к стволу дерева.

Размер блока в файле БД фиксированный, по умолчанию он составляет 8192Б, но есть возможность разрешить создавать БД с размерами блоков 16кБ, 32кБ и 64кБ. Разработчик системы может выбрать необходимый размер блока в зависимости от характера данных, которые он планирует хранить. Но всегда нужно учитывать, что чтение данных производится поблочно – даже если запрошено одно значение размером 1 байт, будет прочитано несколько блоков, и только последним в этой цепочке будет блок с данными. Caché также имеет разные буферы глобалов – нельзя смонтировать или создать новую БД, если в системе не настроен буфер глобалов с соответствующим размером блока – это приведёт к ошибке.

8bd7a79ae5ac4b19be791c71f84a94a8.png

2d4dffd088b1455e90dd1bce7686fcfc.png

На картинке как раз выделена память для буфера глобалов для баз с 8кБ блоками – только такие базы с 8кБ блоками и будут работать в этой системе. Блоки в БД сгруппированы в карты, одна карта в случае с 8кБ блоком описывает 62464 блока, и хранится в блоке карты, который идёт первым в карте.

Типы блоков


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

  • тип 9: блок каталога глобалов. Используется для описания всех имеющихся глобалов и их параметров. Для каждого глобала в этом блоке определена сортировка (collation) индексов глобала — очень важный параметр, отвечающий за сортировку данных. Этот параметр не может быть изменен после создания глобала;
  • тип 66: блок указателей верхнего уровня. На этот блок сверху может указывать только блок каталога глобала;
  • тип 6: блок указателей нижнего уровня, выше него должны быть блоки указателей верхнего уровня, а ниже только блоки данных;
  • тип 70: блок указателей верхнего и нижнего уровня сразу. Используется, когда значений в глобале пока не так много, и нет нужды заводить несколько уровней блоков. Указывает на блоки данных — на такие блоки ссылаются блоки каталога глобалов;
  • тип 2: блок указателей, для хранения достаточно большого глобала. Может потребоваться больше уровней блоков указателей для того, чтобы обеспечить равномерное распределение значений по уровню блоков данных. Данный блок находится между блоками указателями;
  • тип 8: блок данных. В таком блоке хранятся значения не для одного узла глобалов а сразу для нескольких;
  • тип 24: блок хранения больших строк. Если значение одного глобала не может быть умещено в один блок, то оно помещается в такой блок, а узел в блоке данных хранит ссылки на список блоков больших строк, а также общую длину значения;
  • тип 16: блоки карты. Необходимы для хранения информации о том, какие блоки на данный момент свободны.


Итак, в первом блоке базы данных Caché находится служебная информация о файле БД. Во втором – карта блоков. А первый блок каталога идёт третьим (блок номер 3) и таких блоков каталога может быть несколько для БД. Далее идут блоки-указателей (ветви), блоки данных (листья деревьев) и блоки больших строк. Как я уже писал выше, блок(и) каталога глобалов хранит информацию о всех имеющихся глобалах в БД. Он также может хранить настройки глобала даже в том случае, если данных в таком глобале вообще нет. В таком случае узел, описывающий такой глобал, будет иметь нулевую нижнюю ссылку. Просмотреть список глобалов из каталога глобалов можно через портал управления. Там же можно включить возможность сохранения глобала в каталоге после удаления – например, для сохранения сортировки.

400c32bffb6f4b8bbfcf9183017c8640.png

Там же можно создать новый глобал – в таком случае можно задать сразу любую доступную сортировку и выбрать её отличной от той, что установлена по умолчанию в базе данных.

04bb49766950462e908f1fa7ed9cc7a6.png

В общем виде дерево блоков можно представить как на картинке ниже. Красным цветом отмечены ссылки на блоки.
c4042553a2dee5c8c904998d265cf0c3.png

Целостность базы данных


На текущий момент развития СУБД Caché возможные случаи и ошибки, которые могли бы привести к деградации БД, сведены к минимуму, и необходимость ремонта базы данных возникает всё реже. Но проверку целостности в любом случае рекомендуется проводить регулярно на автоматической основе. Для этого есть утилита ^Integrity, которую можно запустить через терминал из области %SYS, через портал управления, на странице Базы данных, а также через менеджер задач. Кстати, задача по автоматической проверке целостности уже настроена по умолчанию, но отключена – её достаточно только активировать:

02ae0d89a6a445f491c1872290295557.png

0b763d6d7089488abf51613b743e9d60.png

В процессе проверки целостности, проверяется правильность указания нижних ссылок, правильность типов блоков, выполняется проверка правых связей. Сравниваются также и узлы глобалов, чтобы они соответствовали порядку сортировки. Если в результате проверки целостности всё-таки были обнаружены ошибки, то можно воспользоваться утилитой ^REPAIR, которую можно запустить в области %SYS. Эта утилита позволяет как просмотреть любой блок, так и подредактировать при необходимости, т.е. отремонтировать БД.

Практика


Но всё это теория. Как выглядит глобал и его блоки на самом деле – судить пока довольно сложно. Единственный сейчас доступный способ просмотра блоков – это упомянутая выше утилита ^REPAIR. Вывод этой программы выглядит примерно так:

dcc46985e80b46e4bf968c83a5156c70.png

Я не так давно начал работать над проектом, который позволяет пройтись по дереву блоков, без риска повредить БД, и удобно просматривать в браузере, с возможностью сохранить эту визуализацию в SVG или PNG-формате. Проект называется CacheBlocksExplorer, исходники проекта выложены на Github.

e790b329d248494f90af903477e399c9.png

Из реализованных возможностей:

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


Что еще необходимо сделать:

  • Отображение правой ссылки: на данный момент отображается как информация по блоку, хотелось бы показать в виде стрелочки;
  • Поддержка отображения блоков больших строк: сейчас они просто не отображаются;
  • Отображение всех блоков каталога глобалов, а не только третьего.


Также хотел сделать отображение сразу всего дерева, но пока не нашёл такой подходящей библиотеки, которая могла бы достаточно быстро отобразить несколько сотен тысяч блоков вместе со связями, в текущей библиотеке это получается очень медленно и отрисовка в браузере получалась медленнее, чем чтение этой структуры в Caché.

В следующей статье я расскажу подробнее на примерах, как всё работает и что можно узнать о наших глобалах и блоках, если у вас есть такой инструмент, как разработанный мной Cache Block Explorer.

© Habrahabr.ru