Системные пакеты предоставляют служебные хранимые процедуры и функции.
- Пакет
RDB$BLOB_UTIL
-
Утилиты для манипуляции BLOB
- Пакет
RDB$PROFILER
-
Профилировщик
- Пакет
RDB$TIME_ZONE_UTIL
-
Утилиты поддержки часовых поясов
Пакет RDB$BLOB_UTIL
предназначен для управления BLOB-объектами так, как это не могут сделать стандартные функции Firebird
такие, как BLOB_APPEND
и SUBSTRING
, или они работают очень медленно.
Эти подпрограммы работают с двоичными данными напрямую, даже с текстовыми BLOB.
Функция RDB$BLOB_UTIL.NEW_BLOB
используется для создания нового BLOB. Он возвращает BLOB, подходящий для добавления данных, как это делает BLOB_APPEND
.
Преимущество по сравнению с BLOB_APPEND
заключается в том, что можно установить собственные параметры SEGMENTED
и TEMP_STORAGE
.
Функция BLOB_APPEND
всегда создаёт BLOB во временном хранилище. Это может быть не лучшим подходом,
если созданный BLOB будет храниться в постоянной таблице, поскольку для этого потребуется копирование.
Возвращённый BLOB из этой функции, даже если TEMP_STORAGE = FALSE
, может использоваться с BLOB_APPEND
для добавления данных.
RDB$BLOB_UTIL.NEW_BLOB
Параметр | Тип | Описание |
---|---|---|
|
|
Тип BLOB. Если TRUE - будет создан сегментированный BLOB, FALSE - потоковый. |
|
|
В каком хранилище создаётся BLOB. TRUE - во временном, FALSE - в постоянном (для записи в обычную таблицу). |
BLOB SUB_TYPE BINARY
Функция RDB$BLOB_UTIL.OPEN_BLOB
используется для открытия существующего BLOB для чтения.
Она возвращает дескриптор (целое число, связанное с транзакцией), подходящий для использования с другими функциями этого пакета,
такими как SEEK
, READ_DATA
и CLOSE_HANDLE
.
RDB$BLOB_UTIL.OPEN_BLOB
Параметр | Тип | Описание |
---|---|---|
|
|
Входной BLOB. |
INTEGER
Функция RDB$BLOB_UTIL.IS_WRITABLE
возвращает TRUE
, если BLOB подходит для добавления данных без копирования с использованием BLOB_APPEND
.
RDB$BLOB_UTIL.IS_WRITABLE
Параметр | Тип | Описание |
---|---|---|
|
|
Проверяемый BLOB. |
BOOLEAN
Функция RDB$BLOB_UTIL.READ_DATA
используется для чтения фрагментов данных из дескриптора BLOB,
открытого с помощью RDB$BLOB_UTIL.OPEN_BLOB
. Когда BLOB полностью прочитан и данных больше нет, она возвращает NULL
.
Если в LENGTH
передаётся положительное число, то возвращается VARBINARY
максимальной длины LENGTH
.
Если в LENGTH
передаётся NULL
, то возвращается только сегмент BLOB с максимальной длиной 32765.
RDB$BLOB_UTIL.READ_DATA
Параметр | Тип | Описание |
---|---|---|
|
|
Дескриптор открытого BLOB. |
|
|
Количество байт, которое необходимо прочитать. |
VARBINARY(32765)
Функция RDB$BLOB_UTIL.SEEK
используется для установки позиции для следующего READ_DATA
. Она возвращает новую позицию.
Параметр MODE
может быть 0 (с начала), 1 (с текущей позиции) или 2 (с конца).
Когда параметр MODE
равен 2, OFFSET
должен быть нулевым или отрицательным.
RDB$BLOB_UTIL.SEEK
Параметр | Тип | Описание |
---|---|---|
|
|
Дескриптор открытого BLOB. |
|
|
Режим поиска. |
|
|
Смещение, байт. |
INTEGER
Процедура RDB$BLOB_UTIL.CANCEL_BLOB
используется для немедленного освобождения временного BLOB-объекта, например созданного с помощью BLOB_APPEND
.
Обратите внимание, что если тот же BLOB используется после отмены, с использованием той же переменной или другой с той же ссылкой на идентификатор BLOB, то будет вызвана ошибка "invalid blob id error".
RDB$BLOB_UTIL.CANCEL_BLOB
Параметр | Тип | Описание |
---|---|---|
|
|
BLOB для отмены. |
Процедура RDB$BLOB_UTIL.CLOSE_HANDLE
используется для закрытия дескриптора BLOB, открытого с помощью RDB$BLOB_UTIL.OPEN_BLOB
.
Незакрытые дескрипторы закрываются автоматически только при завершении транзакции.
RDB$BLOB_UTIL.CLOSE_HANDLE
Параметр | Тип | Описание |
---|---|---|
|
|
Дескриптор BLOB для закрытия. |
execute block returns (b blob)
as
begin
-- Create a BLOB handle in the temporary space.
b = rdb$blob_util.new_blob(false, true);
-- Add chunks of data.
b = blob_append(b, '12345');
b = blob_append(b, '67');
suspend;
end
execute block returns (s varchar(10))
as
declare b blob = '1234567';
declare bhandle integer;
begin
-- Open the BLOB and get a BLOB handle.
bhandle = rdb$blob_util.open_blob(b);
-- Get chunks of data as string and return.
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
-- Here EOF is found, so it returns NULL.
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
-- Close the BLOB handle.
execute procedure rdb$blob_util.close_handle(bhandle);
end
set term !;
execute block returns (s varchar(10))
as
declare b blob;
declare bhandle integer;
begin
-- Create a stream BLOB handle.
b = rdb$blob_util.new_blob(false, true);
-- Add data.
b = blob_append(b, '0123456789');
-- Open the BLOB.
bhandle = rdb$blob_util.open_blob(b);
-- Seek to 5 since the start.
rdb$blob_util.seek(bhandle, 0, 5);
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
-- Seek to 2 since the start.
rdb$blob_util.seek(bhandle, 0, 2);
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
-- Advance 2.
rdb$blob_util.seek(bhandle, 1, 2);
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
-- Seek to -1 since the end.
rdb$blob_util.seek(bhandle, 2, -1);
s = rdb$blob_util.read_data(bhandle, 3);
suspend;
end!
set term ;!
create table t(b blob);
set term !;
execute block returns (bool boolean)
as
declare b blob;
begin
b = blob_append(null, 'writable');
bool = rdb$blob_util.is_writable(b);
suspend;
insert into t (b) values ('not writable') returning b into b;
bool = rdb$blob_util.is_writable(b);
suspend;
end!
set term ;!
Пакет RDB$PROFILER
предназначен для управления сеансами профилирования.
Note
|
|
Подробное описание таблиц и представлений плагина профилирования Default_Profiler см. в приложении Таблицы плагинов. Плагин профилирования Default_Profiler
.
Функция RDB$PROFILER.START_SESSION
запускает новый сеанс профилировщика, превращает его в текущий сеанс (для заданного ATTACHMENT_ID
) и возвращает его идентификатор.
RDB$PROFILER.START_SESSION
Параметр | Тип | Описание |
---|---|---|
|
|
Пользовательское описание сеанса профилирования. По умолчанию |
|
|
Интервал автоматического сброса статистики в таблицы снимков. По умолчанию |
|
|
Идентификатор соединения для которого запускается сеанс профилирования. По умолчанию |
|
|
Наименование плагина профилирования. По умолчанию |
|
|
Параметры специфичные для плагина профилирования. По умолчанию |
Тип выходного результата: BIGINT NOT NULL
.
Если параметр FLUSH_INTERVAL
отличен от NULL
, то включается автоматический сброс статистики так же, как при вызове RDB$PROFILER.SET_FLUSH_INTERVAL
вручную.
Если параметр PLUGIN_NAME
имеет значение NULL
(по умолчанию), он использует конфигурацию базы данных из параметра DefaultProfilerPlugin
.
Для плагина Default_Profiler
допустимыми значениями параметра PLUGIN_OPTIONS
является NULL
или строка DETAILED_REQUESTS
.
Если указана опция DETAILED_REQUESTS
, то таблица PLG$PROF_REQUESTS
будет хранить подробные данные запросов, то есть одну запись для каждого вызова оператора. Это может привести к созданию большого количества записей, что приведёт к медленной работе RDB$PROFILER.FLUSH
.
Когда DETAILED_REQUESTS
не используется (по умолчанию), таблица PLG$PROF_REQUESTS
сохраняет агрегированную запись для каждого оператора, используя REQUEST_ID = 0
.
Процедура RDB$PROFILER.CANCEL_SESSION
отменяет текущий сеанс профилировщика (для заданного ATTACHMENT_ID
).
Все данные сеанса, присутствующие в плагине профилировщика, отбрасываются и не сбрасываются.
Уже сброшенные данные не удаляются автоматически.
RDB$PROFILER.CANCEL_SESSION
Параметр | Тип | Описание |
---|---|---|
|
|
Идентификатор соединения для которого отменяется сеанс профилирования. По умолчанию |
Процедура RDB$PROFILER.DISCARD
удаляет все сеансы (для заданного ATTACHMENT_ID
) из памяти, не сбрасывая их.
Если есть активная сессия, она отменяется.
RDB$PROFILER.DISCARD
Параметр | Тип | Описание |
---|---|---|
|
|
Идентификатор соединения для которого удаляются все сеансы профилирования. По умолчанию |
Процедура RDB$PROFILER.FINISH_SESSION
завершает текущий сеанс профилировщика (для заданного ATTACHMENT_ID
).
RDB$PROFILER.FINISH_SESSION
Параметр | Тип | Описание |
---|---|---|
|
|
Сбрасывать ли текущую статистику профилирования в таблицы моментальных снимков. |
|
|
Идентификатор соединения для которого завершается сеанс профилирования. По умолчанию |
Если значение параметра FLUSH
равно TRUE
, то таблицы моментальных снимков обновляются данными завершённого сеанса (и старых завершённых сеансов, ещё не присутствующих в моментальном снимке). В противном случае данные остаются только в памяти для последующего обновления.
Вызов RDB$PROFILER.FINISH_SESSION(TRUE)
имеет тот же смысл, что и вызов RDB$PROFILER.FINISH_SESSION(FALSE)
, за которым следует RDB$PROFILER.FLUSH
(с использованием того же ATTACHMENT_ID
).
Процедура RDB$PROFILER.FLUSH
обновляет таблицы моментальных снимков данными из сеансов профиля (для заданного ATTACHMENT_ID
) в памяти.
RDB$PROFILER.FLUSH
Параметр | Тип | Описание |
---|---|---|
|
|
Идентификатор соединения для которого обновляются таблицы моментальных снимков из сеансов профилирования. По умолчанию |
После обновления данные сохраняются в таблицах PLG$PROF_SESSIONS
, PLG$PROF_STATEMENTS
, PLG$PROF_RECORD_SOURCES
, PLG$PROF_REQUESTS
, PLG$PROF_PSQL_STATS
и PLG$PROF_RECORD_SOURCE_STATS
и могут быть прочитаны и проанализированы пользователем.
Данные обновляются с помощью автономной транзакции, поэтому если процедура вызывается в snapshot транзакции, данные не будут доступны для прямого чтения в той же транзакции.
После сброса завершённые сеансы удаляются из памяти.
Процедура RDB$PROFILER.PAUSE_SESSION
приостанавливает текущий сеанс профилировщика (для заданного ATTACHMENT_ID
), после чего статистика для последующих выполненных операторов не собирается.
RDB$PROFILER.PAUSE_SESSION
Параметр | Тип | Описание |
---|---|---|
|
|
Сбрасывать ли текущую статистику профилирования в таблицы моментальных снимков. |
|
|
Идентификатор соединения для которого приостанавливается сеанс профилирования. По умолчанию |
Если параметр FLUSH
имеет значение TRUE
, таблицы моментальных снимков обновляются данными до текущего момента.
В противном случае данные остаются только в памяти для последующего обновления.
Вызов RDB$PROFILER.PAUSE_SESSION(TRUE)
имеет тот же смысл, что и вызов RDB$PROFILER.PAUSE_SESSION(FALSE)
, за которым следует RDB$PROFILER.FLUSH
(с использованием того же ATTACHMENT_ID
).
Процедура RDB$PROFILER.RESUME_SESSION
возобновляет текущий сеанс профилировщика (для заданного ATTACHMENT_ID
), если он был приостановлен, после чего вновь собирается статистика последующих выполненных операторов.
RDB$PROFILER.RESUME_SESSION
Параметр | Тип | Описание |
---|---|---|
|
|
Идентификатор соединения для которого возобновляется сеанс профилирования. По умолчанию |
Процедура RDB$PROFILER.SET_FLUSH_INTERVAL
включает периодическую автоматическую сброс статистики в таблицы моментальных снимков (когда FLUSH_INTERVAL
больше 0) или выключает (когда FLUSH_INTERVAL
равно 0).
RDB$PROFILER.SET_FLUSH_INTERVAL
Параметр | Тип | Описание |
---|---|---|
|
|
Интервал автоматического сброса статистики. Задаётся в секундах. |
|
|
Идентификатор соединения для которого обновляются таблицы моментальных снимков из сеансов профилирования. По умолчанию |
Профилировщик позволяет пользователям измерять стоимость производительности кода SQL и PSQL.
Это реализовано с помощью системного пакета в движке, передающего данные плагину профилировщика.
В этой документации части движка и плагина рассматриваются как единое целое, так как будет использоваться профилировщик по умолчанию (Default_Profiler).
Пакет RDB$PROFILER
позволяет профилировать выполнение кода PSQL, собирая статистику о том, сколько раз выполнялась каждая строка, а также её минимальное, максимальное и накопленное время выполнения (с точностью до наносекунд), а также открывать и извлекать статистику неявных и явных SQL-курсоров.
Note
|
К сожалению профилировщик не может работать с базами данных 1 SQL-диалекта. Это происходит из-за того, что таблицы моментальных снимков содержат поля с типом BIGINT, которые нельзя создать в 1-диалекте. |
Для сбора данных профиля пользователь должен сначала запустить сеанс профиля с помощью RDB$PROFILER.START_SESSION
. Эта функция возвращает идентификатор сеанса профиля, который позже сохраняется в таблицах моментальных снимков профилировщика для запроса и анализа пользователем. Сеанс профилировщика может быть локальным (то же соединение) или удалённым (другое соединение).
Удалённое профилирование просто перенаправляет команды на удалённое соединение. Это позволяет клиенту одновременно профилировать несколько сеансов. Кроме того, локально или удалённо запущенный сеанс профилировщика может получать команды, выданные в другом соединении.
Для удалённых команд требуется, чтобы целевой сеанс находился в состоянии ожидания, то есть не выполнял других запросов. Когда они не простаивают, вызов блокируется в ожидании этого состояния.
Если удалённое соединение исходит от другого пользователя, вызывающий пользователь должен иметь системную привилегию PROFILE_ANY_ATTACHMENT
.
После запуска сеанса в памяти начинает собираться статистика PSQL и SQL операторов. Обратите внимание, что сеанс профилировщика собирает данные только об операторах, выполненных только в том соединении, которое связанно с сеансом профилировщика.
Данные агрегируются и сохраняются для каждого запроса. При запросе таблиц моментальных снимков пользователь может выполнять дополнительную агрегацию по операторам или использовать вспомогательные представления, которые делают это автоматически.
Сеанс профилирования может быть приостановлен для временного отключения сбора статистики. Его можно возобновить позже, чтобы вернуть сбор статистики в том же сеансе.
Новый сеанс профилировщика может быть запущен, когда уже есть активный сеанс. В этом случае текущий сеанс завершается как будто была вызвана процедура
RDB$PROFILER.FINISH_SESSION(FALSE)
, поэтому таблицы моментальных снимков не обновляются в этот момент.
Чтобы проанализировать собранные данные, пользователь должен сбросить данные в таблицы моментальных снимков,
что можно сделать, завершив или приостановив сеанс (с параметром FLUSH
, установленным в TRUE
) или вызвав RDB$PROFILER.FLUSH
.
Данные сбрасываются с помощью автономной транзакции (транзакция, запущенная и завершенная для конкретной цели обновления данных профилировщика).
Ниже приведён пример сеанса профилировщика и запросов для анализа данных.
-
Подготовка — создание таблицы и процедур, которые будут анализироваться.
create table tab ( id integer not null, val integer not null ); set term !; create or alter function mult(p1 integer, p2 integer) returns integer as begin return p1 * p2; end! create or alter procedure ins as declare n integer = 1; begin while (n <= 1000) do begin if (mod(n, 2) = 1) then insert into tab values (:n, mult(:n, 2)); n = n + 1; end end! set term ;!
-
Запуск профилирования.
select rdb$profiler.start_session('Profile Session 1') from rdb$database; set term !; execute block as begin execute procedure ins; delete from tab; end! set term ;! execute procedure rdb$profiler.finish_session(true); execute procedure ins; select rdb$profiler.start_session('Profile Session 2') from rdb$database; select mod(id, 5), sum(val) from tab where id <= 50 group by mod(id, 5) order by sum(val); execute procedure rdb$profiler.finish_session(true);
-
Анализ результатов профилирования.
set transaction read committed; select * from plg$prof_sessions; select * from plg$prof_psql_stats_view; select * from plg$prof_record_source_stats_view; select preq.* from plg$prof_requests preq join plg$prof_sessions pses on pses.profile_id = preq.profile_id and pses.description = 'Profile Session 1'; select pstat.* from plg$prof_psql_stats pstat join plg$prof_sessions pses on pses.profile_id = pstat.profile_id and pses.description = 'Profile Session 1' order by pstat.profile_id, pstat.request_id, pstat.line_num, pstat.column_num; select pstat.* from plg$prof_record_source_stats pstat join plg$prof_sessions pses on pses.profile_id = pstat.profile_id and pses.description = 'Profile Session 2' order by pstat.profile_id, pstat.request_id, pstat.cursor_id, pstat.record_source_id;
Пакет RDB$TIME_ZONE_UTIL
содержит процедуры и функции для работы с часовыми поясами.
Функция RDB$TIME_ZONE_UTIL.DATABASE_VERSION
возвращает версию базы данных часовых поясов (из библиотеки icu).
VARCHAR(10) CHARACTER SET ASCII
SELECT rdb$time_zone_util.database_version()
FROM rdb$database;
DATABASE_VERSION ================ 2021a
Процедура RDB$TIME_ZONE_UTIL.TRANSITIONS
возвращает набор правил для часового пояса между начальной и конечной временной меткой.
RDB$TIME_ZONE_UTIL.TRANSITIONS
Параметр | Тип | Описание |
---|---|---|
|
|
Наименование часового пояса |
|
|
Начало интервала дат |
|
|
Окончание интервала дат |
RDB$TIME_ZONE_UTIL.TRANSITIONS
Параметр | Тип | Описание |
---|---|---|
|
|
Дата начала действия правила |
|
|
Дата окончания действия правила |
|
|
Смещение времени в минутах для заданного часового пояса |
|
|
Летнее смещение времени в минутах для заданного часового пояса |
|
|
Эффективное смещение, вычисляется как |
RDB$TIME_ZONE_UTIL.TRANSITIONS
SELECT
RDB$START_TIMESTAMP,
RDB$END_TIMESTAMP,
RDB$ZONE_OFFSET AS ZONE_OFF,
RDB$DST_OFFSET AS DST_OFF,
RDB$EFFECTIVE_OFFSET AS OFF
FROM rdb$time_zone_util.transitions(
'America/Sao_Paulo',
timestamp '2017-01-01',
timestamp '2019-01-01');
RDB$START_TIMESTAMP RDB$END_TIMESTAMP ZONE_OFF DST_OFF OFF ============================ ============================ ======== ======= ==== 2016-10-16 03:00:00.0000 GMT 2017-02-19 01:59:59.9999 GMT -180 60 -120 2017-02-19 02:00:00.0000 GMT 2017-10-15 02:59:59.9999 GMT -180 0 -180 2017-10-15 03:00:00.0000 GMT 2018-02-18 01:59:59.9999 GMT -180 60 -120 2018-02-18 02:00:00.0000 GMT 2018-10-21 02:59:59.9999 GMT -180 0 -180 2018-10-21 03:00:00.0000 GMT 2019-02-17 01:59:59.9999 GMT -180 60 -120