Skip to content

Commit 163ab48

Browse files
committed
Added tempbuffers patch. by A Lubennicova. Resolved conflict with PTRACK. See PGPRO-82
1 parent 9b79234 commit 163ab48

File tree

12 files changed

+318
-8
lines changed

12 files changed

+318
-8
lines changed

src/backend/catalog/namespace.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#include "utils/lsyscache.h"
5757
#include "utils/memutils.h"
5858
#include "utils/syscache.h"
59+
#include "storage/bufmgr.h"
5960

6061

6162
/*
@@ -3879,6 +3880,7 @@ RemoveTempRelations(Oid tempNamespaceId)
38793880
object.objectId = tempNamespaceId;
38803881
object.objectSubId = 0;
38813882

3883+
drop_temptableinfo_hashtable();
38823884
deleteWhatDependsOn(&object, false);
38833885
}
38843886

src/backend/catalog/storage.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ RelationDropStorage(Relation rel)
156156
pending->next = pendingDeletes;
157157
pendingDeletes = pending;
158158

159+
/* Delete cache entry from tempTableHashTab for this rel */
160+
if (rel->rd_rel->relkind == RELKIND_RELATION
161+
&& rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
162+
delete_temptableinfo_from_hashtable(rel->rd_node);
159163
/*
160164
* NOTE: if the relation was created in this transaction, it will now be
161165
* present in the pending-delete list twice, once with atCommit true and
@@ -239,6 +243,7 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
239243
rel->rd_smgr->smgr_fsm_nblocks = InvalidBlockNumber;
240244
rel->rd_smgr->smgr_vm_nblocks = InvalidBlockNumber;
241245
rel->rd_smgr->smgr_ptrack_nblocks = InvalidBlockNumber;
246+
rel->rd_smgr->smgr_main_nblocks = InvalidBlockNumber;
242247

243248
/* Truncate the FSM first if it exists */
244249
fsm = smgrexists(rel->rd_smgr, FSM_FORKNUM);
@@ -250,6 +255,16 @@ RelationTruncate(Relation rel, BlockNumber nblocks)
250255
if (vm)
251256
visibilitymap_truncate(rel, nblocks);
252257

258+
/*
259+
* Update cached number of blocks of temp relation,
260+
* but don't delete the entry from tempTableHashTab
261+
*/
262+
if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP
263+
&& rel->rd_rel->relkind == RELKIND_RELATION)
264+
{
265+
insert_temptableinfo_hashtable(rel->rd_node, 0);
266+
}
267+
253268
/*
254269
* We WAL-log the truncation before actually truncating, which means
255270
* trouble if the truncation fails. If we then crash, the WAL replay

src/backend/commands/cluster.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,18 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
10801080
/* Write out any remaining tuples, and fsync if needed */
10811081
end_heap_rewrite(rwstate);
10821082

1083+
/*
1084+
* Create new entry for temptable to track number of blocks
1085+
* in the new relation
1086+
*/
1087+
if (NewHeap->rd_rel->relpersistence == RELPERSISTENCE_TEMP
1088+
&& NewHeap->rd_rel->relkind == RELKIND_RELATION)
1089+
{
1090+
RelationOpenSmgr(NewHeap);
1091+
insert_temptableinfo_hashtable(NewHeap->rd_node,
1092+
smgrnblocks(NewHeap->rd_smgr, MAIN_FORKNUM));
1093+
}
1094+
10831095
/* Reset rd_toastoid just to be tidy --- it shouldn't be looked at again */
10841096
NewHeap->rd_toastoid = InvalidOid;
10851097

