Skip to content

Commit 8720a15

Browse files
committed
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
1 parent a858be1 commit 8720a15

File tree

1 file changed

+49
-4
lines changed

1 file changed

+49
-4
lines changed

src/backend/storage/buffer/bufmgr.c

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "storage/ipc.h"
5555
#include "storage/lmgr.h"
5656
#include "storage/proc.h"
57+
#include "storage/read_stream.h"
5758
#include "storage/smgr.h"
5859
#include "storage/standby.h"
5960
#include "utils/memdebug.h"
@@ -135,6 +136,33 @@ typedef struct SMgrSortArray
135136
SMgrRelation srel;
136137
} SMgrSortArray;
137138

139+
/*
140+
* Helper struct for read stream object used in
141+
* RelationCopyStorageUsingBuffer() function.
142+
*/
143+
struct copy_storage_using_buffer_read_stream_private
144+
{
145+
BlockNumber blocknum;
146+
BlockNumber last_block;
147+
};
148+
149+
/*
150+
* Callback function to get next block for read stream object used in
151+
* RelationCopyStorageUsingBuffer() function.
152+
*/
153+
static BlockNumber
154+
copy_storage_using_buffer_read_stream_next_block(ReadStream *stream,
155+
void *callback_private_data,
156+
void *per_buffer_data)
157+
{
158+
struct copy_storage_using_buffer_read_stream_private *p = callback_private_data;
159+
160+
if (p->blocknum < p->last_block)
161+
return p->blocknum++;
162+
163+
return InvalidBlockNumber;
164+
}
165+
138166
/* GUC variables */
139167
bool zero_damaged_pages = false;
140168
int bgwriter_lru_maxpages = 100;
@@ -4685,6 +4713,9 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
46854713
PGIOAlignedBlock buf;
46864714
BufferAccessStrategy bstrategy_src;
46874715
BufferAccessStrategy bstrategy_dst;
4716+
struct copy_storage_using_buffer_read_stream_private p;
4717+
ReadStream *src_stream;
4718+
SMgrRelation src_smgr;
46884719

46894720
/*
46904721
* In general, we want to write WAL whenever wal_level > 'minimal', but we
@@ -4713,19 +4744,31 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
47134744
bstrategy_src = GetAccessStrategy(BAS_BULKREAD);
47144745
bstrategy_dst = GetAccessStrategy(BAS_BULKWRITE);
47154746

4747+
/* Initalize streaming read */
4748+
p.blocknum = 0;
4749+
p.last_block = nblocks;
4750+
src_smgr = smgropen(srclocator, INVALID_PROC_NUMBER);
4751+
src_stream = read_stream_begin_smgr_relation(READ_STREAM_FULL,
4752+
bstrategy_src,
4753+
src_smgr,
4754+
permanent ? RELPERSISTENCE_PERMANENT : RELPERSISTENCE_UNLOGGED,
4755+
forkNum,
4756+
copy_storage_using_buffer_read_stream_next_block,
4757+
&p,
4758+
0);
4759+
47164760
/* Iterate over each block of the source relation file. */
47174761
for (blkno = 0; blkno < nblocks; blkno++)
47184762
{
47194763
CHECK_FOR_INTERRUPTS();
47204764

47214765
/* Read block from source relation. */
4722-
srcBuf = ReadBufferWithoutRelcache(srclocator, forkNum, blkno,
4723-
RBM_NORMAL, bstrategy_src,
4724-
permanent);
4766+
srcBuf = read_stream_next_buffer(src_stream, NULL);
47254767
LockBuffer(srcBuf, BUFFER_LOCK_SHARE);
47264768
srcPage = BufferGetPage(srcBuf);
47274769

4728-
dstBuf = ReadBufferWithoutRelcache(dstlocator, forkNum, blkno,
4770+
dstBuf = ReadBufferWithoutRelcache(dstlocator, forkNum,
4771+
BufferGetBlockNumber(srcBuf),
47294772
RBM_ZERO_AND_LOCK, bstrategy_dst,
47304773
permanent);
47314774
dstPage = BufferGetPage(dstBuf);
@@ -4745,6 +4788,8 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
47454788
UnlockReleaseBuffer(dstBuf);
47464789
UnlockReleaseBuffer(srcBuf);
47474790
}
4791+
Assert(read_stream_next_buffer(src_stream, NULL) == InvalidBuffer);
4792+
read_stream_end(src_stream);
47484793

47494794
FreeAccessStrategy(bstrategy_src);
47504795
FreeAccessStrategy(bstrategy_dst);

0 commit comments

Comments
 (0)