Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2000b6c

Browse files
committed
Don't fetch partition check expression during InitResultRelInfo.
Since there is only one place that actually needs the partition checkexpression, namely ExecPartitionCheck, it's better to fetch it fromthe relcache there. In this way we will never fetch it at all ifthe query never has use for it, and we still fetch it just once whenwe do need it.The reason for taking an interest in this is that if the relcachedoesn't already have the check expression cached, fetching itrequires obtaining AccessShareLock on the partition root. Thatmeans that operations that look like they should only touch thepartition itself will also take a lock on the root. In particularwe observed that TRUNCATE on a partition may take a lock on thepartition's root, contributing to a deadlock situation in parallelpg_restore.As written, this patch does have a small cost, which is that weare microscopically reducing efficiency for the case where a partitionhas an empty check expression. ExecPartitionCheck will be called,and will go through the motions of setting up and checking an emptyqual, where before it would not have been called at all. We couldavoid that by adding a separate boolean flag to track whether thereis a partition expression to test. However, this case only arisesfor a default partition with no siblings, which surely is not aninteresting case in practice. Hence adding complexity for itdoes not seem like a good trade-off.Amit Langote, per a suggestion by meDiscussion:https://postgr.es/m/VI1PR03MB31670CA1BD9625C3A8C5DD05EB230@VI1PR03MB3167.eurprd03.prod.outlook.com
1 parentaac80bf commit2000b6c

File tree

7 files changed

+26
-40
lines changed

7 files changed

+26
-40
lines changed

