バージョンごとのドキュメント一覧

64.4. GINインデックス #

<title>GIN Indexes</title>

64.4.1. はじめに #

<title>Introduction</title>

<acronym>GIN</acronym> stands for Generalized Inverted Index. <acronym>GIN</acronym> is designed for handling cases where the items to be indexed are composite values, and the queries to be handled by the index need to search for element values that appear within the composite items. For example, the items could be documents, and the queries could be searches for documents containing specific words. GINとは汎用転置インデックス(Generalized Inverted Index)を表します。 GINは、以下のような状況を取り扱うために設計されました。(1)インデックス対象の項目が複合型である。(2)そのインデックスにより処理される問い合わせは、複合型の項目内に存在する要素の値を検索する必要がある。 例えば、項目は文書であり、問い合わせは特定の単語を含む文書の検索です。

We use the word <firstterm>item</firstterm> to refer to a composite value that is to be indexed, and the word <firstterm>key</firstterm> to refer to an element value. <acronym>GIN</acronym> always stores and searches for keys, not item values per se. ここでは、インデックス対象の複合型の値を項目と呼びます。また、要素値をキーと呼びます。 GINは項目の値自体ではなく、常にキーを格納し検索します。

A <acronym>GIN</acronym> index stores a set of (key, posting list) pairs, where a <firstterm>posting list</firstterm> is a set of row IDs in which the key occurs. The same row ID can appear in multiple posting lists, since an item can contain more than one key. Each key value is stored only once, so a <acronym>GIN</acronym> index is very compact for cases where the same key appears many times. GINインデックスは(キー、ポスティングリスト(posting list))の組み合わせの集合を格納します。 ここでポスティングリストはキーが発生した行IDの集合です。 項目は1つ以上のキーを含むことができますので、同じ行IDが複数のポスティングリストに現れることがあり得ます。 キー値はそれぞれ一度のみ格納されます。 このためGINインデックスの容量は、同じキーが何度も現れる場合に非常に小さくなります。

<acronym>GIN</acronym> is generalized in the sense that the <acronym>GIN</acronym> access method code does not need to know the specific operations that it accelerates. Instead, it uses custom strategies defined for particular data types. The strategy defines how keys are extracted from indexed items and query conditions, and how to determine whether a row that contains some of the key values in a query actually satisfies the query. GINインデックスは、GINアクセスメソッドが高速化対象の操作を把握する必要がないという意味で汎用化されています。 その代わり、特定のデータ型に対して定義された独自の戦略を使用します。 戦略は、インデックス付けされた項目と問い合わせ条件からキーを抽出する方法および問い合わせ内のいくつかのキー値を含む行が実際に問い合わせを満たすかどうかを決定する方法を定義します。

One advantage of <acronym>GIN</acronym> is that it allows the development of custom data types with the appropriate access methods, by an expert in the domain of the data type, rather than a database expert. This is much the same advantage as using <acronym>GiST</acronym>. GINの利点の1つは、データベース専門家ではなくデータ型の分野における専門家により、適切なアクセスメソッドを持つ独自のデータ型を開発できるという点です。 これはGiSTの使用とほぼ同じ利点です。

The <acronym>GIN</acronym> implementation in <productname>PostgreSQL</productname> is primarily maintained by Teodor Sigaev and Oleg Bartunov. There is more information about <acronym>GIN</acronym> on their <ulink url="http://www.sai.msu.su/~megera/wiki/Gin">website</ulink>. PostgreSQLにおけるGINの実装は、主にTeodor SigaevとOleg Bartunovにより保守されています。 GINに関する情報は彼らのwebサイトにより多く記載されています。

64.4.2. 組み込み演算子クラス #

<title>Built-in Operator Classes</title>

The core <productname>PostgreSQL</productname> distribution includes the <acronym>GIN</acronym> operator classes shown in <xref linkend="gin-builtin-opclasses-table"/>. (Some of the optional modules described in <xref linkend="contrib"/> provide additional <acronym>GIN</acronym> operator classes.) PostgreSQLのコア配布物は表 64.3に示すGIN演算子クラスを含みます。 (付録Fに記載された追加モジュールの中には追加のGIN演算子クラスを提供するものもあります。)

表64.3 組み込みGIN演算子クラス

<title>Built-in <acronym>GIN</acronym> Operator Classes</title>
名前インデックス可能な演算子
array_ops&& (anyarray,anyarray)
@> (anyarray,anyarray)
<@ (anyarray,anyarray)
= (anyarray,anyarray)
jsonb_ops@> (jsonb,jsonb)
@? (jsonb,jsonpath)
@@ (jsonb,jsonpath)
? (jsonb,text)
?| (jsonb,text[])
?& (jsonb,text[])
jsonb_path_ops@> (jsonb,jsonb)
@? (jsonb,jsonpath)
@@ (jsonb,jsonpath)
tsvector_ops@@ (tsvector,tsquery)

Of the two operator classes for type <type>jsonb</type>, <literal>jsonb_ops</literal> is the default. <literal>jsonb_path_ops</literal> supports fewer operators but offers better performance for those operators. See <xref linkend="json-indexing"/> for details. jsonb型の2つの演算子クラスのうち、jsonb_opsがデフォルトです。 jsonb_path_opsはより少数の演算子しかサポートしませんが、その演算子に対してはより良いパフォーマンスを提供します。 詳細は8.14.4を参照してください。

64.4.3. 拡張性 #

<title>Extensibility</title>

The <acronym>GIN</acronym> interface has a high level of abstraction, requiring the access method implementer only to implement the semantics of the data type being accessed. The <acronym>GIN</acronym> layer itself takes care of concurrency, logging and searching the tree structure. GINインタフェースは高度に抽象化されています。 アクセスメソッド実装者に要求されることは、アクセスするデータ型の意味を実装することだけです。 GIN層自体が同時実行性、ログ処理、ツリー構造の検索処理に関する面倒を見ます。

All it takes to get a <acronym>GIN</acronym> access method working is to implement a few user-defined methods, which define the behavior of keys in the tree and the relationships between keys, indexed items, and indexable queries. In short, <acronym>GIN</acronym> combines extensibility with generality, code reuse, and a clean interface. GINアクセスメソッドを動作させるために必要なことは、少数のユーザ定義関数を実装することだけです。 これは、ツリー内のキーの動作とキーとインデックス付けされる項目、インデックス可能な問い合わせ間の関係を定義します。 すなわち、GINは、一般化、コード再利用、整理されたインタフェースによる拡張性を組み合わせます。

There are two methods that an operator class for <acronym>GIN</acronym> must provide: GIN用の演算子クラスが提供しなければならないメソッドは2つあります。

Datum *extractValue(Datum itemValue, int32 *nkeys, bool **nullFlags)

Returns a palloc'd array of keys given an item to be indexed. The number of returned keys must be stored into <literal>*nkeys</literal>. If any of the keys can be null, also palloc an array of <literal>*nkeys</literal> <type>bool</type> fields, store its address at <literal>*nullFlags</literal>, and set these null flags as needed. <literal>*nullFlags</literal> can be left <symbol>NULL</symbol> (its initial value) if all keys are non-null. The return value can be <symbol>NULL</symbol> if the item contains no keys. インデックス対象値に与えられる、pallocで割り当てられたキーの配列を返します。 返されるキーの数は*nkeysに格納しなければなりません。 キーのいずれかがNULLになるかもしれない場合、*nkeys個のboolの配列をpallocで割り当てそのアドレスを*nullFlagsに格納し、必要に応じてNULLフラグを設定してください。 すべてのキーが非NULLであれば、*nullFlagsNULL(初期値)のままにすることができます。 項目がキーを含まない場合、戻り値はNULLになるかもしれません。

Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n, bool **pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode)

Returns a palloc'd array of keys given a value to be queried; that is, <literal>query</literal> is the value on the right-hand side of an indexable operator whose left-hand side is the indexed column. <literal>n</literal> is the strategy number of the operator within the operator class (see <xref linkend="xindex-strategies"/>). Often, <function>extractQuery</function> will need to consult <literal>n</literal> to determine the data type of <literal>query</literal> and the method it should use to extract key values. The number of returned keys must be stored into <literal>*nkeys</literal>. If any of the keys can be null, also palloc an array of <literal>*nkeys</literal> <type>bool</type> fields, store its address at <literal>*nullFlags</literal>, and set these null flags as needed. <literal>*nullFlags</literal> can be left <symbol>NULL</symbol> (its initial value) if all keys are non-null. The return value can be <symbol>NULL</symbol> if the <literal>query</literal> contains no keys. 問い合わせ対象の値に与えられる、pallocで割り当てられたキーの配列を返します。 つまり、queryはインデックス可能な演算子の右辺の値です。 この左辺はインデックス対象の列です。 nは演算子クラス内の演算子の戦略番号です(36.16.2を参照)。 extractQueryはしばしば、queryのデータ型とキー値を抽出するために使用しなければならないメソッドを決定するために、nを調べなければなりません。 返されるキーの数を*nkeysに格納しなければなりません。 キーのいずれかがNULLとなる可能性がある場合はまた、*nkeys個のboolの配列をpallocで割り当て、*nullFlagsにそのアドレスを格納し、必要に応じてNULLフラグを設定してください。 すべてのキーが非NULLならば*nullFlagsNULL(初期値)のままにしておくことができます。 queryがキーを含まない場合、戻り値をNULLにすることができます。

<literal>searchMode</literal> is an output argument that allows <function>extractQuery</function> to specify details about how the search will be done. If <literal>*searchMode</literal> is set to <literal>GIN_SEARCH_MODE_DEFAULT</literal> (which is the value it is initialized to before call), only items that match at least one of the returned keys are considered candidate matches. If <literal>*searchMode</literal> is set to <literal>GIN_SEARCH_MODE_INCLUDE_EMPTY</literal>, then in addition to items containing at least one matching key, items that contain no keys at all are considered candidate matches. (This mode is useful for implementing is-subset-of operators, for example.) If <literal>*searchMode</literal> is set to <literal>GIN_SEARCH_MODE_ALL</literal>, then all non-null items in the index are considered candidate matches, whether they match any of the returned keys or not. (This mode is much slower than the other two choices, since it requires scanning essentially the entire index, but it may be necessary to implement corner cases correctly. An operator that needs this mode in most cases is probably not a good candidate for a GIN operator class.) The symbols to use for setting this mode are defined in <filename>access/gin.h</filename>. searchModeは出力引数です。 これによりextractQueryは検索がどのように行われるかの詳細を指定することができます。 *searchModeGIN_SEARCH_MODE_DEFAULT(呼び出し前にこの値に初期化されます。)に設定された場合、返されるキーの少なくとも1つに一致する項目が合致候補とみなされます。 *searchModeGIN_SEARCH_MODE_INCLUDE_EMPTYに設定された場合、少なくとも1つの一致するキーを含む項目に加え、キーをまったく含まない項目が合致候補とみなされます。 (このモードは例えば何のサブセットかを求める演算子を実装する際に有用です。) *searchModeGIN_SEARCH_MODE_ALLに設定された場合、返されるキーのいずれかに一致するかどうかは関係なく、インデックス内の非NULLの項目すべてが合致候補とみなされます。 (このモードは、基本的にインデックス全体のスキャン処理が必要ですので、他の2つの選択肢と比べてかなり低速になります。 しかし境界条件を正確に実装するためにこれが必要になるかもしれません。 おそらく、このモードを必要とする演算子はほとんどの場合、GIN演算子クラス向けに優れた候補ではありません。) このモードを設定するために使用する記号はaccess/gin.hで定義されています。

<literal>pmatch</literal> is an output argument for use when partial match is supported. To use it, <function>extractQuery</function> must allocate an array of <literal>*nkeys</literal> <type>bool</type>s and store its address at <literal>*pmatch</literal>. Each element of the array should be set to true if the corresponding key requires partial match, false if not. If <literal>*pmatch</literal> is set to <symbol>NULL</symbol> then GIN assumes partial match is not required. The variable is initialized to <symbol>NULL</symbol> before call, so this argument can simply be ignored by operator classes that do not support partial match. pmatchは部分一致が提供されている場合に使用する出力引数です。 使用するには、extractQuery*nkeys個のboolの配列を割り当て、そのアドレスを*pmatchに格納しなければなりません。 関連するキーが部分一致を必要とするとき、それぞれの配列要素は真に、そうでなければ偽に設定されなければなりません。 *pmatchNULLに設定されている場合、GINは部分一致が必要ないと想定します。 呼び出し前に変数はNULLに初期化されますので、この引数は部分一致が提供されていない演算子クラスでは、単に無視できます。

<literal>extra_data</literal> is an output argument that allows <function>extractQuery</function> to pass additional data to the <function>consistent</function> and <function>comparePartial</function> methods. To use it, <function>extractQuery</function> must allocate an array of <literal>*nkeys</literal> pointers and store its address at <literal>*extra_data</literal>, then store whatever it wants to into the individual pointers. The variable is initialized to <symbol>NULL</symbol> before call, so this argument can simply be ignored by operator classes that do not require extra data. If <literal>*extra_data</literal> is set, the whole array is passed to the <function>consistent</function> method, and the appropriate element to the <function>comparePartial</function> method. extra_dataは、extractQueryconsistentcomparePartialメソッドに追加データを渡すことができるようにする出力引数です。 使用するには、extractQuery*nkeysポインタの配列を割り当て、そのアドレスを*extra_dataに格納し、そして望まれるものは何でも個別のポインタに格納しなければなりません。 変数は呼び出し前にNULLに初期化されますので、追加データを必要としない演算子クラスでこの引数は単に無視できます。 もし*extra_dataが設定されれば、配列全部がconsistentメソッドに、適切な要素がcomparePartialメソッドに渡されます。

An operator class must also provide a function to check if an indexed item matches the query. It comes in two flavors, a Boolean <function>consistent</function> function, and a ternary <function>triConsistent</function> function. <function>triConsistent</function> covers the functionality of both, so providing <function>triConsistent</function> alone is sufficient. However, if the Boolean variant is significantly cheaper to calculate, it can be advantageous to provide both. If only the Boolean variant is provided, some optimizations that depend on refuting index items before fetching all the keys are disabled. 演算子クラスは、インデックス付けされた項目が問い合わせに一致するか確認する関数も提供しなければなりません。 それは2つの方法で行なわれます。 2値のconsistent関数と3値のtriConsistent関数です。 triConsistentが両方の機能を含みますので、triConsistentだけを提供しても十分です。 しかし、2値の亜種を計算するのが著しく安価であれば、両方を提供することは役に立つかもしれません。 2値の亜種のみが提供されていれば、すべてのキーを取得する前にインデックス項目が一致しないことを確認することに基づく最適化の中には無効となるものもあります。

bool consistent(bool check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], bool *recheck, Datum queryKeys[], bool nullFlags[])

