]> granicus.if.org Git - postgresql/commitdiff
Improve GiST index search performance for trigram regex queries.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Apr 2013 16:49:29 +0000 (12:49 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Apr 2013 16:49:29 +0000 (12:49 -0400)
The initial coding just descended the index if any of the target trigrams
were possibly present at the next level down.  But actually we can apply
trigramsMatchGraph() so as to take advantage of AND requirements when there
are some.  The input data might contain false positive matches, but that
can only result in a false positive result, not false negative, so it's
safe to do it this way.

Alexander Korotkov

contrib/pg_trgm/trgm_gist.c

index 178f073755b11803781d22d8406c84ab196d03bd..c572d0f90f7d76563a08372d72827236a224b54f 100644 (file)
@@ -401,18 +401,24 @@ gtrgm_consistent(PG_FUNCTION_ARGS)
                                                                len = ARRNELEM(qtrg);
                                        trgm       *ptr = GETARR(qtrg);
                                        BITVECP         sign = GETSIGN(key);
+                                       bool       *check;
 
-                                       /* descend only if at least one trigram is present */
-                                       res = false;
+                                       /*
+                                        * GETBIT() tests may give false positives, due to limited
+                                        * size of the sign array.      But since trigramsMatchGraph()
+                                        * implements a monotone boolean function, false positives
+                                        * in the check array can't lead to false negative answer.
+                                        * So we can apply trigramsMatchGraph despite uncertainty,
+                                        * and that usefully improves the quality of the search.
+                                        */
+                                       check = (bool *) palloc(len * sizeof(bool));
                                        for (k = 0; k < len; k++)
                                        {
                                                CPTRGM(((char *) &tmp), ptr + k);
-                                               if (GETBIT(sign, HASHVAL(tmp)))
-                                               {
-                                                       res = true;
-                                                       break;
-                                               }
+                                               check[k] = GETBIT(sign, HASHVAL(tmp));
                                        }
+                                       res = trigramsMatchGraph(cache->graph, check);
+                                       pfree(check);
                                }
                        }
                        else