mirror of https://github.com/citusdata/citus.git
Speed up SequenceUsedInDistributedTable (#7579)
DESCRIPTION: Fix performance issue when creating distributed tables if many already exist This builds on the work to speed up EnsureSequenceTypeSupported, and now does something similar for SequenceUsedInDistributedTable. SequenceUsedInDistributedTable had a similar O(number of citus tables) operation. This fixes that and speeds up creation of distributed tables significantly when many distributed tables already exist. Fixes #7022pull/7574/head^2
parent
381f31756e
commit
cdf51da458
|
@ -14,6 +14,7 @@
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
#include "catalog/dependency.h"
|
#include "catalog/dependency.h"
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
|
#include "catalog/pg_attrdef.h"
|
||||||
#include "commands/defrem.h"
|
#include "commands/defrem.h"
|
||||||
#include "commands/extension.h"
|
#include "commands/extension.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
|
@ -507,22 +508,14 @@ PreprocessAlterSequenceStmt(Node *node, const char *queryString,
|
||||||
static Oid
|
static Oid
|
||||||
SequenceUsedInDistributedTable(const ObjectAddress *sequenceAddress, char depType)
|
SequenceUsedInDistributedTable(const ObjectAddress *sequenceAddress, char depType)
|
||||||
{
|
{
|
||||||
List *citusTableIdList = CitusTableTypeIdList(ANY_CITUS_TABLE_TYPE);
|
Oid relationId;
|
||||||
Oid citusTableId = InvalidOid;
|
List *relations = GetDependentRelationsWithSequence(sequenceAddress->objectId,
|
||||||
foreach_oid(citusTableId, citusTableIdList)
|
depType);
|
||||||
|
foreach_oid(relationId, relations)
|
||||||
{
|
{
|
||||||
List *seqInfoList = NIL;
|
if (IsCitusTable(relationId))
|
||||||
GetDependentSequencesWithRelation(citusTableId, &seqInfoList, 0, depType);
|
|
||||||
SequenceInfo *seqInfo = NULL;
|
|
||||||
foreach_ptr(seqInfo, seqInfoList)
|
|
||||||
{
|
{
|
||||||
/*
|
return relationId;
|
||||||
* This sequence is used in a distributed table
|
|
||||||
*/
|
|
||||||
if (seqInfo->sequenceOid == sequenceAddress->objectId)
|
|
||||||
{
|
|
||||||
return citusTableId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1637,6 +1637,74 @@ GetDependentSequencesWithRelation(Oid relationId, List **seqInfoList,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GetDependentDependentRelationsWithSequence returns a list of oids of
|
||||||
|
* relations that have have a dependency on the given sequence.
|
||||||
|
* There are three types of dependencies:
|
||||||
|
* 1. direct auto (owned sequences), created using SERIAL or BIGSERIAL
|
||||||
|
* 2. indirect auto (through an AttrDef), created using DEFAULT nextval('..')
|
||||||
|
* 3. internal, created using GENERATED ALWAYS AS IDENTITY
|
||||||
|
*
|
||||||
|
* Depending on the passed deptype, we return the relations that have the
|
||||||
|
* given type(s):
|
||||||
|
* - DEPENDENCY_AUTO returns both 1 and 2
|
||||||
|
* - DEPENDENCY_INTERNAL returns 3
|
||||||
|
*
|
||||||
|
* The returned list can contain duplicates, as the same relation can have
|
||||||
|
* multiple dependencies on the sequence.
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
GetDependentRelationsWithSequence(Oid sequenceOid, char depType)
|
||||||
|
{
|
||||||
|
List *relations = NIL;
|
||||||
|
ScanKeyData key[2];
|
||||||
|
HeapTuple tup;
|
||||||
|
|
||||||
|
Relation depRel = table_open(DependRelationId, AccessShareLock);
|
||||||
|
|
||||||
|
ScanKeyInit(&key[0],
|
||||||
|
Anum_pg_depend_classid,
|
||||||
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(RelationRelationId));
|
||||||
|
ScanKeyInit(&key[1],
|
||||||
|
Anum_pg_depend_objid,
|
||||||
|
BTEqualStrategyNumber, F_OIDEQ,
|
||||||
|
ObjectIdGetDatum(sequenceOid));
|
||||||
|
SysScanDesc scan = systable_beginscan(depRel, DependDependerIndexId, true,
|
||||||
|
NULL, lengthof(key), key);
|
||||||
|
while (HeapTupleIsValid(tup = systable_getnext(scan)))
|
||||||
|
{
|
||||||
|
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
|
||||||
|
|
||||||
|
if (
|
||||||
|
deprec->refclassid == RelationRelationId &&
|
||||||
|
deprec->refobjsubid != 0 &&
|
||||||
|
deprec->deptype == depType)
|
||||||
|
{
|
||||||
|
relations = lappend_oid(relations, deprec->refobjid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
systable_endscan(scan);
|
||||||
|
|
||||||
|
table_close(depRel, AccessShareLock);
|
||||||
|
|
||||||
|
if (depType == DEPENDENCY_AUTO)
|
||||||
|
{
|
||||||
|
Oid attrDefOid;
|
||||||
|
List *attrDefOids = GetAttrDefsFromSequence(sequenceOid);
|
||||||
|
|
||||||
|
foreach_oid(attrDefOid, attrDefOids)
|
||||||
|
{
|
||||||
|
ObjectAddress columnAddress = GetAttrDefaultColumnAddress(attrDefOid);
|
||||||
|
relations = lappend_oid(relations, columnAddress.objectId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return relations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetSequencesFromAttrDef returns a list of sequence OIDs that have
|
* GetSequencesFromAttrDef returns a list of sequence OIDs that have
|
||||||
* dependency with the given attrdefOid in pg_depend
|
* dependency with the given attrdefOid in pg_depend
|
||||||
|
|
|
@ -136,6 +136,7 @@ ObjectAddress GetAttrDefaultColumnAddress(Oid attrdefoid);
|
||||||
extern List * GetAttrDefsFromSequence(Oid seqOid);
|
extern List * GetAttrDefsFromSequence(Oid seqOid);
|
||||||
extern void GetDependentSequencesWithRelation(Oid relationId, List **seqInfoList,
|
extern void GetDependentSequencesWithRelation(Oid relationId, List **seqInfoList,
|
||||||
AttrNumber attnum, char depType);
|
AttrNumber attnum, char depType);
|
||||||
|
extern List * GetDependentRelationsWithSequence(Oid seqId, char depType);
|
||||||
extern List * GetDependentFunctionsWithRelation(Oid relationId);
|
extern List * GetDependentFunctionsWithRelation(Oid relationId);
|
||||||
extern Oid GetAttributeTypeOid(Oid relationId, AttrNumber attnum);
|
extern Oid GetAttributeTypeOid(Oid relationId, AttrNumber attnum);
|
||||||
extern void SetLocalEnableMetadataSync(bool state);
|
extern void SetLocalEnableMetadataSync(bool state);
|
||||||
|
|
Loading…
Reference in New Issue