64.3. Функции поддержки B-дерева#

64.3. Функции поддержки B-дерева

64.3. Функции поддержки B-дерева #

Согласно Таблица 35.8, btree определяет одну обязательную и четыре дополнительные функции поддержки. Пять пользовательских методов включают:

order

Для каждой комбинации типов данных, для которых семейство операторов btree предоставляет операторы сравнения, оно должно предоставлять опорную функцию сравнения, зарегистрированную в pg_amproc с номером опорной функции 1 и amproclefttype/amprocrighttype, равными левому и правому типам данных для сравнения (т.е. тем же типам данных, с которыми зарегистрированы соответствующие операторы в pg_amop). Функция сравнения должна принимать два ненулевых значения A и B и возвращать значение int32, которое является < 0, 0 или > 0, когда A < B, A = B или A > B соответственно. Результат null запрещен: все значения типа данных должны быть сравнимыми. См. примеры в src/backend/access/nbtree/nbtcompare.c.

Если сравниваемые значения имеют тип данных, который поддерживает правило сортировки, соответствующий OID правила сортировки будет передан в функцию поддержки сравнения с использованием стандартного механизма PG_GET_COLLATION().

sortsupport

По желанию, семейство операторов btree может предоставлять функции поддержки сортировки, зарегистрированные под номером 2. Эти функции позволяют реализовать сравнения для целей сортировки более эффективным способом, чем просто вызов опорные функции сравнения. Соответствующие API определены в файле src/include/utils/sortsupport.h.

in_range

По желанию, семейство операторов btree может предоставлять опорные функции in_range, зарегистрированные под номером 3. Они не используются во время операций индексирования btree; вместо этого они расширяют семантику семейства операторов таким образом, чтобы оно могло поддерживать оконные предложения, содержащие типы границ рамки RANGE offset PRECEDING и RANGE offset FOLLOWING (см. Раздел 4.2.8). В основном, предоставляемая дополнительная информация определяет, как добавить или вычесть значение offset таким образом, чтобы оно было совместимо с упорядочиванием данных семейства.

Функция in_range должна иметь сигнатуру

in_range(val type1, base type1, offset type2, sub bool, less bool)
returns bool

val и base должны быть одного типа, который является одним из типов, поддерживаемых семейством операторов (т.е. типом, для которого он предоставляет упорядочение). Однако, offset может быть другого типа, который может быть неподдерживаемым семейством. Примером является встроенное семейство time_ops, которое предоставляет функцию in_range, у которой offset имеет тип interval. Семейство может предоставлять функции in_range для любого из поддерживаемых типов и одного или нескольких типов offset. Каждая функция in_range должна быть введена в pg_amproc с amproclefttype, равным type1, и amprocrighttype, равным type2.

Существенная семантика функции in_range зависит от двух логических флаговых параметров. Она должна добавить или вычесть base и offset, затем сравнить val с результатом, следующим образом:

  • если !sub и !less, вернуть val >= (base + offset)

  • если !sub и less, вернуть val <= (base + offset)

  • если sub и !less, вернуть val >= (base - offset)

  • если sub и less, вернуть val <= (base - offset)

Перед этим функция должна проверить знак переменной offset: если он меньше нуля, вызвать ошибку ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE (22013) с текстом ошибки вида недопустимый размер предшествующего или следующего значения в оконной функции. (Это требуется стандартом SQL, хотя нестандартные семейства операторов, возможно, могут игнорировать это ограничение, так как, кажется, нет особой семантической необходимости в нем). Это требование делегируется функции in_range, чтобы основной код не должен был понимать, что означает меньше нуля для конкретного типа данных.

Дополнительное ожидание состоит в том, что функции in_range должны, если это возможно, избегать генерации ошибки, если base + offset или base - offset приведут к переполнению. Правильный результат сравнения может быть определен даже если это значение будет выходить за диапазон типа данных. Обратите внимание, что если тип данных включает понятия, такие как бесконечность или NaN, необходимо удостовериться, что результаты функции in_range согласуются с нормальным порядком сортировки семейства операторов.

Результаты функции in_range должны быть согласованы с порядком сортировки, установленным операторной семьей. А именно, при заданных значениях offset и sub, должно выполняться следующее:

  • Если in_range с less = true истинно для некоторых val1 и base, то оно должно быть истинно для каждого val2 <= val1 с тем же base.

  • Если in_range с less = true равно false для некоторых val1 и base, то оно должно быть false для каждого val2 >= val1 с тем же base.

  • Если in_range с less = true истинно для некоторого val и base1, то оно должно быть истинно для каждого base2 >= base1 с тем же val.

  • Если in_range с less = true равно false для некоторых val и base1, то оно должно быть false для каждого base2 <= base1 с тем же val.

