Skip to content

Commit 1ff4161

Browse files
committed
Use multi-inserts for pg_enum
This allows to insert at once all the enum values defined with a given type into pg_enum, reducing the WAL produced by roughly 10%~. pg_enum's indexes are opened and closed now once rather than N times. The number of items to insert is known in advance, making this change straight-forward, and would happen on a CREATE TYPE .. AS ENUM. The amount of data inserted is capped at 64kB for each insert batch. This is similar to commits 63110c6 and e3931d0, that worked on different catalogs. Reported-by: Ranier Vilela Author: Michael Paquier Reviewed-by: Kyotaro Horiguchi, Ranier Vilela Discussion: https://postgr.es/m/Y3M5bovrkTQbAO4W@paquier.xyz
1 parent 09a7218 commit 1ff4161

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

src/backend/catalog/pg_enum.c

+42-13
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ void
6161
EnumValuesCreate(Oid enumTypeOid, List *vals)
6262
{
6363
Relation pg_enum;
64-
NameData enumlabel;
6564
Oid *oids;
6665
int elemno,
6766
num_elems;
68-
Datum values[Natts_pg_enum];
69-
bool nulls[Natts_pg_enum];
7067
ListCell *lc;
71-
HeapTuple tup;
68+
int slotCount = 0;
69+
int nslots;
70+
CatalogIndexState indstate;
71+
TupleTableSlot **slot;
7272

7373
num_elems = list_length(vals);
7474

@@ -111,12 +111,21 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
111111
qsort(oids, num_elems, sizeof(Oid), oid_cmp);
112112

113113
/* and make the entries */
114-
memset(nulls, false, sizeof(nulls));
114+
indstate = CatalogOpenIndexes(pg_enum);
115+
116+
/* allocate the slots to use and initialize them */
117+
nslots = Min(num_elems,
118+
MAX_CATALOG_MULTI_INSERT_BYTES / sizeof(FormData_pg_enum));
119+
slot = palloc(sizeof(TupleTableSlot *) * nslots);
120+
for (int i = 0; i < nslots; i++)
121+
slot[i] = MakeSingleTupleTableSlot(RelationGetDescr(pg_enum),
122+
&TTSOpsHeapTuple);
115123

116124
elemno = 0;
117125
foreach(lc, vals)
118126
{
119127
char *lab = strVal(lfirst(lc));
128+
Name enumlabel = palloc0(NAMEDATALEN);
120129

121130
/*
122131
* labels are stored in a name field, for easier syscache lookup, so
@@ -129,22 +138,42 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
129138
errdetail("Labels must be %d bytes or less.",
130139
NAMEDATALEN - 1)));
131140

132-
values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(oids[elemno]);
133-
values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
134-
values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(elemno + 1);
135-
namestrcpy(&enumlabel, lab);
136-
values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
141+
ExecClearTuple(slot[slotCount]);
137142

138-
tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
143+
memset(slot[slotCount]->tts_isnull, false,
144+
slot[slotCount]->tts_tupleDescriptor->natts * sizeof(bool));
139145

140-
CatalogTupleInsert(pg_enum, tup);
141-
heap_freetuple(tup);
146+
slot[slotCount]->tts_values[Anum_pg_enum_oid - 1] = ObjectIdGetDatum(oids[elemno]);
147+
slot[slotCount]->tts_values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
148+
slot[slotCount]->tts_values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(elemno + 1);
149+
150+
namestrcpy(enumlabel, lab);
151+
slot[slotCount]->tts_values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(enumlabel);
152+
153+
ExecStoreVirtualTuple(slot[slotCount]);
154+
slotCount++;
155+
156+
/* if slots are full, insert a batch of tuples */
157+
if (slotCount == nslots)
158+
{
159+
CatalogTuplesMultiInsertWithInfo(pg_enum, slot, slotCount,
160+
indstate);
161+
slotCount = 0;
162+
}
142163

143164
elemno++;
144165
}
145166

167+
/* Insert any tuples left in the buffer */
168+
if (slotCount > 0)
169+
CatalogTuplesMultiInsertWithInfo(pg_enum, slot, slotCount,
170+
indstate);
171+
146172
/* clean up */
147173
pfree(oids);
174+
for (int i = 0; i < nslots; i++)
175+
ExecDropSingleTupleTableSlot(slot[i]);
176+
CatalogCloseIndexes(indstate);
148177
table_close(pg_enum, RowExclusiveLock);
149178
}
150179

0 commit comments

Comments
 (0)