По умолчанию функция является лишь ««черный ящик»» , о поведении которой системе баз данных практически ничего не известно. Однако это означает, что запросы с использованием этой функции могут выполняться гораздо менее эффективно, чем могли бы. Для оптимизации вызовов функций планировщику можно предоставить дополнительные сведения.
Некоторые основные сведения могут быть предоставлены посредством декларативных аннотаций, содержащихся в CREATE FUNCTION команде. Наиболее важным из этих параметров является категория
изменчивости (IMMUTABLE, STABLE,
или VOLATILE); этот параметр всегда следует указывать максимально точно при определении функции. Свойство безопасности параллельного режима (PARALLEL
UNSAFE, PARALLEL RESTRICTED, или
PARALLEL SAFE) также необходимо определить, если планируется использовать функцию в параллельных запросах. Кроме того, целесообразно указать оценочную стоимость выполнения функции и/или ожидаемое количество строк для функции, возвращающей набор данных. Однако декларативный способ задания этих двух характеристик позволяет указывать только константные значения, что часто бывает недостаточно.
Также предусмотрена возможность назначения вспомогательной функции планировщика вызываемой из SQL функции (называемой в данном контексте целевой функцией), что позволяет предоставить сведения о целевой функции, слишком сложные для декларативного описания. Вспомогательные функции планировщика должны быть написаны на языке C (хотя их целевые функции могут быть реализованы иначе), поэтому данный продвинутый функционал будет использоваться относительно редко.
Вспомогательная функция планировщика должна иметь следующую SQL-сигнатуру:
supportfn(internal) returns internal
Она связывается с целевой функцией путем указания
предложения SUPPORT при создании целевой функции.
Подробное описание API для вспомогательных функций планировщика приведено в файле src/include/nodes/supportnodes.h в составе
Digital Q.DataBase исходного кода. В данном разделе представлен лишь краткий обзор возможностей вспомогательных функций планировщика. Набор типов запросов к вспомогательной функции является расширяемым, поэтому в будущих версиях функционал может быть дополнен.
Некоторые вызовы функций могут быть упрощены на этапе планирования на основе свойств, характерных для конкретной функции. Например, вызов
int4mul(n, 1) может быть упрощен до
простого выражения n. Преобразования такого типа могут выполняться вспомогательной функцией планировщика, если она поддерживает тип запроса SupportRequestSimplify . Вспомогательная функция будет вызываться для каждого экземпляра целевой функции, обнаруженного в дереве разбора запроса. Если будет определено, что конкретный вызов функции может быть упрощен, вспомогательная функция может сформировать и вернуть дерево разбора, представляющее новое выражение. Это правило будет автоматически применяться
и к операторам, основанным на данной функции, — так, в приведенном
примере выражение n * 1 также будет упрощено до
n. (Однако следует отметить, что это лишь пример; данная оптимизация фактически не выполняется стандартными средствами Digital Q.DataBase.)
Мы не гарантируем, что Digital Q.DataBase никогда не вызовет целевую функцию в тех случаях, когда вспомогательная функция может выполнить упрощение. Обеспечьте строгое соответствие между упрощенным выражением и фактическим результатом выполнения целевой функции.
Для целевых функций, возвращающих тип данных boolean, часто бывает полезно оценить
долю строк, которые будут выбраны через WHERE WHERE с использованием этой
функции. Это можно сделать с помощью вспомогательной функции, реализующей
тип запроса SupportRequestSelectivity request type.
Если время выполнения целевой функции сильно зависит от входных данных, может быть полезно предоставить для неё переменную оценку стоимости. Это может быть реализовано вспомогательной функцией через тип запроса SupportRequestCost request type.
Для целевых функций, возвращающих наборы данных, часто полезно предоставить переменную оценку количества возвращаемых строк. Это может быть реализовано вспомогательной функцией через тип запроса SupportRequestRows request type.
Для целевых функций, возвращающих тип данных boolean, может появиться возможность
преобразовать вызов функции, присутствующий в WHERE в предложение или предложения индексируемого оператора. Преобразованные предложения могут быть полностью эквивалентны условию функции либо могут быть менее строгими (то есть они могут допускать некоторые значения, которые не удовлетворяют условию функции). В последнем случае условие индекса считается lossy; функция всё еще может использоваться для сканирования индекса, но вызов функции должен будет выполняться для каждой строки, возвращаемой индексом, чтобы проверить, действительно ли она удовлетворяет WHERE условию или нет. Для создания таких условий вспомогательная функция должна реализовывать SupportRequestIndexCondition request type.