Returns true if an indexed item satisfies the query operator with strategy number <literal>n</literal> (or might satisfy it, if the recheck indication is returned). This function does not have direct access to the indexed item's value, since <acronym>GIN</acronym> does not store items explicitly. Rather, what is available is knowledge about which key values extracted from the query appear in a given indexed item. The <literal>check</literal> array has length <literal>nkeys</literal>, which is the same as the number of keys previously returned by <function>extractQuery</function> for this <literal>query</literal> datum. Each element of the <literal>check</literal> array is true if the indexed item contains the corresponding query key, i.e., if (check[i] == true) the i-th key of the <function>extractQuery</function> result array is present in the indexed item. The original <literal>query</literal> datum is passed in case the <function>consistent</function> method needs to consult it, and so are the <literal>queryKeys[]</literal> and <literal>nullFlags[]</literal> arrays previously returned by <function>extractQuery</function>. <literal>extra_data</literal> is the extra-data array returned by <function>extractQuery</function>, or <symbol>NULL</symbol> if none. インデックス付けられた項目が戦略番号nを持つ問い合わせ演算子を満たす(または、recheck印が返されたときはたぶん満たすかもしれない)場合に真を返します。 GINは項目を明示的に格納しませんので、この関数はインデックス付けされた項目の値に直接アクセスすることができません。 どちらかというと、この問い合わせから取り出される指定された問い合わせで現れるキー値に関する知識が利用できるものです。 check配列は長さnkeysであり、このqueryデータに対して事前に行われたextractQueryが返したキーの数と同じです。 インデックス対象の項目が対応する問い合わせキーを持つ場合、check配列の各要素は真です。 つまり、(check[i] == true)の場合、extractQueryの結果配列のi番目のキーがインデックス対象項目内に存在します。 元のqueryデータは、consistentメソッドがそれを調査する必要がある場合に、渡されます。 このためqueryKeys[]およびnullFlags[]は事前にextractQueryによって返されます。 extra_dataextractQueryにより返された追加データ配列で、ない場合はNULLです。

When <function>extractQuery</function> returns a null key in <literal>queryKeys[]</literal>, the corresponding <literal>check[]</literal> element is true if the indexed item contains a null key; that is, the semantics of <literal>check[]</literal> are like <literal>IS NOT DISTINCT FROM</literal>. The <function>consistent</function> function can examine the corresponding <literal>nullFlags[]</literal> element if it needs to tell the difference between a regular value match and a null match. extractQueryqueryKeys[]内でNULLキーを返す時、インデックス対象項目がNULLキーを含む場合は対応するcheck[]要素は真です、 つまり、check[]の意味はIS NOT DISTINCT FROMのようなものです。 consistent関数は、通常の値の合致とNULL合致との違いを通知する必要がある場合、対応するnullFlags[]要素を検査することができます。

On success, <literal>*recheck</literal> should be set to true if the heap tuple needs to be rechecked against the query operator, or false if the index test is exact. That is, a false return value guarantees that the heap tuple does not match the query; a true return value with <literal>*recheck</literal> set to false guarantees that the heap tuple does match the query; and a true return value with <literal>*recheck</literal> set to true means that the heap tuple might match the query, so it needs to be fetched and rechecked by evaluating the query operator directly against the originally indexed item. 成功の場合、*recheckは、問い合わせ演算子に対してヒープタプルを再検査する必要があればtrue、インデックス検査が的確であればfalseに設定する必要があります。 つまり、falseの戻り値はヒープタプルが問い合わせに一致しないことを保証します。 trueの戻り値で、*recheckがfalseに設定された場合はヒープタプルが問い合わせに一致することを保証します。 trueの戻り値で、*recheckがtrueに設定された場合はヒープタプルが問い合わせに一致する可能性があることを意味します。 したがって、それを取り出し、元のインデックス付けされた項目を直接問い合わせ演算子で評価することで再検査する必要があることを意味します。

GinTernaryValue triConsistent(GinTernaryValue check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], Datum queryKeys[], bool nullFlags[])

<function>triConsistent</function> is similar to <function>consistent</function>, but instead of Booleans in the <literal>check</literal> vector, there are three possible values for each key: <literal>GIN_TRUE</literal>, <literal>GIN_FALSE</literal> and <literal>GIN_MAYBE</literal>. <literal>GIN_FALSE</literal> and <literal>GIN_TRUE</literal> have the same meaning as regular Boolean values, while <literal>GIN_MAYBE</literal> means that the presence of that key is not known. When <literal>GIN_MAYBE</literal> values are present, the function should only return <literal>GIN_TRUE</literal> if the item certainly matches whether or not the index item contains the corresponding query keys. Likewise, the function must return <literal>GIN_FALSE</literal> only if the item certainly does not match, whether or not it contains the <literal>GIN_MAYBE</literal> keys. If the result depends on the <literal>GIN_MAYBE</literal> entries, i.e., the match cannot be confirmed or refuted based on the known query keys, the function must return <literal>GIN_MAYBE</literal>. triConsistentconsistentと似ていますが、checkベクターの論理値の代わりに、各キーに対して3つの可能な値があります。GIN_TRUEGIN_FALSEGIN_MAYBEです。 GIN_FALSEGIN_TRUEは通常の論理値と同じ意味であり、GIN_MAYBEはそのキーの存在が分からないこと意味します。 GIN_MAYBE値があれば、インデックス項目が対応する問い合わせキーを含むかどうかに関わらず、項目が確実に一致する場合にのみ関数はGIN_TRUEを返すべきです。 同様に、GIN_MAYBEを含むかどうかに関わらず項目が確実に一致しない場合にのみ関数はGIN_FALSEを返さなければなりません。 結果がGIN_MAYBE項目に依存する、すなわち、分かっている問い合わせキーに基づいて、一致することもしないことも確認できない場合には、関数はGIN_MAYBEを返さなければなりません。

