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:
parent
a858be17c3
commit
8720a15e9a
@ -54,6 +54,7 @@
|
|||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
#include "storage/lmgr.h"
|
#include "storage/lmgr.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
|
#include "storage/read_stream.h"
|
||||||
#include "storage/smgr.h"
|
#include "storage/smgr.h"
|
||||||
#include "storage/standby.h"
|
#include "storage/standby.h"
|
||||||
#include "utils/memdebug.h"
|
#include "utils/memdebug.h"
|
||||||
@ -135,6 +136,33 @@ typedef struct SMgrSortArray
|
|||||||
SMgrRelation srel;
|
SMgrRelation srel;
|
||||||
} SMgrSortArray;
|
} 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 */
|
/* GUC variables */
|
||||||
bool zero_damaged_pages = false;
|
bool zero_damaged_pages = false;
|
||||||
int bgwriter_lru_maxpages = 100;
|
int bgwriter_lru_maxpages = 100;
|
||||||
@ -4685,6 +4713,9 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
|
|||||||
PGIOAlignedBlock buf;
|
PGIOAlignedBlock buf;
|
||||||
BufferAccessStrategy bstrategy_src;
|
BufferAccessStrategy bstrategy_src;
|
||||||
BufferAccessStrategy bstrategy_dst;
|
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
|
* 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_src = GetAccessStrategy(BAS_BULKREAD);
|
||||||
bstrategy_dst = GetAccessStrategy(BAS_BULKWRITE);
|
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. */
|
/* Iterate over each block of the source relation file. */
|
||||||
for (blkno = 0; blkno < nblocks; blkno++)
|
for (blkno = 0; blkno < nblocks; blkno++)
|
||||||
{
|
{
|
||||||
CHECK_FOR_INTERRUPTS();
|
CHECK_FOR_INTERRUPTS();
|
||||||
|
|
||||||
/* Read block from source relation. */
|
/* Read block from source relation. */
|
||||||
srcBuf = ReadBufferWithoutRelcache(srclocator, forkNum, blkno,
|
srcBuf = read_stream_next_buffer(src_stream, NULL);
|
||||||
RBM_NORMAL, bstrategy_src,
|
|
||||||
permanent);
|
|
||||||
LockBuffer(srcBuf, BUFFER_LOCK_SHARE);
|
LockBuffer(srcBuf, BUFFER_LOCK_SHARE);
|
||||||
srcPage = BufferGetPage(srcBuf);
|
srcPage = BufferGetPage(srcBuf);
|
||||||
|
|
||||||
dstBuf = ReadBufferWithoutRelcache(dstlocator, forkNum, blkno,
|
dstBuf = ReadBufferWithoutRelcache(dstlocator, forkNum,
|
||||||
|
BufferGetBlockNumber(srcBuf),
|
||||||
RBM_ZERO_AND_LOCK, bstrategy_dst,
|
RBM_ZERO_AND_LOCK, bstrategy_dst,
|
||||||
permanent);
|
permanent);
|
||||||
dstPage = BufferGetPage(dstBuf);
|
dstPage = BufferGetPage(dstBuf);
|
||||||
@ -4745,6 +4788,8 @@ RelationCopyStorageUsingBuffer(RelFileLocator srclocator,
|
|||||||
UnlockReleaseBuffer(dstBuf);
|
UnlockReleaseBuffer(dstBuf);
|
||||||
UnlockReleaseBuffer(srcBuf);
|
UnlockReleaseBuffer(srcBuf);
|
||||||
}
|
}
|
||||||
|
Assert(read_stream_next_buffer(src_stream, NULL) == InvalidBuffer);
|
||||||
|
read_stream_end(src_stream);
|
||||||
|
|
||||||
FreeAccessStrategy(bstrategy_src);
|
FreeAccessStrategy(bstrategy_src);
|
||||||
FreeAccessStrategy(bstrategy_dst);
|
FreeAccessStrategy(bstrategy_dst);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user