8 нояб. 2011 г.

USING INDEX

Век живи — век учись. Оказывается, уже начиная с версии 1.5 в Firebird можно именовать индексы ограничений и указывать их сортировку. Синтаксис соответствующей команды:
[CONSTRAINT constraint-name]
   <constraint-type> <constraint-definition>
   [USING [ASC[ENDING] | DESC[ENDING]] INDEX index_name]
В Гедымине мы используем суррогатные целочисленные первичные ключи. Идентификатор конкретной записи уникален в пределах всех таблиц базы и является положительным числом. Никакого дополнительного смысла в идентификатор не вкладывается, за исключением диапазона от 0 до 146999999, зарезервированного для системных объектов.

Дополнительный смысл — иными словами говоря функциональная зависимость первичного ключа от некоторого поля (полей) записи помогла бы ускорить выполнение некоторых запросов и уменьшить размер базы данных. Вот несколько возможных случаев:

  • Для таблицы gd_document присваивать идентификатор в соответствии с хронологией документов. Тогда сортировка по дате и выборка за период (две наиболее частых операции со списком документов) будут выполняться с использованием индекса первичного ключа, который и так всегда под рукой у оптимизатора для соединений с дополнительными таблицами. Для быстрой выборки за период можно держать под рукой соответствие начальных ИД на каждую дату.
  • Идентификатор для интервальных деревьев присваивать в соответствии с порядковым номером узла при обходе дерева вглубь. Отпадает необходимость в полях LB, RB. Интервал для дочерних элементов будет определяться как разность между ИД соседних узлов. Для совместимости с существующим кодом можно ввести вычисляемые поля LB (просто будет возвращать значение идентификатора записи) и RB (идентификатор следующей записи на этом же уровне минус единица).
  • Для складских карточек (таблица INV_CARD) присваивать идентификатор в соответствии с очередностью цепочки, заменив поле parent на признак первой карточки в последовательности.
  • и т.д.
Можно сказать, что идет речь о симуляции кластерного индекса для таблиц, абсолютное большинство запросов к которым требует сортировки по определенному полю и/или отсечению заданного диапазона значений. Разумеется, что множество значений рассматриваемого поля должно быть линейно упорядоченным.

Основная проблема реализации такой концепции — это вставка идентификатора внутрь существующей цепочки. При отсутствии свободного промежутка придется сдвигать все идентификаторы вправо, что может вызвать цепную реакцию — каскадное обновление огромного количества записей в базе (представьте сдвиг вправо нескольких миллионов записей в таблице gd_document, к которым привязаны дополнительные таблицы документов, бухгалтерские проводки и складское движение). Мы можем минимизировать последствия, если:

  • Откажемся от единого на всю базу генератора gd_g_unique в пользу выделенного генератора для каждой таблицы. Будем формировать идентификаторы с шагом 10 (для менее населенных таблиц можно использовать шаг 100 и даже 1000).
  • Вместо сдвига всего правого поддиапазона относительно вставляемой записи будем выискивать свободные места и перемещать отдельные "кусочки".

Комментариев нет:

Отправить комментарий