When there are no <literal>GIN_MAYBE</literal> values in the <literal>check</literal> vector, a <literal>GIN_MAYBE</literal> return value is the equivalent of setting the <literal>recheck</literal> flag in the Boolean <function>consistent</function> function. checkベクターにGIN_MAYBE値がなければ、GIN_MAYBE戻り値は論理値のconsistent関数でrecheckフラグを設定することと同じです。

In addition, GIN must have a way to sort the key values stored in the index. The operator class can define the sort ordering by specifying a comparison method: さらに、GINにはインデックス内に格納されているキー値をソートする方法がなければなりません。 演算子クラスは比較メソッドを指定することでソート順を定義できます。

int compare(Datum a, Datum b)

Compares two keys (not indexed items!) and returns an integer less than zero, zero, or greater than zero, indicating whether the first key is less than, equal to, or greater than the second. Null keys are never passed to this function. キー(インデックス付けされる項目ではありません)を比較し、0より小さい、0、または0より大きい整数を返します。 それぞれ、最初のキーが2番目のキーより、小さい、等しい、または大きいことを示します。 NULLキーがこの関数に渡されることはありません。

Alternatively, if the operator class does not provide a <function>compare</function> method, GIN will look up the default btree operator class for the index key data type, and use its comparison function. It is recommended to specify the comparison function in a GIN operator class that is meant for just one data type, as looking up the btree operator class costs a few cycles. However, polymorphic GIN operator classes (such as <literal>array_ops</literal>) typically cannot specify a single comparison function. あるいは、演算子クラスがcompareメソッドを提供しない場合には、GINはそのインデックスキーデータ型に対するデフォルトのbtree演算子クラスを探し、その比較関数を使います。 btree演算子クラスを探すのは処理に多少掛かりますので、GIN演算子クラスの中で比較関数を指定することを勧めます。それはただ一つのデータ型に対するものであることを意味します。 しかし、(array_opsのような)多様GIN演算子クラスでは、通常は単一の比較関数を指定できません。

An operator class for <acronym>GIN</acronym> can optionally supply the following methods: 省略可能ですが、GINに対する演算子クラスは以下のメソッドを提供します。

int comparePartial(Datum partial_key, Datum key, StrategyNumber n, Pointer extra_data)

Compare a partial-match query key to an index key. Returns an integer whose sign indicates the result: less than zero means the index key does not match the query, but the index scan should continue; zero means that the index key does match the query; greater than zero indicates that the index scan should stop because no more matches are possible. The strategy number <literal>n</literal> of the operator that generated the partial match query is provided, in case its semantics are needed to determine when to end the scan. Also, <literal>extra_data</literal> is the corresponding element of the extra-data array made by <function>extractQuery</function>, or <symbol>NULL</symbol> if none. Null keys are never passed to this function. 問い合わせキーとインデックスキーの部分一致を比較します。 符号が結果を示す整数が返ります。 ゼロ未満はインデックスキーは問い合わせに一致しないが、インデックススキャンを続けるべきであることを示します。 ゼロはインデックスキーが問い合わせに一致することを示します。 ゼロより大きな値はこれ以上の一致はありえないためインデックススキャンを停止すべきであることを示します。 スキャンをいつ停止するかを決めるためにセマンティクスが必要とされる場合、部分一致問い合わせを生成した演算子の戦略番号nが提供されます。 またextra_dataextractQueryで作成される追加データ配列の対応する要素、もしなければNULLです。 NULLキーがこの関数に渡されることはありません。

void options(local_relopts *relopts)

Defines a set of user-visible parameters that control operator class behavior. 演算子クラスの振舞いを制御するユーザに可視のパラメータの集合を定義します。

The <function>options</function> function is passed a pointer to a <structname>local_relopts</structname> struct, which needs to be filled with a set of operator class specific options. The options can be accessed from other support functions using the <literal>PG_HAS_OPCLASS_OPTIONS()</literal> and <literal>PG_GET_OPCLASS_OPTIONS()</literal> macros. options関数にはlocal_relopts構造体へのポインタが渡されますが、構造体を演算子クラスに固有のオプションの集合で満たすことが必要です。 オプションはマクロPG_HAS_OPCLASS_OPTIONS()PG_GET_OPCLASS_OPTIONS()を使って他のサポート関数からアクセスできます。

Since both key extraction of indexed values and representation of the key in <acronym>GIN</acronym> are flexible, they may depend on user-specified parameters. インデックス付けされた値からのキーの抽出にもGINでのキーの表現にも柔軟性がありますので、ユーザに固有のパラメータに依存するかもしれません。

