Skip to content

Commit d573e23

Browse files
committed
Take fewer snapshots.
When a PORTAL_ONE_SELECT query is executed, we can opportunistically reuse the parse/plan shot for the execution phase. This cuts down the number of snapshots per simple query from 2 to 1 for the simple protocol, and 3 to 2 for the extended protocol. Since we are only reusing a snapshot taken early in the processing of the same protocol message, the change shouldn't be user-visible, except that the remote possibility of the planning and execution snapshots being different is eliminated. Note that this change does not make it safe to assume that the parse/plan snapshot will certainly be reused; that will currently only happen if PortalStart() decides to use the PORTAL_ONE_SELECT strategy. It might be worth trying to provide some stronger guarantees here in the future, but for now we don't. Patch by me; review by Dimitri Fontaine.
1 parent e1042a3 commit d573e23

File tree

6 files changed

+39
-32
lines changed

6 files changed

+39
-32
lines changed

src/backend/commands/portalcmds.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
121121
/*
122122
* Start execution, inserting parameters if any.
123123
*/
124-
PortalStart(portal, params, GetActiveSnapshot());
124+
PortalStart(portal, params, true);
125125

126126
Assert(portal->strategy == PORTAL_ONE_SELECT);
127127

src/backend/commands/prepare.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ ExecuteQuery(ExecuteStmt *stmt, const char *queryString,
278278
/*
279279
* Run the portal to completion.
280280
*/
281-
PortalStart(portal, paramLI, GetActiveSnapshot());
281+
PortalStart(portal, paramLI, true);
282282

283283
(void) PortalRun(portal, FETCH_ALL, false, dest, dest, completionTag);
284284

src/backend/executor/spi.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,6 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
11261126
CachedPlan *cplan;
11271127
List *stmt_list;
11281128
char *query_string;
1129-
Snapshot snapshot;
11301129
MemoryContext oldcontext;
11311130
Portal portal;
11321131

@@ -1269,15 +1268,6 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
12691268
}
12701269
}
12711270

1272-
/* Set up the snapshot to use. */
1273-
if (read_only)
1274-
snapshot = GetActiveSnapshot();
1275-
else
1276-
{
1277-
CommandCounterIncrement();
1278-
snapshot = GetTransactionSnapshot();
1279-
}
1280-
12811271
/*
12821272
* If the plan has parameters, copy them into the portal. Note that this
12831273
* must be done after revalidating the plan, because in dynamic parameter
@@ -1293,7 +1283,13 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
12931283
/*
12941284
* Start portal execution.
12951285
*/
1296-
PortalStart(portal, paramLI, snapshot);
1286+
if (read_only)
1287+
PortalStart(portal, paramLI, true);
1288+
else
1289+
{
1290+
CommandCounterIncrement();
1291+
PortalStart(portal, paramLI, false);
1292+
}
12971293

12981294
Assert(portal->strategy != PORTAL_MULTI_QUERY);
12991295

src/backend/tcop/postgres.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -943,10 +943,6 @@ exec_simple_query(const char *query_string)
943943

944944
plantree_list = pg_plan_queries(querytree_list, 0, NULL);
945945

946-
/* Done with the snapshot used for parsing/planning */
947-
if (snapshot_set)
948-
PopActiveSnapshot();
949-
950946
/* If we got a cancel signal in analysis or planning, quit */
951947
CHECK_FOR_INTERRUPTS();
952948

@@ -971,9 +967,19 @@ exec_simple_query(const char *query_string)
971967
NULL);
972968

973969
/*
974-
* Start the portal. No parameters here.
970+
* Start the portal.
971+
*
972+
* If we took a snapshot for parsing/planning, the portal may be
973+
* able to reuse it for the execution phase. Currently, this will only
974+
* happen in PORTAL_ONE_SELECT mode. But even if PortalStart doesn't
975+
* end up being able to do this, keeping the parse/plan snapshot around
976+
* until after we start the portal doesn't cost much.
975977
*/
976-
PortalStart(portal, NULL, InvalidSnapshot);
978+
PortalStart(portal, NULL, snapshot_set);
979+
980+
/* Done with the snapshot used for parsing/planning */
981+
if (snapshot_set)
982+
PopActiveSnapshot();
977983

978984
/*
979985
* Select the appropriate output format: text unless we are doing a
@@ -1696,14 +1702,18 @@ exec_bind_message(StringInfo input_message)
16961702
cplan->stmt_list,
16971703
cplan);
16981704

1699-
/* Done with the snapshot used for parameter I/O and parsing/planning */
1700-
if (snapshot_set)
1701-
PopActiveSnapshot();
1702-
17031705
/*
17041706
* And we're ready to start portal execution.
1707+
*
1708+
* If we took a snapshot for parsing/planning, we'll try to reuse it
1709+
* for query execution (currently, reuse will only occur if
1710+
* PORTAL_ONE_SELECT mode is chosen).
17051711
*/
1706-
PortalStart(portal, params, InvalidSnapshot);
1712+
PortalStart(portal, params, snapshot_set);
1713+
1714+
/* Done with the snapshot used for parameter I/O and parsing/planning */
1715+
if (snapshot_set)
1716+
PopActiveSnapshot();
17071717

17081718
/*
17091719
* Apply the result format requests to the portal.

src/backend/tcop/pquery.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -446,16 +446,17 @@ FetchStatementTargetList(Node *stmt)
446446
* the query, they must be passed in here (caller is responsible for
447447
* giving them appropriate lifetime).
448448
*
449-
* The caller can optionally pass a snapshot to be used; pass InvalidSnapshot
450-
* for the normal behavior of setting a new snapshot. This parameter is
451-
* presently ignored for non-PORTAL_ONE_SELECT portals (it's only intended
452-
* to be used for cursors).
449+
* The use_active_snapshot parameter is currently used only for
450+
* PORTAL_ONE_SELECT portals. If it is true, the active snapshot will
451+
* be used when starting up the executor; if false, a new snapshot will
452+
* be taken. This is used both for cursors and to avoid taking an entirely
453+
* new snapshot when it isn't necessary.
453454
*
454455
* On return, portal is ready to accept PortalRun() calls, and the result
455456
* tupdesc (if any) is known.
456457
*/
457458
void
458-
PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot)
459+
PortalStart(Portal portal, ParamListInfo params, bool use_active_snapshot)
459460
{
460461
Portal saveActivePortal;
461462
ResourceOwner saveResourceOwner;
@@ -497,8 +498,8 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot)
497498
case PORTAL_ONE_SELECT:
498499

499500
/* Must set snapshot before starting executor. */
500-
if (snapshot)
501-
PushActiveSnapshot(snapshot);
501+
if (use_active_snapshot)
502+
PushActiveSnapshot(GetActiveSnapshot());
502503
else
503504
PushActiveSnapshot(GetTransactionSnapshot());
504505

src/include/tcop/pquery.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ extern List *FetchPortalTargetList(Portal portal);
2828
extern List *FetchStatementTargetList(Node *stmt);
2929

3030
extern void PortalStart(Portal portal, ParamListInfo params,
31-
Snapshot snapshot);
31+
bool use_active_snapshot);
3232

3333
extern void PortalSetResultFormat(Portal portal, int nFormats,
3434
int16 *formats);

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