Use read streams in CREATE DATABASE when STRATEGY=WAL_LOG.

While this doesn't significantly change runtime now, it arranges for
STRATEGY=WAL_LOG to benefit automatically from future optimizations to
the read_stream subsystem.  For large tables in the template database,
this does read 16x as many bytes per system call.  Platforms with high
per-call overhead, if any, may see an immediate benefit.

Nazir Bilal Yavuz

Discussion: https://postgr.es/m/CAN55FZ0JKL6vk1xQp6rfOXiNFV1u1H0tJDPPGHWoiO3ea2Wc=A@mail.gmail.com
This commit is contained in:
Noah Misch 2024-07-20 04:22:12 -07:00
parent a858be17c3
commit 8720a15e9a
1 changed files with 49 additions and 4 deletions

View File

@ -54,6 +54,7 @@
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/read_stream.h"
#include "storage/smgr.h"
#include "storage/standby.h"
#include "utils/memdebug.h"
@ -135,6 +136,33 @@ typedef struct SMgrSortArray
SMgrRelation srel;
} SMgrSortArray;
/*
* Helper struct for read stream object used in
* RelationCopyStorageUsingBuffer() function.
*/
struct copy_storage_using_buffer_read_stream_private
{
BlockNumber blocknum;
BlockNumber last_block;
};
/*
* Callback function to get next block for read stream object used in
* RelationCopyStorageUsingBuffer() function.
*/
static BlockNumber
copy_storage_using_buffer_read_stream_next_block(ReadStream *stream,
void *callback_private_data,
void *per_buffer_data)
{
struct copy_storage_using_buffer_read_stream_private *p = callback_private_data;
if (p->blocknum < p->last_block)
return p->blocknum++;
return InvalidBlockNumber;
}
/* GUC variables */
bool zero_damaged_pages = false;
int bgwriter_lru_maxpages = 100;
@ -4685,6 +4713,9 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
PGIOAlignedBlock buf;
BufferAccessStrategy bstrategy_src;
BufferAccessStrategy bstrategy_dst;
struct copy_storage_using_buffer_read_stream_private p;
ReadStream *src_stream;
SMgrRelation src_smgr;
/*
* In general, we want to write WAL whenever wal_level > 'minimal', but we
@ -4713,19 +4744,31 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
bstrategy_src = GetAccessStrategy(BAS_BULKREAD);
bstrategy_dst = GetAccessStrategy(BAS_BULKWRITE);
/* Initalize streaming read */
p.blocknum = 0;
p.last_block = nblocks;
src_smgr = smgropen(srclocator, INVALID_PROC_NUMBER);
src_stream = read_stream_begin_smgr_relation(READ_STREAM_FULL,
bstrategy_src,
src_smgr,
permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
forkNum,
copy_storage_using_buffer_read_stream_next_block,
&p,
0);
/* Iterate over each block of the source relation file. */
for (blkno = 0; blkno < nblocks; blkno++)
{
CHECK_FOR_INTERRUPTS();
/* Read block from source relation. */
srcBuf = ReadBufferWithoutRelcache(srclocator, forkNum, blkno,
RBM_NORMAL, bstrategy_src,
permanent);
srcBuf = read_stream_next_buffer(src_stream, NULL);
LockBuffer(srcBuf, BUFFER_LOCK_SHARE);
srcPage = BufferGetPage(srcBuf);
dstBuf = ReadBufferWithoutRelcache(dstlocator, forkNum, blkno,
dstBuf = ReadBufferWithoutRelcache(dstlocator, forkNum,
BufferGetBlockNumber(srcBuf),
RBM_ZERO_AND_LOCK, bstrategy_dst,
permanent);
dstPage = BufferGetPage(dstBuf);
@ -4745,6 +4788,8 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
UnlockReleaseBuffer(dstBuf);
UnlockReleaseBuffer(srcBuf);
}
Assert(read_stream_next_buffer(src_stream, NULL) == InvalidBuffer);
read_stream_end(src_stream);
FreeAccessStrategy(bstrategy_src);
FreeAccessStrategy(bstrategy_dst);