Аналогичные операторы с инвертированными условиями выполняются, когда less = false.

Если заказываемый тип (type1) является сортируемым, соответствующий OID правила сортировки будет передан в функцию in_range с использованием стандартного механизма PG_GET_COLLATION().

in_range функции не обязаны обрабатывать NULL входные данные и обычно будут помечены как строгие.

equalimage

По желанию, семейство операторов btree может предоставлять опорные функции equalimage (равенство подразумевает равенство изображения), зарегистрированные под номером 4. Эти функции позволяют основному коду определить, когда безопасно применять оптимизацию дедупликации btree. В настоящее время функции equalimage вызываются только при создании или перестроении индекса.

Функция equalimage должна иметь сигнатуру

equalimage(opcintype oid) returns bool

Возвращаемое значение представляет собой статическую информацию о классе операторов и сортировке. Возвращение true указывает, что функция order для класса операторов гарантированно возвращает только 0 (аргументы равны), когда его аргументы A и B также взаимозаменяемы без потери семантической информации. Не регистрирование функции equalimage или возвращение false указывает на то, что это условие не может быть считано верным.

Аргумент opcintype является pg_type.oid типа данных, индексируемого классом операторов. Это удобство, позволяющее повторно использовать одну и ту же базовую функцию equalimage в разных классах операторов. Если opcintype является сортируемым типом данных, соответствующий OID правила сортировки будет передан функции equalimage с использованием стандартного механизма PG_GET_COLLATION().

С точки зрения класса операторов, возвращение true указывает на то, что дедупликация безопасна (или безопасна для правила сортировки, идентификатор которого был передан в функцию equalimage). Однако, основной код будет считать дедупликацию безопасной только для индекса, когда каждый индексируемый столбец использует класс операторов, который регистрирует функцию equalimage, и каждая функция действительно возвращает true при вызове.

Равенство изображений почти то же самое условие, что и простое побитовое равенство. Есть одно тонкое отличие: при индексировании типа данных varlena, представление на диске двух равных изображений может не быть побитово равным из-за несогласованного применения сжатия TOAST на входе. Формально, когда функция equalimage класса операторов возвращает true, можно считать, что функция datum_image_eq() на языке C всегда согласуется с функцией order класса операторов (при условии, что один и тот же OID правила сортировки передается и в функцию equalimage, и в функцию order).

Основной код фундаментально неспособен вывести какую-либо информацию о статусе равенство подразумевает равенство изображения класса операторов внутри семейства множественных типов данных, основываясь на деталях других классов операторов в том же семействе. Кроме того, не имеет смысла для семейства операторов зарегистрировать функцию equalimage для перекрестного типа, и попытка сделать это приведет к ошибке. Это связано с тем, что статус равенство подразумевает равенство изображения не зависит только от семантики сортировки/равенства, которая более или менее определена на уровне семейства операторов. Обычно, семантику, которую реализует конкретный тип данных, необходимо рассматривать отдельно.

Конвенция, которую следуют классы операторов, включенные в базовую дистрибуцию Tantor BE, заключается в регистрации стандартной обобщенной функции equalimage. Большинство классов операторов регистрируют btequalimage(), что указывает на безопасность дедупликации безусловно. Классы операторов для сравнимых типов данных, таких как text, регистрируют btvarstrequalimage(), что указывает на безопасность дедупликации с детерминированными правилами сортировки. Лучшей практикой для сторонних расширений является регистрация собственной пользовательской функции для сохранения контроля.

options

По желанию, семейство операторов B-дерева может предоставлять опорные функции options (опции, специфичные для класса операторов), зарегистрированные под номером 5. Эти функции определяют набор пользовательских параметров, которые управляют поведением класса операторов.

Опорная функция options должна иметь сигнатуру

options(relopts local_relopts *) returns void

Функции передается указатель на структуру local_relopts, которую необходимо заполнить набором специфических для класса операторов опций. Опции могут быть доступны из других вспомогательных функций с использованием макросов PG_HAS_OPCLASS_OPTIONS() и PG_GET_OPCLASS_OPTIONS().

В настоящее время ни один класс операторов B-Tree не имеет функции поддержки options. B-дерево не позволяет гибкого представления ключей, как это делают GiST, SP-GiST, GIN и BRIN. Поэтому, вероятно, options не имеет большого применения в текущем методе доступа к индексу B-дерева. Тем не менее, эта Опорная функция была добавлена в B-дерево для обеспечения единообразия и, вероятно, найдет применение во время дальнейшего развития B-дерева в Tantor BE.