fix-some-gin-performance-problems.patch
text/x-diff
Filename: fix-some-gin-performance-problems.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/gin/ginget.c | 6 | 4 |
| src/backend/access/gin/ginscan.c | 5 | 1 |
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..a50694f6776 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -68,8 +68,12 @@ 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 1000 entries. That avoids
+ * spending O(N^2) time on probably-fruitless de-duplication of large
+ * search-key sets.
*/
- if (extra_data == NULL)
+ if (extra_data == NULL && so->totalentries < 1000)
{
for (i = 0; i < so->totalentries; i++)
{