64.2. Поведение классов операторов B-дерева#
64.2. Поведение классов операторов B-дерева #
Как показано в Таблица 35.2, класс операторов btree должен предоставлять пять операторов сравнения: <
, <=
, =
, >=
и >
. Можно было бы ожидать, что оператор <>
также будет частью класса операторов, но это не так, потому что в поиске по индексу использование оператора <>
в предложении WHERE практически никогда не будет полезным. (В некоторых случаях планировщик рассматривает оператор <>
как связанный с классом операторов btree, но он находит этот оператор через отрицательную связь оператора =
, а не через pg_amop
).
Когда несколько типов данных имеют почти идентичную семантику сортировки, их классы операторов могут быть сгруппированы в семейство операторов. Это выгодно, поскольку это позволяет планировщику делать выводы о сравнениях между различными типами данных. Каждый класс операторов внутри семейства должен содержать операторы одного типа (и связанные с ними вспомогательные функции) для своего типа входных данных, в то время как операторы и вспомогательные функции для сравнения разных типов данных в семействе могут быть "свободными". Рекомендуется включать полный набор операторов для сравнения разных типов данных в семействе, чтобы гарантировать, что планировщик может представить любые условия сравнения, которые он выводит из транзитивности.
Существуют некоторые основные предположения, которым должна удовлетворять семейство операторов btree:
Оператор
=
должен быть отношением эквивалентности; то есть, для всех ненулевых значенийA
,B
,C
типа данных:A
=
A
истинно (рефлексивное правило)если
A
=
B
, тоB
=
A
(симметричный закон)если
A
=
B
иB
=
C
, тоA
=
C
(транзитивный закон)
Оператор
<
должен быть строгим отношением порядка; то есть, для всех ненулевых значенийA
,B
,C
:A
<
A
is false (закон о нерефлексивности)если
A
<
B
иB
<
C
, тоA
<
C
(транзитивный закон)
Кроме того, упорядочение является полным; то есть, для всех ненулевых значений
A
,B
:ровно одно из
A
<
B
,A
=
B
иB
<
A
истинно (закон трех частей)
(Закон трихотомии оправдывает определение функции сравнения, конечно).
Другие три оператора определены с использованием операторов =
и <
очевидным образом и должны действовать согласованно с ними.
Для семейства операторов, поддерживающего несколько типов данных, вышеуказанные законы должны выполняться, когда A
, B
, C
берутся из любых типов данных в семействе. Транзитивные законы являются самыми сложными для обеспечения, так как в случае перекрестных типов они представляют утверждения о согласованности поведения двух или трех разных операторов. Например, не будет работать, если поместить float8
и numeric
в одно семейство операторов, по крайней мере, не с текущей семантикой, что значения numeric
преобразуются в float8
для сравнения с float8
. Из-за ограниченной точности float8
это означает, что существуют различные значения numeric
, которые будут сравниваться равными с одним и тем же значением float8
, и, следовательно, транзитивный закон не будет выполняться.
Другим требованием для семейства множественных типов данных является то, что любые неявные или бинарные приведения типов, определенные между типами данных, включенными в семейство операторов, не должны изменять связанный порядок сортировки.
Должно быть ясно, почему индекс btree требует соблюдения этих правил в пределах одного типа данных: без них нет упорядочивания для упорядочивания ключей. Кроме того, поиск по индексу с использованием ключа сравнения другого типа данных требует, чтобы сравнения вели себя разумно для двух типов данных. Расширения до трех или более типов данных внутри семейства не являются строго обязательными для самого механизма индекса btree, но планировщик полагается на них в целях оптимизации.