To support <quote>partial match</quote> queries, an operator class must provide the <function>comparePartial</function> method, and its <function>extractQuery</function> method must set the <literal>pmatch</literal> parameter when a partial-match query is encountered. See <xref linkend="gin-partial-match"/> for details. 部分一致問い合わせをサポートするためには、演算子クラスはcomparePartialメソッドを提供しなければなりません。 またそのextractQueryは、部分一致問い合わせであった時にpmatchパラメータを設定しなければなりません。 詳細については64.4.4.2を参照してください。

The actual data types of the various <literal>Datum</literal> values mentioned above vary depending on the operator class. The item values passed to <function>extractValue</function> are always of the operator class's input type, and all key values must be of the class's <literal>STORAGE</literal> type. The type of the <literal>query</literal> argument passed to <function>extractQuery</function>, <function>consistent</function> and <function>triConsistent</function> is whatever is the right-hand input type of the class member operator identified by the strategy number. This need not be the same as the indexed type, so long as key values of the correct type can be extracted from it. However, it is recommended that the SQL declarations of these three support functions use the opclass's indexed data type for the <literal>query</literal> argument, even though the actual type might be something else depending on the operator. 上記の各種Datum値の実データ型は、演算子クラスに依存して変動します。 extractValueに渡される項目値は常に演算子クラスの入力型であり、キー値はすべてそのクラスのSTORAGE型でなければなりません。 extractQueryconsistentおよびtriConsistentに渡されるquery引数の型は、戦略番号によって識別されるクラスのメンバ演算子の右辺入力型です。 正しい型のキー値がそこから抽出できる限り、これはインデックス付けされた型と同じである必要はありません。 しかしながら、この3つのサポート関数のSQL宣言では、実際の型は演算子に依存して何か他のものであるとしても、query引数には演算子クラスのインデックス付けされたデータ型を使うことを勧めます。

64.4.4. 実装 #

<title>Implementation</title>

Internally, a <acronym>GIN</acronym> index contains a B-tree index constructed over keys, where each key is an element of one or more indexed items (a member of an array, for example) and where each tuple in a leaf page contains either a pointer to a B-tree of heap pointers (a <quote>posting tree</quote>), or a simple list of heap pointers (a <quote>posting list</quote>) when the list is small enough to fit into a single index tuple along with the key value. <xref linkend="gin-internals-figure"/> illustrates these components of a GIN index. GINインデックスはキー全体に対するB-treeインデックスを持ちます。 そのキーはそれぞれインデックス対象項目の要素(例えば配列のメンバ)であり、リーフページ内のタプルはそれぞれ、ヒープポインタのB-treeへのポインタ(ポスティングツリー(posting tree))か、もしリストがキー値と共に単一インデックスタプルに合う程度十分に小さければヒープポインタの単純なリスト(ポスティングリスト(posting list))です。 図 64.1にGINインデックスのこれらのコンポーネントを示します。

As of <productname>PostgreSQL</productname> 9.1, null key values can be included in the index. Also, placeholder nulls are included in the index for indexed items that are null or contain no keys according to <function>extractValue</function>. This allows searches that should find empty items to do so. PostgreSQL 9.1からNULLキー値をインデックスに含められるようになりました。 またプレースホルダとしてのNULLが、NULLまたはextractValueによるとキーを含まないインデックス対象項目についてインデックスに含められます。 これにより空の項目を見つけ出すための検索を行うことができます。

Multicolumn <acronym>GIN</acronym> indexes are implemented by building a single B-tree over composite values (column number, key value). The key values for different columns can be of different types. 複数列に対するGINインデックスは複合型の値(列番号、キー値)全体について単一のB-treeを構築することで実装されます。 異なる列に対するキー値は別の型となるかもしれません。

図64.1 GINの内部

<title>GIN Internals</title>

64.4.4.1. GIN高速更新手法 #

<title>GIN Fast Update Technique</title>

Updating a <acronym>GIN</acronym> index tends to be slow because of the intrinsic nature of inverted indexes: inserting or updating one heap row can cause many inserts into the index (one for each key extracted from the indexed item). <acronym>GIN</acronym> is capable of postponing much of this work by inserting new tuples into a temporary, unsorted list of pending entries. When the table is vacuumed or autoanalyzed, or when <function>gin_clean_pending_list</function> function is called, or if the pending list becomes larger than <xref linkend="guc-gin-pending-list-limit"/>, the entries are moved to the main <acronym>GIN</acronym> data structure using the same bulk insert techniques used during initial index creation. This greatly improves <acronym>GIN</acronym> index update speed, even counting the additional vacuum overhead. Moreover the overhead work can be done by a background process instead of in foreground query processing. 1つのヒープ行の挿入または更新によりインデックスへの挿入が多く発生するという、転置インデックスの本質的な性質のためGINインデックスの更新は低速になりがちです。 (各キー用のヒープ行はインデックス付けされた項目から取り出されます。) GINは、新しいタプルを一時的なソートされていない、待機中の項目リストに挿入することにより、この作業の大部分を遅延させることができるようになりました。 テーブルがバキュームまたは自動解析された時、gin_clean_pending_list関数が呼ばれたとき、または、待機中のリスト(pending list)がgin_pending_list_limitよりも大きくなった時、初期のインデックス作成の際に使用されるものと同様の一括挿入技法を使用して、項目は主GINデータ構造に移動されます。 これは、バキュームのオーバーヘッドが追加されることを考慮したとしても、GINインデックスの更新速度を著しく向上します。 さらに、フォアグラウンドの問い合わせ処理ではなくバックグラウンド処理でこのオーバーヘッド作業を実行することができます。

