Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit21025d4

Browse files
committed
Use a hash table to store current sequence values.
This speeds up nextval() and currval(), when you touch a lot of differentsequences in the same backend.David Rowley
1 parent982b82d commit21025d4

File tree

1 file changed

+35
-36
lines changed

1 file changed

+35
-36
lines changed

‎src/backend/commands/sequence.c

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,10 @@ typedef struct sequence_magic
6060
* session. This is needed to hold onto nextval/currval state. (We can't
6161
* rely on the relcache, since it's only, well, a cache, and may decide to
6262
* discard entries.)
63-
*
64-
* XXX We use linear search to find pre-existing SeqTable entries.This is
65-
* good when only a small number of sequences are touched in a session, but
66-
* would suck with many different sequences. Perhaps use a hashtable someday.
6763
*/
6864
typedefstructSeqTableData
6965
{
70-
structSeqTableData*next;/* link to next SeqTable object */
71-
Oidrelid;/* pg_class OID of this sequence */
66+
Oidrelid;/* pg_class OID of this sequence (hash key) */
7267
Oidfilenode;/* last seen relfilenode of this sequence */
7368
LocalTransactionIdlxid;/* xact in which we last did a seq op */
7469
boollast_valid;/* do we have a valid "last" value? */
@@ -81,7 +76,7 @@ typedef struct SeqTableData
8176

8277
typedefSeqTableData*SeqTable;
8378

84-
staticSeqTableseqtab=NULL;/*Head of list of SeqTable items */
79+
staticHTAB*seqhashtab=NULL;/*hash table for SeqTable items */
8580

8681
/*
8782
* last_used_seq is updated by nextval() to point to the last used
@@ -92,6 +87,7 @@ static SeqTableData *last_used_seq = NULL;
9287
staticvoidfill_seq_with_data(Relationrel,HeapTupletuple);
9388
staticint64nextval_internal(Oidrelid);
9489
staticRelationopen_share_lock(SeqTableseq);
90+
staticvoidcreate_seq_hashtable(void);
9591
staticvoidinit_sequence(Oidrelid,SeqTable*p_elm,Relation*p_rel);
9692
staticForm_pg_sequenceread_seq_tuple(SeqTableelm,Relationrel,
9793
Buffer*buf,HeapTupleseqtuple);
@@ -998,6 +994,23 @@ open_share_lock(SeqTable seq)
998994
returnrelation_open(seq->relid,NoLock);
999995
}
1000996

997+
/*
998+
* Creates the hash table for storing sequence data
999+
*/
1000+
staticvoid
1001+
create_seq_hashtable(void)
1002+
{
1003+
HASHCTLctl;
1004+
1005+
memset(&ctl,0,sizeof(ctl));
1006+
ctl.keysize=sizeof(Oid);
1007+
ctl.entrysize=sizeof(SeqTableData);
1008+
ctl.hash=oid_hash;
1009+
1010+
seqhashtab=hash_create("Sequence values",16,&ctl,
1011+
HASH_ELEM |HASH_FUNCTION |HASH_CONTEXT);
1012+
}
1013+
10011014
/*
10021015
* Given a relation OID, open and lock the sequence. p_elm and p_rel are
10031016
* output parameters.
@@ -1007,39 +1020,28 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
10071020
{
10081021
SeqTableelm;
10091022
Relationseqrel;
1023+
boolfound;
10101024

1011-
/* Look to see if we already have a seqtable entry for relation */
1012-
for (elm=seqtab;elm!=NULL;elm=elm->next)
1013-
{
1014-
if (elm->relid==relid)
1015-
break;
1016-
}
1025+
if (seqhashtab==NULL)
1026+
create_seq_hashtable();
1027+
1028+
elm= (SeqTable)hash_search(seqhashtab,&relid,HASH_ENTER,&found);
10171029

10181030
/*
1019-
*Allocatenewseqtableentry ifwe didn't find one.
1031+
*Initalize thenewhash tableentry ifit did not exist already.
10201032
*
1021-
* NOTE: seqtable entries remain in the list for the life of a backend. If
1022-
* the sequence itself is deleted then the entry becomes wasted memory,
1023-
* but it's small enough that this should not matter.
1033+
* NOTE: seqtable entries are stored for the life of a backend (unless
1034+
* explictly discarded with DISCARD). If the sequence itself is deleted
1035+
* then the entry becomes wasted memory, but it's small enough that this
1036+
* should not matter.
10241037
*/
1025-
if (elm==NULL)
1038+
if (!found)
10261039
{
1027-
/*
1028-
* Time to make a new seqtable entry. These entries live as long as
1029-
* the backend does, so we use plain malloc for them.
1030-
*/
1031-
elm= (SeqTable)malloc(sizeof(SeqTableData));
1032-
if (elm==NULL)
1033-
ereport(ERROR,
1034-
(errcode(ERRCODE_OUT_OF_MEMORY),
1035-
errmsg("out of memory")));
1036-
elm->relid=relid;
1040+
/* relid already filled in */
10371041
elm->filenode=InvalidOid;
10381042
elm->lxid=InvalidLocalTransactionId;
10391043
elm->last_valid= false;
10401044
elm->last=elm->cached=elm->increment=0;
1041-
elm->next=seqtab;
1042-
seqtab=elm;
10431045
}
10441046

10451047
/*
@@ -1609,13 +1611,10 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
16091611
void
16101612
ResetSequenceCaches(void)
16111613
{
1612-
SeqTableData*next;
1613-
1614-
while (seqtab!=NULL)
1614+
if (seqhashtab)
16151615
{
1616-
next=seqtab->next;
1617-
free(seqtab);
1618-
seqtab=next;
1616+
hash_destroy(seqhashtab);
1617+
seqhashtab=NULL;
16191618
}
16201619

16211620
last_used_seq=NULL;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp