Хранение данных и доступ к ним
11.1.3 Строки таблиц в блоках базы
Посмотрим, как строки размещаются в блоках таблиц все того же Oracle. Формат строки приведен на рисунке 11.3.:
Заголовок строки состоит из трех байтов — Flag, Lock и Column Count. Отдельные биты байта Flag описывают состояние и расположение строки.
Второй байт определяет особенности блокировок. Третий определяет количество столбцов в строке.
Столбец определяется двумя полями. Первое задает длину столбца, во второе записываются сами данные. Поле Column length принимает значения:
- размер столбца в байтах, если он не занимает больше 253 байт;
- FE+(еще 2 байта длины) —если ширина столбца больше 253 байт;
- FF, если в столбце — NULL; поле Column Data при этом отсутствует
Величина 253 получается потому, что из возможных 256 вариантов три
выпали. Значение 0 не употребляется, так как ширина столбца не может быть нулевой. Код FF обозначает NULL, а FE обозначает столбцы большой длины.
Интересны детали работы со строками в блоке. Запись новых строк ведется от хвоста блока к его голове, где находится заголовок блока. При этом имеющиеся свободные места между строками не учитываются. При удалении строки устанавливается в единицу бит удаления. С данными ничего не происходит. Все остается на прежних местах. При обновлении строки с уменьшением размера она не останется на прежнем месте, а перейдет наверх. И только при обновлениях с сохранением длины всех столбцов строка останется на прежнем месте. Таким образом, при выполнении удалений и обновлений блок постоянно фрагментируется. Тип CHAR в этом отношении имеет преимущества перед VARCHAR. Ниже мы обратим внимание на то, что СУБД может дефрагментировать пространство блока данных.
11.1.4 Заполнение табличного сегмента и миграция строк
Табличный сегмент заполняется последовательно, начиная с первых блоков первого экстента. Указатель, называемый High Water Mark (HWM) устанавливается на первом блоке незаполненной части сегмента. Если затем один или несколько блоков освободятся, HWM сам не сместится вниз. То есть, HWM это что-то вроде медицинского термометра: вверх столбик ртути лезет сам (это соответствует занятию данными очередного блока), а для сбрасывания столбика ртути необходимо встряхнуть термометр (в базе данных это делается с помощью специальной инструкции).
Блоки, расположенные ниже HWM и имеющие достаточно места для вставки новых данных, включены в один из списков свободных блоков. В этот список блок может попасть после сдвига HWM вниз или в случае уменьшения занятого пространства внутри блока, расположенного ниже указателя.
Если в результате обновления размер строки превышает доступное свободное место в блоке, необходимо найти другой блок, в котором строка может поместиться, и перенести ее туда. Происходит миграция строки.
Если в один блок строку поместить не удается, то ее разбивают на части. Первая часть строки остается в том же блоке (конечно, этот блок исключается из списка свободных блоков), остальные ее части размещаются в других блоках. Такие строки называются сцепленными. Для доступа к ним может потребоваться несколько чтений с диска, что значительно замедлит обработку.
Современные базы допускают длину строк до 4 Гбайт. При современных размерах блоков от 4 до 64 Кбайт такие строки всегда представляются только сцепленными строками, в которых каждая часть занимает весь блок.
Теперь пример раздела 10.3.1 с извлечением информации о созданной таблице с помощью метода get_ddl() стал значительно понятнее: начальный размер сегмента таблицы 64K, PCTFREE = 10%, PCTUSED = 40%, "PCTPNCREASE 0" означает, что увеличение сегмента производится равными экстентами, "FREELISTS 1" определяет единственный список блоков пригодных для записи, сегмент таблицы находится в табличном пространстве USERS и т. д.
11.1.5 Фрагментация
Рассматривая заполнение блока, мы пришли к выводу о возможной фрагментации его пространства. Но этот процесс может затронуть и сегменты, и табличные пространства.
В табличном пространстве могут образовываться фрагментированные свободные области. Они имеют структуры пузырьковую (как правило, одиночные свободные области между занятыми областями) или сотовую (как правило, несколько свободных областей между занятыми). Фрагментация табличных пространств снижает производительность создания, расширения и удаления хранимых объектов.
Фрагментация сегментов — это естественное явление, которое мало влияет на производительность.
Фрагментация блоков существенно снижает производительность, как запросов, так и инструкций манипулирования данными.
Основные производители СУБД прекрасно понимают проблемы, связанные с фрагментацией базы, и движение в сторону автоматического обнаружения фрагментации и устранения ее вредных разновидностей наблюдается давно и уже близко к завершению.
В заключение заметим, что для нас важно общее представление о структурах хранения, процессах работы с ними, о миграции строк, образовании фрагментации и путях ее устранения. Так легче представить "закулисную" сторону работы СУБД и не поддаваться соблазну простых решений, которые могут игнорировать перечисленные особенности.
11.1.6 Столбцовая и строчная организация таблиц
До сих пор мы рассматривали таблицы со строчной организацией, в которых строка хранилась в виде записи, находящейся в одном блоке. При столбцовой организации основная единица хранения не строка, а столбец, так что в одном блоке будут храниться значения одного столбца для нескольких строк. Имеются средства для автоматической "сборки" значений столбцов в одну строку, так что дальше все идет в привычном русле.
На самом деле существуют СУБД реляционного типа, которые хранят данные в столбцах (Sybase IQ и др.). В других используется строчное представление основных типов данных, а большие типы (BLOB'bi) хранятся в столбцах (Oracle).
Одно из важных отличий в том, что для строчной организации естественная минимальная единица блокировки — строка, а для столбцовой, естественно, — столбец. Другое отличие в том, что, например, для выполнения запроса
SELECT coll FROM TABLE WHERE COl25=1
к таблице из 25 столбцов со столбцовой организацией теперь не нужно читать "лишние" данные из 23 столбцов.
Строчная организация эффективнее, когда чаще требуются данные всей или большей части строки. Столбцовая организация выгоднее когда в таблицах много столбцов, но в запросах используется незначительная их часть.
В современных СУБД со столбцовой организацией применяются бестиповые столбцы, допускающие в качестве элемента хранения дерево, набор версий и т.д.
Большой интерес представляют СУБД столбцового типа BigTable фирмы Google, Everest фирмы Yahoo, Hadoop и Hbase. Все они предназначены для создания хранилищ данных очень большого объема в больших кластерах серверов или облаках. CouchDB столбцовая, документно-ориентированная база.
Может показаться, что использование вертикальной сегментации таблиц со строчной организацией на двухстолбцовые таблицы с индексом (второй столбец нужен для связи) даст те же результаты, что при столбцовой организации. Оказалось, что это предположение неверно.