aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/gin/ginget.c10
-rw-r--r--src/backend/access/gin/ginscan.c7
2 files changed, 12 insertions, 5 deletions
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index f3b19d280c3..4a56f19390d 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -558,16 +558,18 @@ startScanKey(GinState *ginstate, GinScanOpaque so, GinScanKey key)
qsort_arg(entryIndexes, key->nentries, sizeof(int),
entryIndexByFrequencyCmp, key);
+ for (i = 1; i < key->nentries; i++)
+ key->entryRes[entryIndexes[i]] = GIN_MAYBE;
for (i = 0; i < key->nentries - 1; i++)
{
/* Pass all entries <= i as FALSE, and the rest as MAYBE */
- for (j = 0; j <= i; j++)
- key->entryRes[entryIndexes[j]] = GIN_FALSE;
- for (j = i + 1; j < key->nentries; j++)
- key->entryRes[entryIndexes[j]] = GIN_MAYBE;
+ key->entryRes[entryIndexes[i]] = GIN_FALSE;
if (key->triConsistentFn(key) == GIN_FALSE)
break;
+
+ /* Make this loop interruptible in case there are many keys */
+ CHECK_FOR_INTERRUPTS();
}
/* i is now the last required entry. */
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index 63ded6301e2..84aa14594f8 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -68,8 +68,13 @@ ginFillScanEntry(GinScanOpaque so, OffsetNumber attnum,
*
* Entries with non-null extra_data are never considered identical, since
* we can't know exactly what the opclass might be doing with that.
+ *
+ * Also, give up de-duplication once we have 100 entries. That avoids
+ * spending O(N^2) time on probably-fruitless de-duplication of large
+ * search-key sets. The threshold of 100 is arbitrary but matches
+ * predtest.c's threshold for what's a large array.
*/
- if (extra_data == NULL)
+ if (extra_data == NULL && so->totalentries < 100)
{
for (i = 0; i < so->totalentries; i++)
{