public inbox for [email protected]
help / color / mirror / Atom feedFrom: Quan Zongliang <[email protected]>
To: pgsql-hackers <[email protected]>
Subject: Improving the heapgetpage function improves performance in common scenarios
Date: Thu, 24 Aug 2023 18:55:28 +0800
Message-ID: <[email protected]> (raw)
Hi
In the function heapgetpage. If a table is not updated very frequently.
Many actions in tuple loops are superfluous. For all_visible pages,
loctup does not need to be assigned, nor does the "valid" variable.
CheckForSerializableConflictOutNeeded from
HeapCheckForSerializableConflictOut function, it only need to inspect at
the beginning of the cycle only once. Using vtune you can clearly see
the result (attached heapgetpage.jpg).
So by splitting the loop logic into two parts, the vtune results show
significant improvement (attached heapgetpage-allvis.jpg).
The test data uses TPC-H's table "orders" with a scale=20, 30 million rows.
Quan Zongliang
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 7ed72abe59..21ac1da8ab 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -451,30 +451,43 @@ heapgetpage(TableScanDesc sscan, BlockNumber block)
*/
all_visible = PageIsAllVisible(page) && !snapshot->takenDuringRecovery;
- for (lineoff = FirstOffsetNumber; lineoff <= lines; lineoff++)
+ if (all_visible && !CheckForSerializableConflictOutNeeded(scan->rs_base.rs_rd, snapshot))
{
- ItemId lpp = PageGetItemId(page, lineoff);
- HeapTupleData loctup;
- bool valid;
+ for (lineoff = FirstOffsetNumber; lineoff <= lines; lineoff++)
+ {
+ if (!ItemIdIsNormal(PageGetItemId(page, lineoff)))
+ continue;
- if (!ItemIdIsNormal(lpp))
- continue;
+ scan->rs_vistuples[ntup++] = lineoff;
+ }
+ }
+ else
+ {
+ for (lineoff = FirstOffsetNumber; lineoff <= lines; lineoff++)
+ {
+ ItemId lpp = PageGetItemId(page, lineoff);
+ HeapTupleData loctup;
+ bool valid;
- loctup.t_tableOid = RelationGetRelid(scan->rs_base.rs_rd);
- loctup.t_data = (HeapTupleHeader) PageGetItem(page, lpp);
- loctup.t_len = ItemIdGetLength(lpp);
- ItemPointerSet(&(loctup.t_self), block, lineoff);
+ if (!ItemIdIsNormal(lpp))
+ continue;
- if (all_visible)
- valid = true;
- else
- valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+ loctup.t_tableOid = RelationGetRelid(scan->rs_base.rs_rd);
+ loctup.t_data = (HeapTupleHeader) PageGetItem(page, lpp);
+ loctup.t_len = ItemIdGetLength(lpp);
+ ItemPointerSet(&(loctup.t_self), block, lineoff);
+
+ if (all_visible)
+ valid = true;
+ else
+ valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
- HeapCheckForSerializableConflictOut(valid, scan->rs_base.rs_rd,
- &loctup, buffer, snapshot);
+ HeapCheckForSerializableConflictOut(valid, scan->rs_base.rs_rd,
+ &loctup, buffer, snapshot);
- if (valid)
- scan->rs_vistuples[ntup++] = lineoff;
+ if (valid)
+ scan->rs_vistuples[ntup++] = lineoff;
+ }
}
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
Attachments:
[image/jpeg] heapgetpage-allvis.jpg (43.0K, ../[email protected]/2-heapgetpage-allvis.jpg)
download | view image
[image/jpeg] heapgetpage.jpg (99.9K, ../[email protected]/3-heapgetpage.jpg)
download | view image
[text/plain] heapgetpage.patch (2.1K, ../[email protected]/4-heapgetpage.patch)
download | inline diff:
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 7ed72abe59..21ac1da8ab 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -451,30 +451,43 @@ heapgetpage(TableScanDesc sscan, BlockNumber block)
*/
all_visible = PageIsAllVisible(page) && !snapshot->takenDuringRecovery;
- for (lineoff = FirstOffsetNumber; lineoff <= lines; lineoff++)
+ if (all_visible && !CheckForSerializableConflictOutNeeded(scan->rs_base.rs_rd, snapshot))
{
- ItemId lpp = PageGetItemId(page, lineoff);
- HeapTupleData loctup;
- bool valid;
+ for (lineoff = FirstOffsetNumber; lineoff <= lines; lineoff++)
+ {
+ if (!ItemIdIsNormal(PageGetItemId(page, lineoff)))
+ continue;
- if (!ItemIdIsNormal(lpp))
- continue;
+ scan->rs_vistuples[ntup++] = lineoff;
+ }
+ }
+ else
+ {
+ for (lineoff = FirstOffsetNumber; lineoff <= lines; lineoff++)
+ {
+ ItemId lpp = PageGetItemId(page, lineoff);
+ HeapTupleData loctup;
+ bool valid;
- loctup.t_tableOid = RelationGetRelid(scan->rs_base.rs_rd);
- loctup.t_data = (HeapTupleHeader) PageGetItem(page, lpp);
- loctup.t_len = ItemIdGetLength(lpp);
- ItemPointerSet(&(loctup.t_self), block, lineoff);
+ if (!ItemIdIsNormal(lpp))
+ continue;
- if (all_visible)
- valid = true;
- else
- valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
+ loctup.t_tableOid = RelationGetRelid(scan->rs_base.rs_rd);
+ loctup.t_data = (HeapTupleHeader) PageGetItem(page, lpp);
+ loctup.t_len = ItemIdGetLength(lpp);
+ ItemPointerSet(&(loctup.t_self), block, lineoff);
+
+ if (all_visible)
+ valid = true;
+ else
+ valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
- HeapCheckForSerializableConflictOut(valid, scan->rs_base.rs_rd,
- &loctup, buffer, snapshot);
+ HeapCheckForSerializableConflictOut(valid, scan->rs_base.rs_rd,
+ &loctup, buffer, snapshot);
- if (valid)
- scan->rs_vistuples[ntup++] = lineoff;
+ if (valid)
+ scan->rs_vistuples[ntup++] = lineoff;
+ }
}
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
view thread (4+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: Improving the heapgetpage function improves performance in common scenarios
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox