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)
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