]> granicus.if.org Git - postgresql/blob - doc/src/sgml/gist.sgml
Remove dead NULL-pointer checks in GiST code.
[postgresql] / doc / src / sgml / gist.sgml
1 <!-- doc/src/sgml/gist.sgml -->
2
3 <chapter id="GiST">
4 <title>GiST Indexes</title>
5
6    <indexterm>
7     <primary>index</primary>
8     <secondary>GiST</secondary>
9    </indexterm>
10
11 <sect1 id="gist-intro">
12  <title>Introduction</title>
13
14  <para>
15    <acronym>GiST</acronym> stands for Generalized Search Tree.  It is a
16    balanced, tree-structured access method, that acts as a base template in
17    which to implement arbitrary indexing schemes. B-trees, R-trees and many
18    other indexing schemes can be implemented in <acronym>GiST</acronym>.
19  </para>
20
21  <para>
22   One advantage of <acronym>GiST</acronym> is that it allows the development
23   of custom data types with the appropriate access methods, by
24   an expert in the domain of the data type, rather than a database expert.
25  </para>
26
27   <para>
28     Some of the information here is derived from the University of California
29     at Berkeley's GiST Indexing Project
30     <ulink url="http://gist.cs.berkeley.edu/">web site</ulink> and
31     Marcel Kornacker's thesis,
32     <ulink url="http://www.sai.msu.su/~megera/postgres/gist/papers/concurrency/access-methods-for-next-generation.pdf.gz">
33     Access Methods for Next-Generation Database Systems</ulink>.
34     The <acronym>GiST</acronym>
35     implementation in <productname>PostgreSQL</productname> is primarily
36     maintained by Teodor Sigaev and Oleg Bartunov, and there is more
37     information on their
38     <ulink url="http://www.sai.msu.su/~megera/postgres/gist/">web site</ulink>.
39   </para>
40
41 </sect1>
42
43 <sect1 id="gist-builtin-opclasses">
44  <title>Built-in Operator Classes</title>
45
46  <para>
47   The core <productname>PostgreSQL</> distribution
48   includes the <acronym>GiST</acronym> operator classes shown in
49   <xref linkend="gist-builtin-opclasses-table">.
50   (Some of the optional modules described in <xref linkend="contrib">
51   provide additional <acronym>GiST</acronym> operator classes.)
52  </para>
53
54   <table id="gist-builtin-opclasses-table">
55    <title>Built-in <acronym>GiST</acronym> Operator Classes</title>
56    <tgroup cols="4">
57     <thead>
58      <row>
59       <entry>Name</entry>
60       <entry>Indexed Data Type</entry>
61       <entry>Indexable Operators</entry>
62       <entry>Ordering Operators</entry>
63      </row>
64     </thead>
65     <tbody>
66      <row>
67       <entry><literal>box_ops</></entry>
68       <entry><type>box</></entry>
69       <entry>
70        <literal>&amp;&amp;</>
71        <literal>&amp;&gt;</>
72        <literal>&amp;&lt;</>
73        <literal>&amp;&lt;|</>
74        <literal>&gt;&gt;</>
75        <literal>&lt;&lt;</>
76        <literal>&lt;&lt;|</>
77        <literal>&lt;@</>
78        <literal>@&gt;</>
79        <literal>@</>
80        <literal>|&amp;&gt;</>
81        <literal>|&gt;&gt;</>
82        <literal>~</>
83        <literal>~=</>
84       </entry>
85       <entry>
86       </entry>
87      </row>
88      <row>
89       <entry><literal>circle_ops</></entry>
90       <entry><type>circle</></entry>
91       <entry>
92        <literal>&amp;&amp;</>
93        <literal>&amp;&gt;</>
94        <literal>&amp;&lt;</>
95        <literal>&amp;&lt;|</>
96        <literal>&gt;&gt;</>
97        <literal>&lt;&lt;</>
98        <literal>&lt;&lt;|</>
99        <literal>&lt;@</>
100        <literal>@&gt;</>
101        <literal>@</>
102        <literal>|&amp;&gt;</>
103        <literal>|&gt;&gt;</>
104        <literal>~</>
105        <literal>~=</>
106       </entry>
107       <entry>
108       </entry>
109      </row>
110      <row>
111       <entry><literal>inet_ops</></entry>
112       <entry><type>inet</>, <type>cidr</></entry>
113       <entry>
114        <literal>&amp;&amp;</>
115        <literal>&gt;&gt;</>
116        <literal>&gt;&gt;=</>
117        <literal>&gt;</>
118        <literal>&gt;=</>
119        <literal>&lt;&gt;</>
120        <literal>&lt;&lt;</>
121        <literal>&lt;&lt;=</>
122        <literal>&lt;</>
123        <literal>&lt;=</>
124        <literal>=</>
125       </entry>
126       <entry>
127       </entry>
128      </row>
129      <row>
130       <entry><literal>point_ops</></entry>
131       <entry><type>point</></entry>
132       <entry>
133        <literal>&gt;&gt;</>
134        <literal>&gt;^</>
135        <literal>&lt;&lt;</>
136        <literal>&lt;@</>
137        <literal>&lt;@</>
138        <literal>&lt;@</>
139        <literal>&lt;^</>
140        <literal>~=</>
141       </entry>
142       <entry>
143        <literal>&lt;-&gt;</>
144       </entry>
145      </row>
146      <row>
147       <entry><literal>poly_ops</></entry>
148       <entry><type>polygon</></entry>
149       <entry>
150        <literal>&amp;&amp;</>
151        <literal>&amp;&gt;</>
152        <literal>&amp;&lt;</>
153        <literal>&amp;&lt;|</>
154        <literal>&gt;&gt;</>
155        <literal>&lt;&lt;</>
156        <literal>&lt;&lt;|</>
157        <literal>&lt;@</>
158        <literal>@&gt;</>
159        <literal>@</>
160        <literal>|&amp;&gt;</>
161        <literal>|&gt;&gt;</>
162        <literal>~</>
163        <literal>~=</>
164       </entry>
165       <entry>
166       </entry>
167      </row>
168      <row>
169       <entry><literal>range_ops</></entry>
170       <entry>any range type</entry>
171       <entry>
172        <literal>&amp;&amp;</>
173        <literal>&amp;&gt;</>
174        <literal>&amp;&lt;</>
175        <literal>&gt;&gt;</>
176        <literal>&lt;&lt;</>
177        <literal>&lt;@</>
178        <literal>-|-</>
179        <literal>=</>
180        <literal>@&gt;</>
181        <literal>@&gt;</>
182       </entry>
183       <entry>
184       </entry>
185      </row>
186      <row>
187       <entry><literal>tsquery_ops</></entry>
188       <entry><type>tsquery</></entry>
189       <entry>
190        <literal>&lt;@</>
191        <literal>@&gt;</>
192       </entry>
193       <entry>
194       </entry>
195      </row>
196      <row>
197       <entry><literal>tsvector_ops</></entry>
198       <entry><type>tsvector</></entry>
199       <entry>
200        <literal>@@</>
201       </entry>
202       <entry>
203       </entry>
204      </row>
205     </tbody>
206    </tgroup>
207   </table>
208
209  <para>
210   For historical reasons, the <literal>inet_ops</> operator class is
211   not the default class for types <type>inet</> and <type>cidr</>.
212   To use it, mention the class name in <command>CREATE INDEX</>,
213   for example
214 <programlisting>
215 CREATE INDEX ON my_table USING gist (my_inet_column inet_ops);
216 </programlisting>
217  </para>
218
219 </sect1>
220
221 <sect1 id="gist-extensibility">
222  <title>Extensibility</title>
223
224  <para>
225    Traditionally, implementing a new index access method meant a lot of
226    difficult work.  It was necessary to understand the inner workings of the
227    database, such as the lock manager and Write-Ahead Log.  The
228    <acronym>GiST</acronym> interface has a high level of abstraction,
229    requiring the access method implementer only to implement the semantics of
230    the data type being accessed.  The <acronym>GiST</acronym> layer itself
231    takes care of concurrency, logging and searching the tree structure.
232  </para>
233
234  <para>
235    This extensibility should not be confused with the extensibility of the
236    other standard search trees in terms of the data they can handle.  For
237    example, <productname>PostgreSQL</productname> supports extensible B-trees
238    and hash indexes. That means that you can use
239    <productname>PostgreSQL</productname> to build a B-tree or hash over any
240    data type you want. But B-trees only support range predicates
241    (<literal>&lt;</literal>, <literal>=</literal>, <literal>&gt;</literal>),
242    and hash indexes only support equality queries.
243  </para>
244
245  <para>
246    So if you index, say, an image collection with a
247    <productname>PostgreSQL</productname> B-tree, you can only issue queries
248    such as <quote>is imagex equal to imagey</quote>, <quote>is imagex less
249    than imagey</quote> and <quote>is imagex greater than imagey</quote>.
250    Depending on how you define <quote>equals</quote>, <quote>less than</quote>
251    and <quote>greater than</quote> in this context, this could be useful.
252    However, by using a <acronym>GiST</acronym> based index, you could create
253    ways to ask domain-specific questions, perhaps <quote>find all images of
254    horses</quote> or <quote>find all over-exposed images</quote>.
255  </para>
256
257  <para>
258    All it takes to get a <acronym>GiST</acronym> access method up and running
259    is to implement several user-defined methods, which define the behavior of
260    keys in the tree. Of course these methods have to be pretty fancy to
261    support fancy queries, but for all the standard queries (B-trees,
262    R-trees, etc.) they're relatively straightforward. In short,
263    <acronym>GiST</acronym> combines extensibility along with generality, code
264    reuse, and a clean interface.
265   </para>
266
267  <para>
268    There are seven methods that an index operator class for
269    <acronym>GiST</acronym> must provide, and an eighth that is optional.
270    Correctness of the index is ensured
271    by proper implementation of the <function>same</>, <function>consistent</>
272    and <function>union</> methods, while efficiency (size and speed) of the
273    index will depend on the <function>penalty</> and <function>picksplit</>
274    methods.
275    The remaining two basic methods are <function>compress</> and
276    <function>decompress</>, which allow an index to have internal tree data of
277    a different type than the data it indexes. The leaves are to be of the
278    indexed data type, while the other tree nodes can be of any C struct (but
279    you still have to follow <productname>PostgreSQL</> data type rules here,
280    see about <literal>varlena</> for variable sized data). If the tree's
281    internal data type exists at the SQL level, the <literal>STORAGE</> option
282    of the <command>CREATE OPERATOR CLASS</> command can be used.
283    The optional eighth method is <function>distance</>, which is needed
284    if the operator class wishes to support ordered scans (nearest-neighbor
285    searches).
286  </para>
287
288  <variablelist>
289     <varlistentry>
290      <term><function>consistent</></term>
291      <listitem>
292       <para>
293        Given an index entry <literal>p</> and a query value <literal>q</>,
294        this function determines whether the index entry is
295        <quote>consistent</> with the query; that is, could the predicate
296        <quote><replaceable>indexed_column</>
297        <replaceable>indexable_operator</> <literal>q</></quote> be true for
298        any row represented by the index entry?  For a leaf index entry this is
299        equivalent to testing the indexable condition, while for an internal
300        tree node this determines whether it is necessary to scan the subtree
301        of the index represented by the tree node.  When the result is
302        <literal>true</>, a <literal>recheck</> flag must also be returned.
303        This indicates whether the predicate is certainly true or only possibly
304        true.  If <literal>recheck</> = <literal>false</> then the index has
305        tested the predicate condition exactly, whereas if <literal>recheck</>
306        = <literal>true</> the row is only a candidate match.  In that case the
307        system will automatically evaluate the
308        <replaceable>indexable_operator</> against the actual row value to see
309        if it is really a match.  This convention allows
310        <acronym>GiST</acronym> to support both lossless and lossy index
311        structures.
312       </para>
313
314       <para>
315         The <acronym>SQL</> declaration of the function must look like this:
316
317 <programlisting>
318 CREATE OR REPLACE FUNCTION my_consistent(internal, data_type, smallint, oid, internal)
319 RETURNS bool
320 AS 'MODULE_PATHNAME'
321 LANGUAGE C STRICT;
322 </programlisting>
323
324         And the matching code in the C module could then follow this skeleton:
325
326 <programlisting>
327 Datum       my_consistent(PG_FUNCTION_ARGS);
328 PG_FUNCTION_INFO_V1(my_consistent);
329
330 Datum
331 my_consistent(PG_FUNCTION_ARGS)
332 {
333     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
334     data_type  *query = PG_GETARG_DATA_TYPE_P(1);
335     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
336     /* Oid subtype = PG_GETARG_OID(3); */
337     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
338     data_type  *key = DatumGetDataType(entry-&gt;key);
339     bool        retval;
340
341     /*
342      * determine return value as a function of strategy, key and query.
343      *
344      * Use GIST_LEAF(entry) to know where you're called in the index tree,
345      * which comes handy when supporting the = operator for example (you could
346      * check for non empty union() in non-leaf nodes and equality in leaf
347      * nodes).
348      */
349
350     *recheck = true;        /* or false if check is exact */
351
352     PG_RETURN_BOOL(retval);
353 }
354 </programlisting>
355
356        Here, <varname>key</> is an element in the index and <varname>query</>
357        the value being looked up in the index. The <literal>StrategyNumber</>
358        parameter indicates which operator of your operator class is being
359        applied &mdash; it matches one of the operator numbers in the
360        <command>CREATE OPERATOR CLASS</> command.  Depending on what operators
361        you have included in the class, the data type of <varname>query</> could
362        vary with the operator, but the above skeleton assumes it doesn't.
363       </para>
364
365      </listitem>
366     </varlistentry>
367
368     <varlistentry>
369      <term><function>union</></term>
370      <listitem>
371       <para>
372        This method consolidates information in the tree.  Given a set of
373        entries, this function generates a new index entry that represents
374        all the given entries.
375       </para>
376
377       <para>
378         The <acronym>SQL</> declaration of the function must look like this:
379
380 <programlisting>
381 CREATE OR REPLACE FUNCTION my_union(internal, internal)
382 RETURNS internal
383 AS 'MODULE_PATHNAME'
384 LANGUAGE C STRICT;
385 </programlisting>
386
387         And the matching code in the C module could then follow this skeleton:
388
389 <programlisting>
390 Datum       my_union(PG_FUNCTION_ARGS);
391 PG_FUNCTION_INFO_V1(my_union);
392
393 Datum
394 my_union(PG_FUNCTION_ARGS)
395 {
396     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
397     GISTENTRY  *ent = entryvec-&gt;vector;
398     data_type  *out,
399                *tmp,
400                *old;
401     int         numranges,
402                 i = 0;
403
404     numranges = entryvec-&gt;n;
405     tmp = DatumGetDataType(ent[0].key);
406     out = tmp;
407
408     if (numranges == 1)
409     {
410         out = data_type_deep_copy(tmp);
411
412         PG_RETURN_DATA_TYPE_P(out);
413     }
414
415     for (i = 1; i &lt; numranges; i++)
416     {
417         old = out;
418         tmp = DatumGetDataType(ent[i].key);
419         out = my_union_implementation(out, tmp);
420     }
421
422     PG_RETURN_DATA_TYPE_P(out);
423 }
424 </programlisting>
425       </para>
426
427       <para>
428         As you can see, in this skeleton we're dealing with a data type
429         where <literal>union(X, Y, Z) = union(union(X, Y), Z)</>. It's easy
430         enough to support data types where this is not the case, by
431         implementing the proper union algorithm in this
432         <acronym>GiST</> support method.
433       </para>
434
435       <para>
436         The <function>union</> implementation function should return a
437         pointer to newly <function>palloc()</>ed memory. You can't just
438         return whatever the input is.
439       </para>
440      </listitem>
441     </varlistentry>
442
443     <varlistentry>
444      <term><function>compress</></term>
445      <listitem>
446       <para>
447        Converts the data item into a format suitable for physical storage in
448        an index page.
449       </para>
450
451       <para>
452         The <acronym>SQL</> declaration of the function must look like this:
453
454 <programlisting>
455 CREATE OR REPLACE FUNCTION my_compress(internal)
456 RETURNS internal
457 AS 'MODULE_PATHNAME'
458 LANGUAGE C STRICT;
459 </programlisting>
460
461         And the matching code in the C module could then follow this skeleton:
462
463 <programlisting>
464 Datum       my_compress(PG_FUNCTION_ARGS);
465 PG_FUNCTION_INFO_V1(my_compress);
466
467 Datum
468 my_compress(PG_FUNCTION_ARGS)
469 {
470     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
471     GISTENTRY  *retval;
472
473     if (entry-&gt;leafkey)
474     {
475         /* replace entry-&gt;key with a compressed version */
476         compressed_data_type *compressed_data = palloc(sizeof(compressed_data_type));
477
478         /* fill *compressed_data from entry-&gt;key ... */
479
480         retval = palloc(sizeof(GISTENTRY));
481         gistentryinit(*retval, PointerGetDatum(compressed_data),
482                       entry-&gt;rel, entry-&gt;page, entry-&gt;offset, FALSE);
483     }
484     else
485     {
486         /* typically we needn't do anything with non-leaf entries */
487         retval = entry;
488     }
489
490     PG_RETURN_POINTER(retval);
491 }
492 </programlisting>
493       </para>
494
495       <para>
496        You have to adapt <replaceable>compressed_data_type</> to the specific
497        type you're converting to in order to compress your leaf nodes, of
498        course.
499       </para>
500      </listitem>
501     </varlistentry>
502
503     <varlistentry>
504      <term><function>decompress</></term>
505      <listitem>
506       <para>
507        The reverse of the <function>compress</function> method.  Converts the
508        index representation of the data item into a format that can be
509        manipulated by the database.
510       </para>
511
512       <para>
513         The <acronym>SQL</> declaration of the function must look like this:
514
515 <programlisting>
516 CREATE OR REPLACE FUNCTION my_decompress(internal)
517 RETURNS internal
518 AS 'MODULE_PATHNAME'
519 LANGUAGE C STRICT;
520 </programlisting>
521
522         And the matching code in the C module could then follow this skeleton:
523
524 <programlisting>
525 Datum       my_decompress(PG_FUNCTION_ARGS);
526 PG_FUNCTION_INFO_V1(my_decompress);
527
528 Datum
529 my_decompress(PG_FUNCTION_ARGS)
530 {
531     PG_RETURN_POINTER(PG_GETARG_POINTER(0));
532 }
533 </programlisting>
534
535         The above skeleton is suitable for the case where no decompression
536         is needed.
537       </para>
538      </listitem>
539     </varlistentry>
540
541     <varlistentry>
542      <term><function>penalty</></term>
543      <listitem>
544       <para>
545        Returns a value indicating the <quote>cost</quote> of inserting the new
546        entry into a particular branch of the tree.  Items will be inserted
547        down the path of least <function>penalty</function> in the tree.
548        Values returned by <function>penalty</function> should be non-negative.
549        If a negative value is returned, it will be treated as zero.
550       </para>
551
552       <para>
553         The <acronym>SQL</> declaration of the function must look like this:
554
555 <programlisting>
556 CREATE OR REPLACE FUNCTION my_penalty(internal, internal, internal)
557 RETURNS internal
558 AS 'MODULE_PATHNAME'
559 LANGUAGE C STRICT;  -- in some cases penalty functions need not be strict
560 </programlisting>
561
562         And the matching code in the C module could then follow this skeleton:
563
564 <programlisting>
565 Datum       my_penalty(PG_FUNCTION_ARGS);
566 PG_FUNCTION_INFO_V1(my_penalty);
567
568 Datum
569 my_penalty(PG_FUNCTION_ARGS)
570 {
571     GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
572     GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
573     float      *penalty = (float *) PG_GETARG_POINTER(2);
574     data_type  *orig = DatumGetDataType(origentry-&gt;key);
575     data_type  *new = DatumGetDataType(newentry-&gt;key);
576
577     *penalty = my_penalty_implementation(orig, new);
578     PG_RETURN_POINTER(penalty);
579 }
580 </programlisting>
581       </para>
582
583       <para>
584         The <function>penalty</> function is crucial to good performance of
585         the index. It'll get used at insertion time to determine which branch
586         to follow when choosing where to add the new entry in the tree. At
587         query time, the more balanced the index, the quicker the lookup.
588       </para>
589      </listitem>
590     </varlistentry>
591
592     <varlistentry>
593      <term><function>picksplit</></term>
594      <listitem>
595       <para>
596        When an index page split is necessary, this function decides which
597        entries on the page are to stay on the old page, and which are to move
598        to the new page.
599       </para>
600
601       <para>
602         The <acronym>SQL</> declaration of the function must look like this:
603
604 <programlisting>
605 CREATE OR REPLACE FUNCTION my_picksplit(internal, internal)
606 RETURNS internal
607 AS 'MODULE_PATHNAME'
608 LANGUAGE C STRICT;
609 </programlisting>
610
611         And the matching code in the C module could then follow this skeleton:
612
613 <programlisting>
614 Datum       my_picksplit(PG_FUNCTION_ARGS);
615 PG_FUNCTION_INFO_V1(my_picksplit);
616
617 Datum
618 my_picksplit(PG_FUNCTION_ARGS)
619 {
620     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
621     OffsetNumber maxoff = entryvec-&gt;n - 1;
622     GISTENTRY  *ent = entryvec-&gt;vector;
623     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
624     int         i,
625                 nbytes;
626     OffsetNumber *left,
627                *right;
628     data_type  *tmp_union;
629     data_type  *unionL;
630     data_type  *unionR;
631     GISTENTRY **raw_entryvec;
632
633     maxoff = entryvec-&gt;n - 1;
634     nbytes = (maxoff + 1) * sizeof(OffsetNumber);
635
636     v-&gt;spl_left = (OffsetNumber *) palloc(nbytes);
637     left = v-&gt;spl_left;
638     v-&gt;spl_nleft = 0;
639
640     v-&gt;spl_right = (OffsetNumber *) palloc(nbytes);
641     right = v-&gt;spl_right;
642     v-&gt;spl_nright = 0;
643
644     unionL = NULL;
645     unionR = NULL;
646
647     /* Initialize the raw entry vector. */
648     raw_entryvec = (GISTENTRY **) malloc(entryvec-&gt;n * sizeof(void *));
649     for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
650         raw_entryvec[i] = &amp;(entryvec-&gt;vector[i]);
651
652     for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
653     {
654         int         real_index = raw_entryvec[i] - entryvec-&gt;vector;
655
656         tmp_union = DatumGetDataType(entryvec-&gt;vector[real_index].key);
657         Assert(tmp_union != NULL);
658
659         /*
660          * Choose where to put the index entries and update unionL and unionR
661          * accordingly. Append the entries to either v_spl_left or
662          * v_spl_right, and care about the counters.
663          */
664
665         if (my_choice_is_left(unionL, curl, unionR, curr))
666         {
667             if (unionL == NULL)
668                 unionL = tmp_union;
669             else
670                 unionL = my_union_implementation(unionL, tmp_union);
671
672             *left = real_index;
673             ++left;
674             ++(v-&gt;spl_nleft);
675         }
676         else
677         {
678             /*
679              * Same on the right
680              */
681         }
682     }
683
684     v-&gt;spl_ldatum = DataTypeGetDatum(unionL);
685     v-&gt;spl_rdatum = DataTypeGetDatum(unionR);
686     PG_RETURN_POINTER(v);
687 }
688 </programlisting>
689       </para>
690
691       <para>
692         Like <function>penalty</>, the <function>picksplit</> function
693         is crucial to good performance of the index.  Designing suitable
694         <function>penalty</> and <function>picksplit</> implementations
695         is where the challenge of implementing well-performing
696         <acronym>GiST</> indexes lies.
697       </para>
698      </listitem>
699     </varlistentry>
700
701     <varlistentry>
702      <term><function>same</></term>
703      <listitem>
704       <para>
705        Returns true if two index entries are identical, false otherwise.
706       </para>
707
708       <para>
709         The <acronym>SQL</> declaration of the function must look like this:
710
711 <programlisting>
712 CREATE OR REPLACE FUNCTION my_same(internal, internal, internal)
713 RETURNS internal
714 AS 'MODULE_PATHNAME'
715 LANGUAGE C STRICT;
716 </programlisting>
717
718         And the matching code in the C module could then follow this skeleton:
719
720 <programlisting>
721 Datum       my_same(PG_FUNCTION_ARGS);
722 PG_FUNCTION_INFO_V1(my_same);
723
724 Datum
725 my_same(PG_FUNCTION_ARGS)
726 {
727     prefix_range *v1 = PG_GETARG_PREFIX_RANGE_P(0);
728     prefix_range *v2 = PG_GETARG_PREFIX_RANGE_P(1);
729     bool       *result = (bool *) PG_GETARG_POINTER(2);
730
731     *result = my_eq(v1, v2);
732     PG_RETURN_POINTER(result);
733 }
734 </programlisting>
735
736         For historical reasons, the <function>same</> function doesn't
737         just return a Boolean result; instead it has to store the flag
738         at the location indicated by the third argument.
739       </para>
740      </listitem>
741     </varlistentry>
742
743     <varlistentry>
744      <term><function>distance</></term>
745      <listitem>
746       <para>
747        Given an index entry <literal>p</> and a query value <literal>q</>,
748        this function determines the index entry's
749        <quote>distance</> from the query value.  This function must be
750        supplied if the operator class contains any ordering operators.
751        A query using the ordering operator will be implemented by returning
752        index entries with the smallest <quote>distance</> values first,
753        so the results must be consistent with the operator's semantics.
754        For a leaf index entry the result just represents the distance to
755        the index entry; for an internal tree node, the result must be the
756        smallest distance that any child entry could have.
757       </para>
758
759       <para>
760         The <acronym>SQL</> declaration of the function must look like this:
761
762 <programlisting>
763 CREATE OR REPLACE FUNCTION my_distance(internal, data_type, smallint, oid)
764 RETURNS float8
765 AS 'MODULE_PATHNAME'
766 LANGUAGE C STRICT;
767 </programlisting>
768
769         And the matching code in the C module could then follow this skeleton:
770
771 <programlisting>
772 Datum       my_distance(PG_FUNCTION_ARGS);
773 PG_FUNCTION_INFO_V1(my_distance);
774
775 Datum
776 my_distance(PG_FUNCTION_ARGS)
777 {
778     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
779     data_type  *query = PG_GETARG_DATA_TYPE_P(1);
780     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
781     /* Oid subtype = PG_GETARG_OID(3); */
782     data_type  *key = DatumGetDataType(entry-&gt;key);
783     double      retval;
784
785     /*
786      * determine return value as a function of strategy, key and query.
787      */
788
789     PG_RETURN_FLOAT8(retval);
790 }
791 </programlisting>
792
793        The arguments to the <function>distance</> function are identical to
794        the arguments of the <function>consistent</> function, except that no
795        recheck flag is used.  The distance to a leaf index entry must always
796        be determined exactly, since there is no way to re-order the tuples
797        once they are returned.  Some approximation is allowed when determining
798        the distance to an internal tree node, so long as the result is never
799        greater than any child's actual distance.  Thus, for example, distance
800        to a bounding box is usually sufficient in geometric applications.  The
801        result value can be any finite <type>float8</> value.  (Infinity and
802        minus infinity are used internally to handle cases such as nulls, so it
803        is not recommended that <function>distance</> functions return these
804        values.)
805       </para>
806
807      </listitem>
808     </varlistentry>
809
810   </variablelist>
811
812   <para>
813    All the GiST support methods are normally called in short-lived memory
814    contexts; that is, <varname>CurrentMemoryContext</> will get reset after
815    each tuple is processed.  It is therefore not very important to worry about
816    pfree'ing everything you palloc.  However, in some cases it's useful for a
817    support method to cache data across repeated calls.  To do that, allocate
818    the longer-lived data in <literal>fcinfo-&gt;flinfo-&gt;fn_mcxt</>, and
819    keep a pointer to it in <literal>fcinfo-&gt;flinfo-&gt;fn_extra</>.  Such
820    data will survive for the life of the index operation (e.g., a single GiST
821    index scan, index build, or index tuple insertion).  Be careful to pfree
822    the previous value when replacing a <literal>fn_extra</> value, or the leak
823    will accumulate for the duration of the operation.
824   </para>
825
826 </sect1>
827
828 <sect1 id="gist-implementation">
829  <title>Implementation</title>
830
831  <sect2 id="gist-buffering-build">
832   <title>GiST buffering build</title>
833   <para>
834    Building large GiST indexes by simply inserting all the tuples tends to be
835    slow, because if the index tuples are scattered across the index and the
836    index is large enough to not fit in cache, the insertions need to perform
837    a lot of random I/O.  Beginning in version 9.2, PostgreSQL supports a more
838    efficient method to build GiST indexes based on buffering, which can
839    dramatically reduce the number of random I/Os needed for non-ordered data
840    sets. For well-ordered data sets the benefit is smaller or non-existent,
841    because only a small number of pages receive new tuples at a time, and
842    those pages fit in cache even if the index as whole does not.
843   </para>
844
845   <para>
846    However, buffering index build needs to call the <function>penalty</>
847    function more often, which consumes some extra CPU resources. Also, the
848    buffers used in the buffering build need temporary disk space, up to
849    the size of the resulting index. Buffering can also influence the quality
850    of the resulting index, in both positive and negative directions. That
851    influence depends on various factors, like the distribution of the input
852    data and the operator class implementation.
853   </para>
854
855   <para>
856    By default, a GiST index build switches to the buffering method when the
857    index size reaches <xref linkend="guc-effective-cache-size">. It can
858    be manually turned on or off by the <literal>buffering</literal> parameter
859    to the CREATE INDEX command. The default behavior is good for most cases,
860    but turning buffering off might speed up the build somewhat if the input
861    data is ordered.
862   </para>
863
864  </sect2>
865 </sect1>
866
867 <sect1 id="gist-examples">
868  <title>Examples</title>
869
870  <para>
871   The <productname>PostgreSQL</productname> source distribution includes
872   several examples of index methods implemented using
873   <acronym>GiST</acronym>.  The core system currently provides text search
874   support (indexing for <type>tsvector</> and <type>tsquery</>) as well as
875   R-Tree equivalent functionality for some of the built-in geometric data types
876   (see <filename>src/backend/access/gist/gistproc.c</>).  The following
877   <filename>contrib</> modules also contain <acronym>GiST</acronym>
878   operator classes:
879
880  <variablelist>
881   <varlistentry>
882    <term><filename>btree_gist</></term>
883    <listitem>
884     <para>B-tree equivalent functionality for several data types</para>
885    </listitem>
886   </varlistentry>
887
888   <varlistentry>
889    <term><filename>cube</></term>
890    <listitem>
891     <para>Indexing for multidimensional cubes</para>
892    </listitem>
893   </varlistentry>
894
895   <varlistentry>
896    <term><filename>hstore</></term>
897    <listitem>
898     <para>Module for storing (key, value) pairs</para>
899    </listitem>
900   </varlistentry>
901
902   <varlistentry>
903    <term><filename>intarray</></term>
904    <listitem>
905     <para>RD-Tree for one-dimensional array of int4 values</para>
906    </listitem>
907   </varlistentry>
908
909   <varlistentry>
910    <term><filename>ltree</></term>
911    <listitem>
912     <para>Indexing for tree-like structures</para>
913    </listitem>
914   </varlistentry>
915
916   <varlistentry>
917    <term><filename>pg_trgm</></term>
918    <listitem>
919     <para>Text similarity using trigram matching</para>
920    </listitem>
921   </varlistentry>
922
923   <varlistentry>
924    <term><filename>seg</></term>
925    <listitem>
926     <para>Indexing for <quote>float ranges</quote></para>
927    </listitem>
928   </varlistentry>
929  </variablelist>
930  </para>
931
932 </sect1>
933
934 </chapter>