65.3. Функции поддержки B-дерева#
65.3. Функции поддержки B-дерева
Согласно Таблица 36.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; вместо этого они расширяют семантику семейства операторов таким образом, чтобы оно могло поддерживать оконные предложения, содержащие типы границ рамки
RANGEoffsetPRECEDINGиRANGEoffsetFOLLOWING(см. Раздел 4.2.8). В основном, предоставляемая дополнительная информация определяет, как добавить или вычесть значениеoffsetтаким образом, чтобы оно было совместимо с упорядочиванием данных семейства.Функция
in_rangeдолжна иметь сигнатуруin_range(
valtype1,basetype1,offsettype2,subbool,lessbool) returns boolvalи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(
opcintypeoid) returns boolВозвращаемое значение представляет собой статическую информацию о классе операторов и сортировке. Возвращение
trueуказывает, что функцияorderдля класса операторов гарантированно возвращает только0(“аргументы равны”), когда его аргументыAиBтакже взаимозаменяемы без потери семантической информации. Не регистрирование функцииequalimageили возвращениеfalseуказывает на то, что это условие не может быть считано верным.Аргумент
opcintypeявляетсятипа данных, индексируемого классом операторов. Это удобство, позволяющее повторно использовать одну и ту же базовую функциюpg_type.oidequalimageв разных классах операторов. Еслиopcintypeявляется сортируемым типом данных, соответствующий OID правила сортировки будет передан функцииequalimageс использованием стандартного механизмаPG_GET_COLLATION().С точки зрения класса операторов, возвращение
trueуказывает на то, что дедупликация безопасна (или безопасна для правила сортировки, идентификатор которого был передан в функциюequalimage). Однако, основной код будет считать дедупликацию безопасной только для индекса, когда каждый индексируемый столбец использует класс операторов, который регистрирует функциюequalimage, и каждая функция действительно возвращаетtrueпри вызове.Равенство изображений почти то же самое условие, что и простое побитовое равенство. Есть одно тонкое отличие: при индексировании типа данных varlena, представление на диске двух равных изображений может не быть побитово равным из-за несогласованного применения сжатия TOAST на входе. Формально, когда функция
equalimageкласса операторов возвращаетtrue, можно считать, что функцияdatum_image_eq()на языке C всегда согласуется с функциейorderкласса операторов (при условии, что один и тот же OID правила сортировки передается и в функциюequalimage, и в функциюorder).Основной код фундаментально неспособен вывести какую-либо информацию о статусе “равенство подразумевает равенство изображения” класса операторов внутри семейства множественных типов данных, основываясь на деталях других классов операторов в том же семействе. Кроме того, не имеет смысла для семейства операторов зарегистрировать функцию
equalimageдля перекрестного типа, и попытка сделать это приведет к ошибке. Это связано с тем, что статус “равенство подразумевает равенство изображения” не зависит только от семантики сортировки/равенства, которая более или менее определена на уровне семейства операторов. Обычно, семантику, которую реализует конкретный тип данных, необходимо рассматривать отдельно.Конвенция, которую следуют классы операторов, включенные в базовую дистрибуцию Tantor SE, заключается в регистрации стандартной обобщенной функции
equalimage. Большинство классов операторов регистрируютbtequalimage(), что указывает на безопасность дедупликации безусловно. Классы операторов для сравнимых типов данных, таких какtext, регистрируютbtvarstrequalimage(), что указывает на безопасность дедупликации с детерминированными правилами сортировки. Лучшей практикой для сторонних расширений является регистрация собственной пользовательской функции для сохранения контроля.optionsПо желанию, семейство операторов B-дерева может предоставлять опорные функции
options(“опции, специфичные для класса операторов”), зарегистрированные под номером 5. Эти функции определяют набор пользовательских параметров, которые управляют поведением класса операторов.Опорная функция
optionsдолжна иметь сигнатуруoptions(
reloptslocal_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 SE.