From 3785f7eee3d98bc0a7ac2576aac9c0be974217d4 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 6 Feb 2018 13:52:27 -0500 Subject: [PATCH] Doc: move info for btree opclass implementors into main documentation. Up to now, useful info for writing a new btree opclass has been buried in the backend's nbtree/README file. Let's move it into the SGML docs, in preparation for extending it with info about "in_range" functions in the upcoming window RANGE patch. To do this, I chose to create a new chapter for btree indexes in Part VII (Internals), parallel to the chapters that exist for the newer index AMs. This is a pretty short chapter as-is. At some point somebody might care to flesh it out with more detail about btree internals, but that is beyond the scope of my ambition for today. Discussion: https://postgr.es/m/23141.1517874668@sss.pgh.pa.us --- doc/src/sgml/btree.sgml | 267 +++++++++++++++++++++++++++++++ doc/src/sgml/filelist.sgml | 1 + doc/src/sgml/postgres.sgml | 1 + doc/src/sgml/xindex.sgml | 15 +- src/backend/access/nbtree/README | 53 ------ 5 files changed, 276 insertions(+), 61 deletions(-) create mode 100644 doc/src/sgml/btree.sgml diff --git a/doc/src/sgml/btree.sgml b/doc/src/sgml/btree.sgml new file mode 100644 index 0000000000..9f39edc742 --- /dev/null +++ b/doc/src/sgml/btree.sgml @@ -0,0 +1,267 @@ + + + +B-Tree Indexes + + + index + B-Tree + + + + Introduction + + + PostgreSQL includes an implementation of the + standard btree (multi-way binary tree) index data + structure. Any data type that can be sorted into a well-defined linear + order can be indexed by a btree index. The only limitation is that an + index entry cannot exceed approximately one-third of a page (after TOAST + compression, if applicable). + + + + Because each btree operator class imposes a sort order on its data type, + btree operator classes (or, really, operator families) have come to be + used as PostgreSQL's general representation + and understanding of sorting semantics. Therefore, they've acquired + some features that go beyond what would be needed just to support btree + indexes, and parts of the system that are quite distant from the + btree AM make use of them. + + + + + + Behavior of B-Tree Operator Classes + + + As shown in , a btree operator + class must provide five comparison operators, + <, + <=, + =, + >= and + >. + One might expect that <> should also be part of + the operator class, but it is not, because it would almost never be + useful to use a <> WHERE clause in an index + search. (For some purposes, the planner treats <> + as associated with a btree operator class; but it finds that operator via + the = operator's negator link, rather than + from pg_amop.) + + + + When several data types share near-identical sorting semantics, their + operator classes can be grouped into an operator family. Doing so is + advantageous because it allows the planner to make deductions about + cross-type comparisons. Each operator class within the family should + contain the single-type operators (and associated support functions) + for its input data type, while cross-type comparison operators and + support functions are loose in the family. It is + recommendable that a complete set of cross-type operators be included + in the family, thus ensuring that the planner can represent any + comparison conditions that it deduces from transitivity. + + + + There are some basic assumptions that a btree operator family must + satisfy: + + + + + + An = operator must be an equivalence relation; that + is, for all non-null values A, + B, C of the + data type: + + + + + A = + A is true + (reflexive law) + + + + + if A = + B, + then B = + A + (symmetric law) + + + + + if A = + B and B + = C, + then A = + C + (transitive law) + + + + + + + + + A < operator must be a strong ordering relation; + that is, for all non-null values A, + B, C: + + + + + A < + A is false + (irreflexive law) + + + + + if A < + B + and B < + C, + then A < + C + (transitive law) + + + + + + + + + Furthermore, the ordering is total; that is, for all non-null + values A, B: + + + + + exactly one of A < + B, A + = B, and + B < + A is true + (trichotomy law) + + + + + (The trichotomy law justifies the definition of the comparison support + function, of course.) + + + + + + The other three operators are defined in terms of = + and < in the obvious way, and must act consistently + with them. + + + + For an operator family supporting multiple data types, the above laws must + hold when A, B, + C are taken from any data types in the family. + The transitive laws are the trickiest to ensure, as in cross-type + situations they represent statements that the behaviors of two or three + different operators are consistent. + As an example, it would not work to put float8 + and numeric into the same operator family, at least not with + the current semantics that numeric values are converted + to float8 for comparison to a float8. Because + of the limited accuracy of float8, this means there are + distinct numeric values that will compare equal to the + same float8 value, and thus the transitive law would fail. + + + + Another requirement for a multiple-data-type family is that any implicit + or binary-coercion casts that are defined between data types included in + the operator family must not change the associated sort ordering. + + + + It should be fairly clear why a btree index requires these laws to hold + within a single data type: without them there is no ordering to arrange + the keys with. Also, index searches using a comparison key of a + different data type require comparisons to behave sanely across two + data types. The extensions to three or more data types within a family + are not strictly required by the btree index mechanism itself, but the + planner relies on them for optimization purposes. + + + + + + B-Tree Support Functions + + + As shown in , btree defines + one required and one optional support function. + + + + For each combination of data types that a btree operator family provides + comparison operators for, it must provide a comparison support function, + registered in pg_amproc with support function + number 1 and + amproclefttype/amprocrighttype + equal to the left and right data types for the comparison (i.e., the + same data types that the matching operators are registered with + in pg_amop). + The comparison function must take two non-null values + A and B and + return an int32 value that + is < 0, 0, + or > 0 + when A < + B, A + = B, + or A > + B, respectively. The function must not + return INT_MIN for the A + < B case, + since the value may be negated before being tested for sign. A null + result is disallowed, too. + See src/backend/access/nbtree/nbtcompare.c for + examples. + + + + If the compared values are of a collatable data type, the appropriate + collation OID will be passed to the comparison support function, using + the standard PG_GET_COLLATION() mechanism. + + + + Optionally, a btree operator family may provide sort + support function(s), registered under support function number + 2. These functions allow implementing comparisons for sorting purposes + in a more efficient way than naively calling the comparison support + function. The APIs involved in this are defined in + src/include/utils/sortsupport.h. + + + + + + Implementation + + + An introduction to the btree index implementation can be found in + src/backend/access/nbtree/README. + + + + + diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index a72c50eadb..732b8ab7d0 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -83,6 +83,7 @@ + diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index 041afdbd86..054347b17d 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -252,6 +252,7 @@ &geqo; &indexam; &generic-wal; + &btree; &gist; &spgist; &gin; diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml index 81c0cdc4f8..e40131473f 100644 --- a/doc/src/sgml/xindex.sgml +++ b/doc/src/sgml/xindex.sgml @@ -35,7 +35,7 @@ PostgreSQL, but all index methods are described in pg_am. It is possible to add a new index access method by writing the necessary code and - then creating a row in pg_am — but that is + then creating an entry in pg_am — but that is beyond the scope of this chapter (see ). @@ -404,6 +404,8 @@ B-trees require a single support function, and allow a second one to be supplied at the operator class author's option, as shown in . + The requirements for these support functions are explained further in + . @@ -426,8 +428,8 @@ - Return the addresses of C-callable sort support function(s), - as documented in utils/sortsupport.h (optional) + Return the addresses of C-callable sort support function(s) + (optional) 2 @@ -1056,11 +1058,8 @@ ALTER OPERATOR FAMILY integer_ops USING btree ADD In a B-tree operator family, all the operators in the family must sort - compatibly, meaning that the transitive laws hold across all the data types - supported by the family: if A = B and B = C, then A = C, - and if A < B and B < C, then A < C. Moreover, implicit - or binary coercion casts between types represented in the operator family - must not change the associated sort ordering. For each + compatibly, as is specified in detail in . + For each operator in the family there must be a support function having the same two input data types as the operator. It is recommended that a family be complete, i.e., for each combination of data types, all operators are diff --git a/src/backend/access/nbtree/README b/src/backend/access/nbtree/README index a3f11da8d5..34f78b2f50 100644 --- a/src/backend/access/nbtree/README +++ b/src/backend/access/nbtree/README @@ -623,56 +623,3 @@ routines must treat it accordingly. The actual key stored in the item is irrelevant, and need not be stored at all. This arrangement corresponds to the fact that an L&Y non-leaf page has one more pointer than key. - -Notes to Operator Class Implementors ------------------------------------- - -With this implementation, we require each supported combination of -datatypes to supply us with a comparison procedure via pg_amproc. -This procedure must take two nonnull values A and B and return an int32 < 0, -0, or > 0 if A < B, A = B, or A > B, respectively. The procedure must -not return INT_MIN for "A < B", since the value may be negated before -being tested for sign. A null result is disallowed, too. See nbtcompare.c -for examples. - -There are some basic assumptions that a btree operator family must satisfy: - -An = operator must be an equivalence relation; that is, for all non-null -values A,B,C of the datatype: - - A = A is true reflexive law - if A = B, then B = A symmetric law - if A = B and B = C, then A = C transitive law - -A < operator must be a strong ordering relation; that is, for all non-null -values A,B,C: - - A < A is false irreflexive law - if A < B and B < C, then A < C transitive law - -Furthermore, the ordering is total; that is, for all non-null values A,B: - - exactly one of A < B, A = B, and B < A is true trichotomy law - -(The trichotomy law justifies the definition of the comparison support -procedure, of course.) - -The other three operators are defined in terms of these two in the obvious way, -and must act consistently with them. - -For an operator family supporting multiple datatypes, the above laws must hold -when A,B,C are taken from any datatypes in the family. The transitive laws -are the trickiest to ensure, as in cross-type situations they represent -statements that the behaviors of two or three different operators are -consistent. As an example, it would not work to put float8 and numeric into -an opfamily, at least not with the current semantics that numerics are -converted to float8 for comparison to a float8. Because of the limited -accuracy of float8, this means there are distinct numeric values that will -compare equal to the same float8 value, and thus the transitive law fails. - -It should be fairly clear why a btree index requires these laws to hold within -a single datatype: without them there is no ordering to arrange the keys with. -Also, index searches using a key of a different datatype require comparisons -to behave sanely across two datatypes. The extensions to three or more -datatypes within a family are not strictly required by the btree index -mechanism itself, but the planner relies on them for optimization purposes.