Перейти к основному содержимому
Версия: 7.0

Правила: исполнение

Таблицы

Хранение данных в базе описано в таблицах.

  1. Таблицы следует объявлять явно для каждого используемого набора классов ключей, а свойства с этим набором параметров — размещать в них опцией TABLE. Автоматически созданной таблицы _auto_... в логике быть не должно: ее имя строится из идентификаторов классов свойства, отсортированных по алфавиту, поэтому изменение набора классов переносит данные в другую таблицу, а перестановка тех же классов местами оставляет их в той же.

  2. Свойства с одинаковым набором параметров, которые обычно читаются вместе, следует хранить в одной таблице: тогда их чтение не требует соединения таблиц.

  3. Опцию NODEFAULT следует использовать для таблиц узкого назначения, в которые свойства должны попадать только явно.

  4. Опцию FULL следует указывать для таблицы, которая содержит все объекты классов своих ключей. Она влияет только на способ выполнения запросов, поэтому указывать ее для таблицы, которая заполнена не для всех объектов, нельзя.

  5. Политику именования следует выбирать на старте проекта. Короткая политика делает имена в базе читаемыми, но при большом количестве материализованных свойств требует явных имен полей, чтобы имена оставались уникальными.

Материализации

Сам механизм описан в материализациях.

  1. Материализовать следует агрегированные свойства, которые читаются или используются в условиях фильтрации значительно чаще, чем меняются данные, от которых они зависят.

  2. Материализовать не следует свойства, у которых значение не NULL для бесконечного числа наборов объектов, — такое свойство материализовать нельзя. Типичный случай — свойство с параметром встроенного класса, например датой, не ограниченным условием.

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

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

  5. После изменения определения материализованного свойства или прямого исправления данных в базе хранимые значения следует пересчитать оператором RECALCULATE.

Индексы

Сам механизм описан в индексах.

  1. Индексы следует создавать для свойств, по которым выполняется фильтрация или поиск в формах и запросах, и не следует создавать «на всякий случай»: каждый индекс обновляется при каждом изменении значений его полей.

  2. Индексировать можно только материализованные свойства, поэтому индекс по вычисляемому свойству требует его материализации — и решение о ней принимается по правилам материализации из этой же статьи — свойство материализуют потому, что его читают или используют в фильтрации заметно чаще, чем меняются данные, от которых оно зависит, а не ради индекса.

  3. Составной индекс следует создавать, когда фильтрация идет сразу по нескольким полям одной таблицы; первыми в нём должны идти поля, ограничиваемые равенством, а за ними — поле, ограничиваемое диапазоном: именно на такой форме btree-скан сужается лучше всего.

  4. Индекс, дублирующий автоматически создаваемые, создавать не следует: уникальный индекс по всем ключам таблицы и индексы по суффиксам ключей уже существуют.

  5. Для полей, по которым выполняется поиск операторами LIKE и MATCH, следует использовать одноименные типы индексов, а не обычный индекс.

Примеры

Таблица на каждый набор классов ключей, свойство размещено в неё опцией TABLE, материализован читаемый результат — построчный sum оставлен вычисляемым, потому что правило 3 запрещает хранить промежуточный шаг цепочки. В составном индексе поле, ограниченное равенством, стоит перед полем, ограниченным диапазоном, как требует правило 3 правил индексов.

TABLE order (Order);
TABLE orderDetail (OrderDetail);
TABLE skuStock (Sku, Stock);

date = DATA DATE (Order) TABLE order INDEXED;
sum (OrderDetail d) = quantity(d) * price(d);
sum (Order o) = GROUP SUM sum(OrderDetail d) BY order(d) MATERIALIZED TABLE order;

INDEX customer(Order o), date(o);