The main disadvantage of this approach is that searches must scan the list of pending entries in addition to searching the regular index, and so a large list of pending entries will slow searches significantly. Another disadvantage is that, while most updates are fast, an update that causes the pending list to become <quote>too large</quote> will incur an immediate cleanup cycle and thus be much slower than other updates. Proper use of autovacuum can minimize both of these problems. この手法の大きな欠点は、検索時に通常のインデックス検索に加え待機中の項目リストのスキャンを行わなければならない点です。 このため、待機中の項目リストが大きくなると検索が顕著に遅くなります。 他の欠点は、ほとんどの更新は高速ですが、待機中の項目リストが大きくなりすぎるきっかけとなった更新は即時の整理処理を招くことになり、他の更新に比べ大きく低速になります。 自動バキュームを適切に使用することで、これらの両方の問題を最小化することができます。

If consistent response time is more important than update speed, use of pending entries can be disabled by turning off the <literal>fastupdate</literal> storage parameter for a <acronym>GIN</acronym> index. See <xref linkend="sql-createindex"/> for details. 一貫した応答時間が更新速度より重要な場合、GINインデックスに対するfastupdate格納パラメータを無効にすることにより、待機中の項目の使用を無効にすることができます。 詳細はCREATE INDEXを参照してください。

64.4.4.2. 部分一致アルゴリズム #

<title>Partial Match Algorithm</title>

GIN can support <quote>partial match</quote> queries, in which the query does not determine an exact match for one or more keys, but the possible matches fall within a reasonably narrow range of key values (within the key sorting order determined by the <function>compare</function> support method). The <function>extractQuery</function> method, instead of returning a key value to be matched exactly, returns a key value that is the lower bound of the range to be searched, and sets the <literal>pmatch</literal> flag true. The key range is then scanned using the <function>comparePartial</function> method. <function>comparePartial</function> must return zero for a matching index key, less than zero for a non-match that is still within the range to be searched, or greater than zero if the index key is past the range that could match. GINは部分一致問い合わせをサポートすることができます。 この問い合わせは1つ以上のキーに正確に一致することは決定しませんが、キー値の合理的に狭い(compareサポートメソッドで決まるキーのソート順に従った)範囲内に一致する可能性があります。 extractQueryは、正確に一致したキー値を返す代わりに、検索される範囲の下限となるキー値を返し、pmatchフラグを真に設定します。 そしてキー範囲をcomparePartialメソッドを使用して検索します。 comparePartialは一致するインデックスキーではゼロを、一致しないが検索すべき範囲内にあればゼロ未満の値を、インデックスキーが一致可能な範囲を超えた場合はゼロより大きな値を返さなければなりません。

64.4.5. GINの小技 #

<title>GIN Tips and Tricks</title>
作成と挿入

Insertion into a <acronym>GIN</acronym> index can be slow due to the likelihood of many keys being inserted for each item. So, for bulk insertions into a table it is advisable to drop the GIN index and recreate it after finishing bulk insertion. 各項目に対して多くのキーが挿入される可能性がありますので、GINインデックスへの挿入は低速になることがあります。 ですので、テーブルに対する大量の挿入では、GINインデックスを削除し、大量の挿入が終わった段階で再作成することを勧めます。

When <literal>fastupdate</literal> is enabled for <acronym>GIN</acronym> (see <xref linkend="gin-fast-update"/> for details), the penalty is less than when it is not. But for very large updates it may still be best to drop and recreate the index. GINではfastupdateが有効である場合、このペナルティはそうでない場合よりも少なくなります。 (64.4.4.1を参照してください。) しかし非常に大規模な更新では、インデックスの削除と再作成がまだ最善かもしれません。

maintenance_work_mem

Build time for a <acronym>GIN</acronym> index is very sensitive to the <varname>maintenance_work_mem</varname> setting; it doesn't pay to skimp on work memory during index creation. GINインデックスの構築時間はmaintenance_work_memの設定に非常に敏感です。 インデックス作成時に作業メモリをより少なく使用しようとはしません。

gin_pending_list_limit

