FirebirdSQL logo

Псевдостолбец RDB$DB_KEY

Каждая таблица и представление содержит псевдостолбец RDB$DB_KEY.

Столбец RDB$DB_KEY представляет собой внутренний ключ, который указывает на позицию записи в таблице. Он поддерживаемый сервером базы данных длявнутреннего использования, и может быть использован вами в некоторых случаях, как самый быстрый способ найти запись в таблице.

RDB$DB_KEY является логическим указателем на запись в таблице, и никак не с физическим адресом на диске. Значения RDB$DB_KEY не следуют в предсказуемой последовательности, поэтому не пытайтесь использовать напрямую вычисления, включающие их относительные позиции. Это можно делать только с помощью функцииMAKE_DBKEY.

Important

Значения RDB$DB_KEY не являются стабильными.Они изменяются после резервного копирования и последующего восстановления, а иногда и после подтверждения транзакции.Таким образом, относитесь к RDB$DB_KEY мимолётному значению, и не пытайтесь его использовать, когда транзакция в которой он получен, завершена или отменена.

Размер RDB$DB_KEY

Для таблиц поле RDB$DB_KEY использует 8 байт и имеет тип BINARY(8). Для представлений поле RDB$DB_KEY использует размер 8 умноженное на количество таблициспользуемых в представлении. Например, если представление соединяет три таблицы, его RDB$DB_KEY использует 24 байт. Это важно, когда вы работаете с PSQL модулями и собираетесь сохранять RDB$DB_KEY в переменных. Вы должны использовать тип данных BINARY(n) корректной длины. Точное значение длинны поля RDB$DB_KEY можно узнатьиспользуя системную таблицу RDB$RELATIONS. Она хранится в поле RDB$DBKEY_LENGTH.

Example 1. Определение длины RDB$DB_KEY для представления V_FARM
SELECT
  RDB$DBKEY_LENGTH
FROM RDB$RELATIONS
WHERE RDB$RELATION_NAME = 'V_FARM'

Использование RDB$DB_KEY

Поскольку RDB$DB_KEY напрямую указывает на место хранения записи, он будет быстрее для поиска, чем первичный ключ. Если по каким-то причинам в таблице нет первичного ключа или активного уникального индекса, или уникальный индекс допускает NULL значения, то возможно существование полных дубликатов записей. В этих условиях RDB$DB_KEY является единственным способом точной идентификации каждой записи.

Сервер Firebird использует RDB$DB_KEY для оптимизации, некоторых методов доступа. Например, для оптимизации внешней сортировки. Если ширина записи для сортировки очень велика (превышает значение указанное в параметре конфигурации InlineSortThreshold), то вместо классической внешней сортировки используется сортировка только ключей, с сохранением RDB$DB_KEY для связанных таблиц, и последующем выполнением Refetch для извлечения записей этих таблиц по сохранённым RDB$DB_KEY.

Другим применением RDB$DB_KEY и функции MAKE_DBKEY является разбиение больших таблиц на приблизительно одинаковые части, что используется при параллельном резервном копировании.

Example 2. Разбиение большой таблицы на части
-- Получение данных таблицы SOMETABLE, содержащихся на страницах данных (DP),
-- на которые указывает первая страница указателей (PP).
select * from SOMETABLE
where rdb$db_key >= make_dbkey('SOMETABLE', 0, 0, 0)
  and rdb$db_key <  make_dbkey('SOMETABLE', 0, 0, 1);

-- Получение данных таблицы SOMETABLE, содержащихся на страницах данных (DP),
-- на которые указывает вторая страница указателей (PP).
select * from SOMETABLE
where rdb$db_key >= make_dbkey('SOMETABLE', 0, 0, 1)
  and rdb$db_key <  make_dbkey('SOMETABLE', 0, 0, 2);

...

Время жизни RDB$DB_KEY

По умолчанию областью действия RDB$DB_KEY является текущая транзакция. Вы можете считать, что он остаётся правильным во время действия текущей транзакции. Подтверждение или откат транзакции приведёт к тому, что значения RDB$DB_KEY станут непредсказуемыми. Если вы используете COMMIT RETAINING, контекст транзакции сохраняется, блокируя сборку мусора и, следовательно, предотвращая "переназначение" старого db_key. При этих условиях значения RDB$DB_KEY для любых используемых записей в вашей транзакции сохраняются действительными, пока не произойдёт "жёсткое" подтверждение или откат.

После жёсткого подтверждения или отката другая транзакция может удалить запись, которая была изолирована внутри контекста вашей транзакции и, следовательно, рассматривалась как "существующая" в вашем приложении. Любое значение RDB$DB_KEY теперь может указывать на несуществующую запись или другую запись помещённую на это место.