@@ -1578,7 +1590,6 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
15781590
* depends on it, so DROP_RESTRICT should be OK.
15791591
*/
15801592
performDeletion(&object, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
1581-
15821593
/* performDeletion does CommandCounterIncrement at end */
15831594

15841595
/*

src/backend/storage/buffer/bufmgr.c

Lines changed: 198 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ ForgetPrivateRefCountEntry(PrivateRefCountEntry *ref)
428428
)
429429

430430

431-
static Buffer ReadBuffer_common(SMgrRelation reln, char relpersistence,
431+
static Buffer ReadBuffer_common(SMgrRelation reln, char relpersistence, char relkind,
432432
ForkNumber forkNum, BlockNumber blockNum,
433433
ReadBufferMode mode, BufferAccessStrategy strategy,
434434
bool *hit);
@@ -458,6 +458,95 @@ static int buffertag_comparator(const void *p1, const void *p2);
458458
static int ckpt_buforder_comparator(const void *pa, const void *pb);
459459
static int ts_ckpt_progress_comparator(Datum a, Datum b, void *arg);
460460

461+
/* ----------------------------
462+
* TODO Replace it somewhere. BEGIN.
463+
* ----------------------------
464+
*/
465+
466+
typedef struct TempTableInfoData
467+
{
468+
RelFileNode rnode; /* relfilenode of this temp table (hash key) */
469+
BlockNumber main_nblocks; /* number of blocks in the rel */
470+
} TempTableInfoData;
471+
472+
typedef TempTableInfoData *TempTableInfo;
473+
474+
static HTAB *tempTableHashTab = NULL; /* hash table for tracking temp table's length */
475+
476+
/*
477+
* Creates the hash table for storing the actual length of temp tables
478+
*/
479+
static void
480+
create_temptableinfo_hashtable(void)
481+
{
482+
HASHCTL ctl;
483+
484+
memset(&ctl, 0, sizeof(ctl));
485+
ctl.keysize = sizeof(RelFileNode);
486+
ctl.entrysize = sizeof(TempTableInfoData);
487+
488+
tempTableHashTab = hash_create("Temp table's lengts", 16, &ctl,
489+
HASH_ELEM | HASH_BLOBS);
490+
}
491+
492+
void
493+
drop_temptableinfo_hashtable(void)
494+
{
495+
if (tempTableHashTab)
496+
{
497+
hash_destroy(tempTableHashTab);
498+
tempTableHashTab = NULL;
499+
}
500+
}
501+
502+
void
503+
delete_temptableinfo_from_hashtable(RelFileNode rnode)
504+
{
505+
elog(DEBUG1, "delete entry from tempTableHashTab");
506+
507+
if (tempTableHashTab == NULL)
508+
return;
509+
510+
if (hash_search(tempTableHashTab,
511+
(void *) &rnode,
512+
HASH_REMOVE, NULL) == NULL)
513+
elog(DEBUG1, "tempTableHashTab has no entry to delete");
514+
}
515+
516+
void
517+
insert_temptableinfo_hashtable(RelFileNode rnode, BlockNumber nblocks)
518+
{
519+
TempTableInfo tti;
520+
bool ttiIsFound;
521+
elog(DEBUG1, "insert entry to tempTableHashTab, nblocks %u", nblocks);
522+
elog(DEBUG1, "insert entry. spcNode %u, dbNode %u, relNode %u",rnode.spcNode, rnode.dbNode, rnode.relNode);
523+
524+
/* hash table must already exist, when we are rewriting temp rel */
525+
if (tempTableHashTab == NULL)
526+
{
527+
//TODO add some check here.
528+
return;
529+
}
530+
/* Create a hash table entry for this temp table */
531+
tti = (TempTableInfo) hash_search(tempTableHashTab, &rnode,
532+
HASH_ENTER, &ttiIsFound);
533+
534+
if (!ttiIsFound)
535+
{
536+
elog(DEBUG1, "tempTableHashTab entry is not found");
537+
}
538+
else
539+
{
540+
elog(DEBUG1, "tempTableHashTab entry is found. main_nblocks %u, nblocks %u", tti->main_nblocks, nblocks);
541+
}
542+
tti->main_nblocks = nblocks;
543+
}
544+
545+
/* ----------------------------
546+
* TODO Replace it somewhere. END.
547+
* ----------------------------
548+
*/
549+
461550

462551
/*
463552
* ComputeIoConcurrency -- get the number of pages to prefetch for a given
@@ -662,6 +751,7 @@ ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum,
662751
*/
663752
pgstat_count_buffer_read(reln);
664753
buf = ReadBuffer_common(reln->rd_smgr, reln->rd_rel->relpersistence,
754+
reln->rd_rel->relkind,
665755
forkNum, blockNum, mode, strategy, &hit);
666756
if (hit)
667757
pgstat_count_buffer_hit(reln);
@@ -689,7 +779,7 @@ ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum,
689779

690780
Assert(InRecovery);
691781

692-
return ReadBuffer_common(smgr, RELPERSISTENCE_PERMANENT, forkNum, blockNum,
782+
return ReadBuffer_common(smgr, RELPERSISTENCE_PERMANENT, RELKIND_UNKNOWN, forkNum, blockNum,
693783
mode, strategy, &hit);
694784
}
695785

@@ -711,15 +801,17 @@ ReadBufferWithoutRelcache2(SMgrRelation smgr, ForkNumber forkNum,
711801
* *hit is set to true if the request was satisfied from shared buffer cache.
712802
*/
713803
static Buffer
714-
ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
715-
BlockNumber blockNum, ReadBufferMode mode,
716-
BufferAccessStrategy strategy, bool *hit)
804+
ReadBuffer_common(SMgrRelation smgr, char relpersistence, char relkind,
805+
ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode,
806+
BufferAccessStrategy strategy, bool* hit)
717807
{
718808
BufferDesc *bufHdr;
719809
Block bufBlock;
720810
bool found;
721811
bool isExtend;
722812
bool isLocalBuf = SmgrIsTemp(smgr);
813+
bool isTempTableMainFork = false;
814+
TempTableInfo tti;
723815

724816
*hit = false;
725817

@@ -736,12 +828,70 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
736828
isExtend);
737829

738830
/* Substitute proper block number if caller asked for P_NEW */
831+
832+
/*
833+
* It's unnecessary to create a physical file for a local temp
834+
* relation when all buffers can be kept in memory.
835+
* Track actual number of blocks in tempTableHashTab and don't
836+
* use smgrnblocks to compute it.
837+
* Here we do all the work needed for cache initialization.
838+
*/
839+
if (isLocalBuf
840+
&& relkind == RELKIND_RELATION
841+
&& forkNum == MAIN_FORKNUM)
842+
{
843+
bool ttiIsFound;
844+
RelFileNode rnode = smgr->smgr_rnode.node;
845+
846+
elog(DEBUG1, "ReadBuffer_common. spcNode %u, dbNode %u, relNode %u",rnode.spcNode, rnode.dbNode, rnode.relNode);
847+
/* use the flag instead of "if" constructions like above */
848+
isTempTableMainFork = true;
849+
850+
/* Create hash table if it's the first call */
851+
if (tempTableHashTab == NULL)
852+
{
853+
create_temptableinfo_hashtable();
854+
elog(DEBUG1, "tempTableHashTab is created");
855+
}
856+
/* Find or create a hash table entry for this temp table */
857+
tti = (TempTableInfo) hash_search(tempTableHashTab, &rnode,
858+
HASH_ENTER, &ttiIsFound);
859+
860+
/*
861+
* If it's the first time we're going to extend rel,
862+
* fill the cache entry with number of blocks = 0
863+
*/
864+
if (!ttiIsFound)
865+
{
866+
elog(DEBUG1, "tempTableHashTab entry is not found");
867+
/* tti->rnode already filled in */
868+
tti->main_nblocks = 0;
869+
}
870+
else
871+
{
872+
elog(DEBUG1, "tempTableHashTab is found. nblocks %u",tti->main_nblocks);
873+
}
874+
875+
/* And finally fill up the smgr cache value */
876+
smgr->smgr_main_nblocks = tti->main_nblocks;
877+
elog(DEBUG1, "We're done with a cache entry. smgr->smgr_main_nblocks %u tti->main_nblocks %u",
878+
smgr->smgr_main_nblocks, tti->main_nblocks);
879+
}
880+
739881
if (isExtend)
740-
blockNum = smgrnblocks(smgr, forkNum);
882+
{
883+
if (isTempTableMainFork)
884+
blockNum = smgr->smgr_main_nblocks;
885+
else
886+
blockNum = smgrnblocks(smgr, forkNum);
887+
888+
elog(DEBUG1, "isExtend. blockNum %u smgr->smgr_main_nblocks %u", blockNum, smgr->smgr_main_nblocks);
889+
}
741890

742891
if (isLocalBuf)
743892
{
744893
bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
894+
745895
if (found)
746896
pgBufferUsage.local_blks_hit++;
747897
else
@@ -873,7 +1023,23 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
8731023
/* new buffers are zero-filled */
8741024
MemSet((char *) bufBlock, 0, BLCKSZ);
8751025
/* don't set checksum for all-zero page */
876-
smgrextend(smgr, forkNum, blockNum, (char *) bufBlock, false);
1026+
1027+
1028+
/* Do not extend physical file for temp tables while table fits
1029+
* into temp_buffers cache. We'll do it on demand, when buffer
1030+
* will be flushed out to disk.
1031+
* NOTE Currently works only for plain tables.
1032+
*/
1033+
if (isTempTableMainFork)
1034+
{
1035+
smgr->smgr_main_nblocks++;
1036+
tti->main_nblocks++;
1037+
}
1038+
else
1039+
smgrextend(smgr, forkNum, blockNum, (char *) bufBlock, false);
1040+
1041+
elog(DEBUG1, "isExtend 2. relnode %u smgr->smgr_main_nblocks %u",
1042+
smgr->smgr_rnode.node.relNode, smgr->smgr_main_nblocks);
8771043

8781044
/*
8791045
* NB: we're *not* doing a ScheduleBufferTagForWriteback here;
@@ -2784,6 +2950,31 @@ RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
27842950
/* Open it at the smgr level if not already done */
27852951
RelationOpenSmgr(relation);
27862952

2953+
/* Handle temp tables separately */
2954+
if (SmgrIsTemp(relation->rd_smgr)
2955+
&& forkNum == MAIN_FORKNUM
2956+
&& relation->rd_rel->relkind == RELKIND_RELATION)
2957+
{
2958+
TempTableInfo tti;
2959+
bool ttiIsFound;
2960+
RelFileNode rnode = relation->rd_smgr->smgr_rnode.node;
2961+
2962+
/* If we have no hash table, the relation is definitely new and empty. */
2963+
if (tempTableHashTab == NULL)
2964+
return 0;
2965+
2966+
tti = (TempTableInfo) hash_search(tempTableHashTab, &rnode,
2967+
HASH_FIND, &ttiIsFound);
2968+
if (!ttiIsFound)
2969+
{
2970+
elog(DEBUG1, "No cache entry for this temp relation");
2971+
// /* It's essential to fill the entry here */
2972+
// tti->main_nblocks = 0;
2973+
return 0;
2974+
}
2975+
else
2976+
return tti->main_nblocks;
2977+
}
27872978
return smgrnblocks(relation->rd_smgr, forkNum);
27882979
}
27892980

0 commit comments

Comments
 (0)