During a series of insertions into an existing <acronym>GIN</acronym> index that has <literal>fastupdate</literal> enabled, the system will clean up the pending-entry list whenever the list grows larger than <varname>gin_pending_list_limit</varname>. To avoid fluctuations in observed response time, it's desirable to have pending-list cleanup occur in the background (i.e., via autovacuum). Foreground cleanup operations can be avoided by increasing <varname>gin_pending_list_limit</varname> or making autovacuum more aggressive. However, enlarging the threshold of the cleanup operation means that if a foreground cleanup does occur, it will take even longer. fastupdateが有効な既存のGINインデックスに対して挿入を繰り返す間、待機中の項目リストがgin_pending_list_limitより大きくなると、システムはこのリストを整理します。 観測される応答時間の変動を防ぐためには、待機中リストの整理をバックグラウンド(すなわち自動バキューム)で起きるようにすることが望まれます。 フォアグラウンドでの整理処理は、gin_pending_list_limitを大きくすること、もしくは自動バキュームをより積極的に行うことで防ぐことができます。 しかし、整理処理の閾値を大きくすることは、フォアグラウンドで整理処理が発生した時により長い時間がかかることを意味します。

<varname>gin_pending_list_limit</varname> can be overridden for individual GIN indexes by changing storage parameters, which allows each GIN index to have its own cleanup threshold. For example, it's possible to increase the threshold only for the GIN index which can be updated heavily, and decrease it otherwise. gin_pending_list_limitは格納パラメータを変更することで個々のGINインデックスに対して上書きでき、それにより各GINインデックスが自身の整理閾値を持てます。 例えば、頻繁に更新される可能性のあるGINインデックスの閾値のみを増やして、それ以外は減らすことができます。

gin_fuzzy_search_limit

The primary goal of developing <acronym>GIN</acronym> indexes was to create support for highly scalable full-text search in <productname>PostgreSQL</productname>, and there are often situations when a full-text search returns a very large set of results. Moreover, this often happens when the query contains very frequent words, so that the large result set is not even useful. Since reading many tuples from the disk and sorting them could take a lot of time, this is unacceptable for production. (Note that the index search itself is very fast.) GINインデックス開発の主な目的は、スケーラビリティが高い全文検索のサポートをPostgreSQLで作成することでした。 全文検索の結果は非常に大規模な結果セットを返します。 さらに、問い合わせが非常に高頻度な単語を持つ場合、こうした状況はよく発生しますが、大規模な結果セットは有用ですらありません。 ディスクから大量のタプルを読み、ソートすることは長い時間がかかりますので、実運用レベルでは受け入れられません。 (インデックス検索自体は非常に高速であることに注意してください。)

To facilitate controlled execution of such queries, <acronym>GIN</acronym> has a configurable soft upper limit on the number of rows returned: the <varname>gin_fuzzy_search_limit</varname> configuration parameter. It is set to 0 (meaning no limit) by default. If a non-zero limit is set, then the returned set is a subset of the whole result set, chosen at random. こうした問い合わせの実行を簡単に制御できるように、GINは返される行数に対して設定可能なソフト上限、gin_fuzzy_search_limit設定パラメータを持ちます。 これはデフォルトでは0です(無制限を意味します)。 非0の制限が設定された場合、返されるセットは結果セット全体からランダムに選んだサブセットになります。

<quote>Soft</quote> means that the actual number of returned results could differ somewhat from the specified limit, depending on the query and the quality of the system's random number generator. ソフトは、問い合わせとシステムの乱数ジェネレータの品質に依存して、返される結果の実際の数が指定した上限より多少異なることを意味します。

From experience, values in the thousands (e.g., 5000 &mdash; 20000) work well. 経験上、数千(例えば5000から20000)の値がうまく動作します。

64.4.6. 制限事項 #

<title>Limitations</title>

<acronym>GIN</acronym> assumes that indexable operators are strict. This means that <function>extractValue</function> will not be called at all on a null item value (instead, a placeholder index entry is created automatically), and <function>extractQuery</function> will not be called on a null query value either (instead, the query is presumed to be unsatisfiable). Note however that null key values contained within a non-null composite item or query value are supported. GINは、インデックス付け可能な演算子は厳密であると仮定します。 これはextractValueはNULL項目値についてはまったく呼び出されない(代わりにインデックス項目のプレースホルダが自動的に生成される)こと、および、extractQueryは問い合わせの値がNULLの場合に呼び出されない(代わりに問い合わせは不一致であるとみなされる)ことを意味します。 しかし非NULLの複合型項目内または問い合わせ値内のNULLキー値はサポートされます。

64.4.7. 例 #

<title>Examples</title>

The core <productname>PostgreSQL</productname> distribution includes the <acronym>GIN</acronym> operator classes previously shown in <xref linkend="gin-builtin-opclasses-table"/>. The following <filename>contrib</filename> modules also contain <acronym>GIN</acronym> operator classes: PostgreSQLのコア配布物は以前表 64.3に示したGIN演算子クラスを含みます。 以下のcontribモジュールにもGIN演算子クラスが含まれています。

btree_gin
<para>B-tree equivalent functionality for several data types</para>

さまざまなデータ型に対するB-tree等価の機能

hstore
<para>Module for storing (key, value) pairs</para>

(キー、値)の組み合わせを格納するモジュール

intarray
<para>Enhanced support for <type>int[]</type></para>

int[]に対する高度サポート

pg_trgm
<para>Text similarity using trigram matching</para>

トライグラム一致を使用したテキスト類似度