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

Commitd0ce9d0

Browse files
Remove unnecessary checks for indexes for REPLICA IDENTITY FULL tables.
Previously, when selecting an usable index for update/delete for theREPLICA IDENTITY FULL table, in IsIndexOnlyExpression(), we used tocheck if all index fields are not expressions. However, it was notnecessary, because it is enough to check if only the leftmost indexfield is not an expression (and references the remote table column)and this check has already been done byRemoteRelContainsLeftMostColumnOnIdx().This commit removes IsIndexOnlyExpression() andRemoteRelContainsLeftMostColumnOnIdx() and all checks for usableindexes for REPLICA IDENTITY FULL tables are now performed byIsIndexUsableForReplicaIdentityFull().Backpatch this to remain the code consistent.Reported-by: Peter SmithReviewed-by: Amit Kapila, Önder KalacıDiscussion:https://postgr.es/m/CAHut%2BPsGRE5WSsY0jcLHJEoA17MrbP9yy8FxdjC_ZOAACxbt%2BQ%40mail.gmail.comBackpatch-through: 16
1 parent71e4cc6 commitd0ce9d0

File tree

4 files changed

+64
-89
lines changed

4 files changed

+64
-89
lines changed

‎src/backend/executor/execReplication.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,7 @@ RelationFindReplTupleByIndex(Relation rel, Oid idxoid,
222222
if (!isIdxSafeToSkipDuplicates)
223223
{
224224
if (eq==NULL)
225-
{
226-
#ifdefUSE_ASSERT_CHECKING
227-
/* apply assertions only once for the input idxoid */
228-
IndexInfo*indexInfo=BuildIndexInfo(idxrel);
229-
230-
Assert(IsIndexUsableForReplicaIdentityFull(indexInfo));
231-
#endif
232-
233225
eq=palloc0(sizeof(*eq)*outslot->tts_tupleDescriptor->natts);
234-
}
235226

236227
if (!tuples_equal(outslot,searchslot,eq))
237228
continue;

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

Lines changed: 44 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -734,71 +734,9 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root,
734734
returnentry;
735735
}
736736

737-
/*
738-
* Returns true if the given index consists only of expressions such as:
739-
* CREATE INDEX idx ON table(foo(col));
740-
*
741-
* Returns false even if there is one column reference:
742-
* CREATE INDEX idx ON table(foo(col), col_2);
743-
*/
744-
staticbool
745-
IsIndexOnlyOnExpression(IndexInfo*indexInfo)
746-
{
747-
for (inti=0;i<indexInfo->ii_NumIndexKeyAttrs;i++)
748-
{
749-
AttrNumberattnum=indexInfo->ii_IndexAttrNumbers[i];
750-
751-
if (AttributeNumberIsValid(attnum))
752-
return false;
753-
}
754-
755-
return true;
756-
}
757-
758-
/*
759-
* Returns true if the attrmap contains the leftmost column of the index.
760-
* Otherwise returns false.
761-
*
762-
* attrmap is a map of local attributes to remote ones. We can consult this
763-
* map to check whether the local index attribute has a corresponding remote
764-
* attribute.
765-
*/
766-
staticbool
767-
RemoteRelContainsLeftMostColumnOnIdx(IndexInfo*indexInfo,AttrMap*attrmap)
768-
{
769-
AttrNumberkeycol;
770-
771-
Assert(indexInfo->ii_NumIndexAttrs >=1);
772-
773-
keycol=indexInfo->ii_IndexAttrNumbers[0];
774-
if (!AttributeNumberIsValid(keycol))
775-
return false;
776-
777-
if (attrmap->maplen <=AttrNumberGetAttrOffset(keycol))
778-
return false;
779-
780-
returnattrmap->attnums[AttrNumberGetAttrOffset(keycol)] >=0;
781-
}
782-
783737
/*
784738
* Returns the oid of an index that can be used by the apply worker to scan
785-
* the relation. The index must be btree or hash, non-partial, and the leftmost
786-
* field must be a column (not an expression) that references the remote
787-
* relation column. These limitations help to keep the index scan similar
788-
* to PK/RI index scans.
789-
*
790-
* Note that the limitations of index scans for replica identity full only
791-
* adheres to a subset of the limitations of PK/RI. For example, we support
792-
* columns that are marked as [NULL] or we are not interested in the [NOT
793-
* DEFERRABLE] aspect of constraints here. It works for us because we always
794-
* compare the tuples for non-PK/RI index scans. See
795-
* RelationFindReplTupleByIndex().
796-
*
797-
* XXX: See IsIndexUsableForReplicaIdentityFull() to know the challenges in
798-
* supporting indexes other than btree and hash. For partial indexes, the
799-
* required changes are likely to be larger. If none of the tuples satisfy
800-
* the expression for the index scan, we fall-back to sequential execution,
801-
* which might not be a good idea in some cases.
739+
* the relation.
802740
*
803741
* We expect to call this function when REPLICA IDENTITY FULL is defined for
804742
* the remote relation.
@@ -815,31 +753,41 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
815753
{
816754
Oididxoid=lfirst_oid(lc);
817755
boolisUsableIdx;
818-
boolcontainsLeftMostCol;
819756
RelationidxRel;
820757
IndexInfo*idxInfo;
821758

822759
idxRel=index_open(idxoid,AccessShareLock);
823760
idxInfo=BuildIndexInfo(idxRel);
824-
isUsableIdx=IsIndexUsableForReplicaIdentityFull(idxInfo);
825-
containsLeftMostCol=
826-
RemoteRelContainsLeftMostColumnOnIdx(idxInfo,attrmap);
761+
isUsableIdx=IsIndexUsableForReplicaIdentityFull(idxInfo,attrmap);
827762
index_close(idxRel,AccessShareLock);
828763

829764
/* Return the first eligible index found */
830-
if (isUsableIdx&&containsLeftMostCol)
765+
if (isUsableIdx)
831766
returnidxoid;
832767
}
833768

834769
returnInvalidOid;
835770
}
836771

837772
/*
838-
* Returns true if the index is usable for replica identity full. For details,
839-
* see FindUsableIndexForReplicaIdentityFull.
773+
* Returns true if the index is usable for replica identity full.
840774
*
841-
* Currently, only Btree and Hash indexes can be returned as usable. This
842-
* is due to following reasons:
775+
* The index must be btree or hash, non-partial, and the leftmost field must be
776+
* a column (not an expression) that references the remote relation column. These
777+
* limitations help to keep the index scan similar to PK/RI index scans.
778+
*
779+
* attrmap is a map of local attributes to remote ones. We can consult this
780+
* map to check whether the local index attribute has a corresponding remote
781+
* attribute.
782+
*
783+
* Note that the limitations of index scans for replica identity full only
784+
* adheres to a subset of the limitations of PK/RI. For example, we support
785+
* columns that are marked as [NULL] or we are not interested in the [NOT
786+
* DEFERRABLE] aspect of constraints here. It works for us because we always
787+
* compare the tuples for non-PK/RI index scans. See
788+
* RelationFindReplTupleByIndex().
789+
*
790+
* The reasons why only Btree and Hash indexes can be considered as usable are:
843791
*
844792
* 1) Other index access methods don't have a fixed strategy for equality
845793
* operation. Refer get_equal_strategy_number_for_am().
@@ -851,16 +799,38 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
851799
*
852800
* XXX: Note that BRIN and GIN indexes do not implement "amgettuple" which
853801
* will be used later to fetch the tuples. See RelationFindReplTupleByIndex().
802+
*
803+
* XXX: To support partial indexes, the required changes are likely to be larger.
804+
* If none of the tuples satisfy the expression for the index scan, we fall-back
805+
* to sequential execution, which might not be a good idea in some cases.
854806
*/
855807
bool
856-
IsIndexUsableForReplicaIdentityFull(IndexInfo*indexInfo)
808+
IsIndexUsableForReplicaIdentityFull(IndexInfo*indexInfo,AttrMap*attrmap)
857809
{
810+
AttrNumberkeycol;
811+
858812
/* Ensure that the index access method has a valid equal strategy */
859813
if (get_equal_strategy_number_for_am(indexInfo->ii_Am)==InvalidStrategy)
860814
return false;
815+
816+
/* The index must not be a partial index */
861817
if (indexInfo->ii_Predicate!=NIL)
862818
return false;
863-
if (IsIndexOnlyOnExpression(indexInfo))
819+
820+
Assert(indexInfo->ii_NumIndexAttrs >=1);
821+
822+
/* The leftmost index field must not be an expression */
823+
keycol=indexInfo->ii_IndexAttrNumbers[0];
824+
if (!AttributeNumberIsValid(keycol))
825+
return false;
826+
827+
/*
828+
* And the leftmost index field must reference the remote relation column.
829+
* This is because if it doesn't, the sequential scan is favorable over
830+
* index scan in most cases.
831+
*/
832+
if (attrmap->maplen <=AttrNumberGetAttrOffset(keycol)||
833+
attrmap->attnums[AttrNumberGetAttrOffset(keycol)]<0)
864834
return false;
865835

866836
#ifdefUSE_ASSERT_CHECKING

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
#include<sys/stat.h>
141141
#include<unistd.h>
142142

143+
#include"access/genam.h"
143144
#include"access/table.h"
144145
#include"access/tableam.h"
145146
#include"access/twophase.h"
@@ -410,7 +411,7 @@ static void apply_handle_delete_internal(ApplyExecutionData *edata,
410411
ResultRelInfo*relinfo,
411412
TupleTableSlot*remoteslot,
412413
Oidlocalindexoid);
413-
staticboolFindReplTupleInLocalRel(EState*estate,Relationlocalrel,
414+
staticboolFindReplTupleInLocalRel(ApplyExecutionData*edata,Relationlocalrel,
414415
LogicalRepRelation*remoterel,
415416
Oidlocalidxoid,
416417
TupleTableSlot*remoteslot,
@@ -2663,7 +2664,7 @@ apply_handle_update_internal(ApplyExecutionData *edata,
26632664
EvalPlanQualInit(&epqstate,estate,NULL,NIL,-1,NIL);
26642665
ExecOpenIndices(relinfo, false);
26652666

2666-
found=FindReplTupleInLocalRel(estate,localrel,
2667+
found=FindReplTupleInLocalRel(edata,localrel,
26672668
&relmapentry->remoterel,
26682669
localindexoid,
26692670
remoteslot,&localslot);
@@ -2816,7 +2817,7 @@ apply_handle_delete_internal(ApplyExecutionData *edata,
28162817
EvalPlanQualInit(&epqstate,estate,NULL,NIL,-1,NIL);
28172818
ExecOpenIndices(relinfo, false);
28182819

2819-
found=FindReplTupleInLocalRel(estate,localrel,remoterel,localindexoid,
2820+
found=FindReplTupleInLocalRel(edata,localrel,remoterel,localindexoid,
28202821
remoteslot,&localslot);
28212822

28222823
/* If found delete it. */
@@ -2855,12 +2856,13 @@ apply_handle_delete_internal(ApplyExecutionData *edata,
28552856
* Local tuple, if found, is returned in '*localslot'.
28562857
*/
28572858
staticbool
2858-
FindReplTupleInLocalRel(EState*estate,Relationlocalrel,
2859+
FindReplTupleInLocalRel(ApplyExecutionData*edata,Relationlocalrel,
28592860
LogicalRepRelation*remoterel,
28602861
Oidlocalidxoid,
28612862
TupleTableSlot*remoteslot,
28622863
TupleTableSlot**localslot)
28632864
{
2865+
EState*estate=edata->estate;
28642866
boolfound;
28652867

28662868
/*
@@ -2875,9 +2877,21 @@ FindReplTupleInLocalRel(EState *estate, Relation localrel,
28752877
(remoterel->replident==REPLICA_IDENTITY_FULL));
28762878

28772879
if (OidIsValid(localidxoid))
2880+
{
2881+
#ifdefUSE_ASSERT_CHECKING
2882+
Relationidxrel=index_open(localidxoid,AccessShareLock);
2883+
2884+
/* Index must be PK, RI, or usable for REPLICA IDENTITY FULL tables */
2885+
Assert(GetRelationIdentityOrPK(idxrel)==localidxoid||
2886+
IsIndexUsableForReplicaIdentityFull(BuildIndexInfo(idxrel),
2887+
edata->targetRel->attrmap));
2888+
index_close(idxrel,AccessShareLock);
2889+
#endif
2890+
28782891
found=RelationFindReplTupleByIndex(localrel,localidxoid,
28792892
LockTupleExclusive,
28802893
remoteslot,*localslot);
2894+
}
28812895
else
28822896
found=RelationFindReplTupleSeq(localrel,LockTupleExclusive,
28832897
remoteslot,*localslot);
@@ -2995,7 +3009,7 @@ apply_handle_tuple_routing(ApplyExecutionData *edata,
29953009
boolfound;
29963010

29973011
/* Get the matching local tuple from the partition. */
2998-
found=FindReplTupleInLocalRel(estate,partrel,
3012+
found=FindReplTupleInLocalRel(edata,partrel,
29993013
&part_entry->remoterel,
30003014
part_entry->localindexoid,
30013015
remoteslot_part,&localslot);

‎src/include/replication/logicalrelation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ extern LogicalRepRelMapEntry *logicalrep_partition_open(LogicalRepRelMapEntry *r
4848
Relationpartrel,AttrMap*map);
4949
externvoidlogicalrep_rel_close(LogicalRepRelMapEntry*rel,
5050
LOCKMODElockmode);
51-
externboolIsIndexUsableForReplicaIdentityFull(IndexInfo*indexInfo);
51+
externboolIsIndexUsableForReplicaIdentityFull(IndexInfo*indexInfo,AttrMap*attrmap);
5252
externOidGetRelationIdentityOrPK(Relationrel);
5353

5454
#endif/* LOGICALRELATION_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp