Skip to content

Commit cdd6ab9

Browse files
committed
amcheck: Optimize speed of checking for unique constraint violation
Currently, when amcheck validates a unique constraint, it visits the heap for each index tuple. This commit implements skipping keys, which have only one non-dedeuplicated index tuple (quite common case for unique indexes). That gives substantial economy on index checking time. Reported-by: Noah Misch Discussion: https://postgr.es/m/20240325020323.fd.nmisch%40google.com Author: Alexander Korotkov, Pavel Borisov
1 parent b181062 commit cdd6ab9

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

contrib/amcheck/verify_nbtree.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,13 @@ bt_target_page_check(BtreeCheckState *state)
14331433
bool lowersizelimit;
14341434
ItemPointer scantid;
14351435

1436+
/*
1437+
* True if we already called bt_entry_unique_check() for the current
1438+
* item. This helps to avoid visiting the heap for keys, which are
1439+
* anyway presented only once and can't comprise a unique violation.
1440+
*/
1441+
bool unique_checked = false;
1442+
14361443
CHECK_FOR_INTERRUPTS();
14371444

14381445
itemid = PageGetItemIdCareful(state, state->targetblock,
@@ -1775,12 +1782,18 @@ bt_target_page_check(BtreeCheckState *state)
17751782

17761783
/*
17771784
* If the index is unique verify entries uniqueness by checking the
1778-
* heap tuples visibility.
1785+
* heap tuples visibility. Immediately check posting tuples and
1786+
* tuples with repeated keys. Postpone check for keys, which have the
1787+
* first appearance.
17791788
*/
17801789
if (state->checkunique && state->indexinfo->ii_Unique &&
1781-
P_ISLEAF(topaque) && !skey->anynullkeys)
1790+
P_ISLEAF(topaque) && !skey->anynullkeys &&
1791+
(BTreeTupleIsPosting(itup) || ItemPointerIsValid(lVis.tid)))
1792+
{
17821793
bt_entry_unique_check(state, itup, state->targetblock, offset,
17831794
&lVis);
1795+
unique_checked = true;
1796+
}
17841797

17851798
if (state->checkunique && state->indexinfo->ii_Unique &&
17861799
P_ISLEAF(topaque) && OffsetNumberNext(offset) <= max)
@@ -1799,6 +1812,9 @@ bt_target_page_check(BtreeCheckState *state)
17991812
* data (whole index tuple or last posting in index tuple). Key
18001813
* containing null value does not violate unique constraint and
18011814
* treated as different to any other key.
1815+
*
1816+
* If the next key is the same as the previous one, do the
1817+
* bt_entry_unique_check() call if it was postponed.
18021818
*/
18031819
if (_bt_compare(state->rel, skey, state->target,
18041820
OffsetNumberNext(offset)) != 0 || skey->anynullkeys)
@@ -1808,6 +1824,11 @@ bt_target_page_check(BtreeCheckState *state)
18081824
lVis.postingIndex = -1;
18091825
lVis.tid = NULL;
18101826
}
1827+
else if (!unique_checked)
1828+
{
1829+
bt_entry_unique_check(state, itup, state->targetblock, offset,
1830+
&lVis);
1831+
}
18111832
skey->scantid = scantid; /* Restore saved scan key state */
18121833
}
18131834

@@ -1890,10 +1911,19 @@ bt_target_page_check(BtreeCheckState *state)
18901911
rightkey->scantid = NULL;
18911912

18921913
/* The first key on the next page is the same */
1893-
if (_bt_compare(state->rel, rightkey, state->target, max) == 0 && !rightkey->anynullkeys)
1914+
if (_bt_compare(state->rel, rightkey, state->target, max) == 0 &&
1915+
!rightkey->anynullkeys)
18941916
{
18951917
Page rightpage;
18961918

1919+
/*
1920+
* Do the bt_entry_unique_check() call if it was
1921+
* postponed.
1922+
*/
1923+
if (!unique_checked)
1924+
bt_entry_unique_check(state, itup, state->targetblock,
1925+
offset, &lVis);
1926+
18971927
elog(DEBUG2, "cross page equal keys");
18981928
rightpage = palloc_btree_page(state,
18991929
rightblock_number);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy