Век живи — век учись. Оказывается, уже начиная с версии 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).
Вместо сдвига всего правого поддиапазона относительно вставляемой записи будем выискивать свободные места и перемещать отдельные "кусочки".
Комментариев нет:
Отправить комментарий