‎src/backend/commands/copy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3236,7 +3236,7 @@ CopyFrom(CopyState cstate)
32363236
* we don't need to if there's no BR trigger defined on the
32373237
* partition.
32383238
*/
3239-
if (resultRelInfo->ri_PartitionCheck&&
3239+
if (resultRelInfo->ri_RelationDesc->rd_rel->relispartition&&
32403240
(proute==NULL||has_before_insert_row_trig))
32413241
ExecPartitionCheck(resultRelInfo,myslot,estate, true);
32423242

‎src/backend/executor/execMain.c

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,8 +1280,6 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
12801280
Relationpartition_root,
12811281
intinstrument_options)
12821282
{
1283-
List*partition_check=NIL;
1284-
12851283
MemSet(resultRelInfo,0,sizeof(ResultRelInfo));
12861284
resultRelInfo->type=T_ResultRelInfo;
12871285
resultRelInfo->ri_RangeTableIndex=resultRelationIndex;
@@ -1325,23 +1323,6 @@ InitResultRelInfo(ResultRelInfo *resultRelInfo,
13251323
resultRelInfo->ri_ReturningSlot=NULL;
13261324
resultRelInfo->ri_TrigOldSlot=NULL;
13271325
resultRelInfo->ri_TrigNewSlot=NULL;
1328-
1329-
/*
1330-
* Partition constraint, which also includes the partition constraint of
1331-
* all the ancestors that are partitions. Note that it will be checked
1332-
* even in the case of tuple-routing where this table is the target leaf
1333-
* partition, if there any BR triggers defined on the table. Although
1334-
* tuple-routing implicitly preserves the partition constraint of the
1335-
* target partition for a given row, the BR triggers may change the row
1336-
* such that the constraint is no longer satisfied, which we must fail for
1337-
* by checking it explicitly.
1338-
*
1339-
* If this is a partitioned table, the partition constraint (if any) of a
1340-
* given row will be checked just before performing tuple-routing.
1341-
*/
1342-
partition_check=RelationGetPartitionQual(resultRelationDesc);
1343-
1344-
resultRelInfo->ri_PartitionCheck=partition_check;
13451326
resultRelInfo->ri_PartitionRoot=partition_root;
13461327
resultRelInfo->ri_PartitionInfo=NULL;/* may be set later */
13471328
resultRelInfo->ri_CopyMultiInsertBuffer=NULL;
@@ -1776,7 +1757,7 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
17761757
* ExecPartitionCheck --- check that tuple meets the partition constraint.
17771758
*
17781759
* Returns true if it meets the partition constraint. If the constraint
1779-
* fails and we're asked to emitto error, do so and don't return; otherwise
1760+
* fails and we're asked to emitan error, do so and don't return; otherwise
17801761
* return false.
17811762
*/
17821763
bool
@@ -1788,14 +1769,22 @@ ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
17881769

17891770
/*
17901771
* If first time through, build expression state tree for the partition
1791-
* check expression. Keep it in the per-query memory context so they'll
1792-
* survive throughout the query.
1772+
* check expression. (In the corner case where the partition check
1773+
* expression is empty, ie there's a default partition and nothing else,
1774+
* we'll be fooled into executing this code each time through. But it's
1775+
* pretty darn cheap in that case, so we don't worry about it.)
17931776
*/
17941777
if (resultRelInfo->ri_PartitionCheckExpr==NULL)
17951778
{
1796-
List*qual=resultRelInfo->ri_PartitionCheck;
1779+
/*
1780+
* Ensure that the qual tree and prepared expression are in the
1781+
* query-lifespan context.
1782+
*/
1783+
MemoryContextoldcxt=MemoryContextSwitchTo(estate->es_query_cxt);
1784+
List*qual=RelationGetPartitionQual(resultRelInfo->ri_RelationDesc);
17971785

17981786
resultRelInfo->ri_PartitionCheckExpr=ExecPrepareCheck(qual,estate);
1787+
MemoryContextSwitchTo(oldcxt);
17991788
}
18001789

18011790
/*
@@ -1904,9 +1893,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
19041893
Bitmapset*insertedCols;
19051894
Bitmapset*updatedCols;
19061895

1907-
Assert(constr||resultRelInfo->ri_PartitionCheck);
1896+
Assert(constr);/* we should not be called otherwise */
19081897

1909-
if (constr&&constr->has_not_null)
1898+
if (constr->has_not_null)
19101899
{
19111900
intnatts=tupdesc->natts;
19121901
intattrChk;
@@ -1967,7 +1956,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
19671956
}
19681957
}
19691958

1970-
if (constr&&constr->num_check>0)
1959+
if (constr->num_check>0)
19711960
{
19721961
constchar*failed;
19731962

‎src/backend/executor/execPartition.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ ExecFindPartition(ModifyTableState *mtstate,
299299
* First check the root table's partition constraint, if any. No point in
300300
* routing the tuple if it doesn't belong in the root table itself.
301301
*/
302-
if (rootResultRelInfo->ri_PartitionCheck)
302+
if (rootResultRelInfo->ri_RelationDesc->rd_rel->relispartition)
303303
ExecPartitionCheck(rootResultRelInfo,slot,estate, true);
304304

305305
/* start with the root partitioned table */

‎src/backend/executor/execReplication.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
435435
/* Check the constraints of the tuple */
436436
if (rel->rd_att->constr)
437437
ExecConstraints(resultRelInfo,slot,estate);
438-
if (resultRelInfo->ri_PartitionCheck)
438+
if (rel->rd_rel->relispartition)
439439
ExecPartitionCheck(resultRelInfo,slot,estate, true);
440440

441441
/* OK, store the tuple and create index entries for it */
@@ -501,7 +501,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
501501
/* Check the constraints of the tuple */
502502
if (rel->rd_att->constr)
503503
ExecConstraints(resultRelInfo,slot,estate);
504-
if (resultRelInfo->ri_PartitionCheck)
504+
if (rel->rd_rel->relispartition)
505505
ExecPartitionCheck(resultRelInfo,slot,estate, true);
506506

507507
simple_table_tuple_update(rel,tid,slot,estate->es_snapshot,

‎src/backend/executor/nodeModifyTable.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ ExecInsert(ModifyTableState *mtstate,
491491
* one; except that if we got here via tuple-routing, we don't need to
492492
* if there's no BR trigger defined on the partition.
493493
*/
494-
if (resultRelInfo->ri_PartitionCheck&&
494+
if (resultRelationDesc->rd_rel->relispartition&&
495495
(resultRelInfo->ri_PartitionRoot==NULL||
496496
(resultRelInfo->ri_TrigDesc&&
497497
resultRelInfo->ri_TrigDesc->trig_insert_before_row)))
@@ -1181,7 +1181,7 @@ lreplace:;
11811181
* row. So skip the WCO checks if the partition constraint fails.
11821182
*/
11831183
partition_constraint_failed=
1184-
resultRelInfo->ri_PartitionCheck&&
1184+
resultRelationDesc->rd_rel->relispartition&&
11851185
!ExecPartitionCheck(resultRelInfo,slot,estate, false);
11861186

11871187
if (!partition_constraint_failed&&

‎src/backend/replication/logical/worker.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1676,7 +1676,7 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo,
16761676
* Does the updated tuple still satisfy the current
16771677
* partition's constraint?
16781678
*/
1679-
if (partrelinfo->ri_PartitionCheck==NULL||
1679+
if (!partrel->rd_rel->relispartition||
16801680
ExecPartitionCheck(partrelinfo,remoteslot_part,estate,
16811681
false))
16821682
{

‎src/include/nodes/execnodes.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -477,19 +477,16 @@ typedef struct ResultRelInfo
477477
/* ON CONFLICT evaluation state */
478478
OnConflictSetState*ri_onConflict;
479479

480-
/* partition check expression */
481-
List*ri_PartitionCheck;
482-
483-
/* partition check expression state */
480+
/* partition check expression state (NULL if not set up yet) */
484481
ExprState*ri_PartitionCheckExpr;
485482

486-
/* relation descriptor forrootpartitioned table */
483+
/* relation descriptor for partitioned table's root, if any */
487484
Relationri_PartitionRoot;
488485

489-
/*Additional information specific topartition tuple routing */
486+
/*info forpartition tuple routing (NULL if not set up yet) */
490487
structPartitionRoutingInfo*ri_PartitionInfo;
491488

492-
/*For use by copy.c when performing multi-inserts */
489+
/*for use by copy.c when performing multi-inserts */
493490
structCopyMultiInsertBuffer*ri_CopyMultiInsertBuffer;
494491
}ResultRelInfo;
495492

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp