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

Commitafc3f55

Browse files
author
Maksim Milyutin
committed
Apply patches to optimize partition pruning
1 parent0c39d10 commitafc3f55

File tree

2 files changed

+138
-60
lines changed

2 files changed

+138
-60
lines changed

‎src/backend/catalog/pg_inherits.c

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,19 @@
2828
#include"parser/parse_type.h"
2929
#include"storage/lmgr.h"
3030
#include"utils/fmgroids.h"
31+
#include"utils/memutils.h"
3132
#include"utils/syscache.h"
3233
#include"utils/tqual.h"
3334

35+
/*
36+
* Entry of a hash table used in find_all_inheritors. See below.
37+
*/
38+
typedefstructSeenRelsEntry
39+
{
40+
Oidrel_id;/* relation oid */
41+
ListCell*numparents_cell;/* corresponding list cell */
42+
}SeenRelsEntry;
43+
3444
staticintoid_cmp(constvoid*p1,constvoid*p2);
3545

3646

@@ -158,10 +168,33 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
158168
List*
159169
find_all_inheritors(OidparentrelId,LOCKMODElockmode,List**numparents)
160170
{
171+
/* hash table for O(1) rel_oid -> rel_numparents cell lookup */
172+
HTAB*seen_rels;
173+
HASHCTLctl;
174+
MemoryContextnew_ctx;
161175
List*rels_list,
162176
*rel_numparents;
163177
ListCell*l;
164178

179+
/*
180+
* We need a separate memory context for a hash table. This is because
181+
* hash table is used only in this procedure. To free a memory we need to
182+
* call hash_destroy which is just a wrapper around MemoryContextDelete.
183+
*/
184+
new_ctx=AllocSetContextCreate(CurrentMemoryContext,
185+
"FindAllInheritorsSeenRelsContext",
186+
ALLOCSET_DEFAULT_SIZES);
187+
188+
memset(&ctl,0,sizeof(ctl));
189+
ctl.keysize=sizeof(Oid);
190+
ctl.entrysize=sizeof(SeenRelsEntry);
191+
ctl.hcxt=new_ctx;
192+
193+
seen_rels=hash_create(
194+
"find_all_inheritors temporary table",
195+
32,/* start small and extend */
196+
&ctl,HASH_ELEM |HASH_BLOBS |HASH_CONTEXT);
197+
165198
/*
166199
* We build a list starting with the given rel and adding all direct and
167200
* indirect children. We can use a single list as both the record of
@@ -191,26 +224,21 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
191224
foreach(lc,currentchildren)
192225
{
193226
Oidchild_oid=lfirst_oid(lc);
194-
boolfound= false;
195-
ListCell*lo;
196-
ListCell*li;
227+
boolfound;
228+
SeenRelsEntry*hash_entry;
197229

198-
/* if the rel is already there, bump number-of-parents counter */
199-
forboth(lo,rels_list,li,rel_numparents)
230+
hash_entry=hash_search(seen_rels,&child_oid,HASH_ENTER,&found);
231+
if (found)
200232
{
201-
if (lfirst_oid(lo)==child_oid)
202-
{
203-
lfirst_int(li)++;
204-
found= true;
205-
break;
206-
}
233+
/* if the rel is already there, bump number-of-parents counter */
234+
lfirst_int(hash_entry->numparents_cell)++;
207235
}
208-
209-
/* if it's not there, add it. expect 1 parent, initially. */
210-
if (!found)
236+
else
211237
{
238+
/* if it's not there, add it. expect 1 parent, initially. */
212239
rels_list=lappend_oid(rels_list,child_oid);
213240
rel_numparents=lappend_int(rel_numparents,1);
241+
hash_entry->numparents_cell=rel_numparents->tail;
214242
}
215243
}
216244
}
@@ -219,6 +247,9 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
219247
*numparents=rel_numparents;
220248
else
221249
list_free(rel_numparents);
250+
251+
hash_destroy(seen_rels);
252+
222253
returnrels_list;
223254
}
224255

‎src/backend/postmaster/pgstat.c

Lines changed: 93 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,20 @@ typedef struct TabStatusArray
160160

161161
staticTabStatusArray*pgStatTabList=NULL;
162162

163+
/*
164+
* pgStatTabHash entry
165+
*/
166+
typedefstructTabStatHashEntry
167+
{
168+
Oidt_id;
169+
PgStat_TableStatus*tsa_entry;
170+
}TabStatHashEntry;
171+
172+
/*
173+
* Hash table for O(1) t_id -> tsa_entry lookup
174+
*/
175+
staticHTAB*pgStatTabHash=NULL;
176+
163177
/*
164178
* Backends store per-function info that's waiting to be sent to the collector
165179
* in this hash table (indexed by function OID).
@@ -817,6 +831,14 @@ pgstat_report_stat(bool force)
817831
tsa->tsa_used=0;
818832
}
819833

834+
/*
835+
* pgStatTabHash is outdated on this point so we have to clean it,
836+
* hash_destroy() will remove hash memory context, allocated in
837+
* make_sure_stat_tab_initialized()
838+
*/
839+
hash_destroy(pgStatTabHash);
840+
pgStatTabHash=NULL;
841+
820842
/*
821843
* Send partial messages. Make sure that any pending xact commit/abort
822844
* gets counted, even if there are no table stats to send.
@@ -1661,60 +1683,88 @@ pgstat_initstats(Relation rel)
16611683
rel->pgstat_info=get_tabstat_entry(rel_id,rel->rd_rel->relisshared);
16621684
}
16631685

1686+
/*
1687+
* Make sure pgStatTabList and pgStatTabHash are initialized.
1688+
*/
1689+
staticvoid
1690+
make_sure_stat_tab_initialized()
1691+
{
1692+
HASHCTLctl;
1693+
MemoryContextnew_ctx;
1694+
1695+
if(!pgStatTabList)
1696+
{
1697+
/* This is first time procedure is called */
1698+
pgStatTabList= (TabStatusArray*)MemoryContextAllocZero(TopMemoryContext,
1699+
sizeof(TabStatusArray));
1700+
}
1701+
1702+
if(pgStatTabHash)
1703+
return;
1704+
1705+
/* Hash table was freed or never existed. */
1706+
1707+
new_ctx=AllocSetContextCreate(
1708+
TopMemoryContext,
1709+
"PGStatLookupHashTableContext",
1710+
ALLOCSET_DEFAULT_SIZES);
1711+
1712+
memset(&ctl,0,sizeof(ctl));
1713+
ctl.keysize=sizeof(Oid);
1714+
ctl.entrysize=sizeof(TabStatHashEntry);
1715+
ctl.hcxt=new_ctx;
1716+
1717+
pgStatTabHash=hash_create("pgstat t_id to tsa_entry lookup hash table",
1718+
TABSTAT_QUANTUM,&ctl,HASH_ELEM |HASH_BLOBS |HASH_CONTEXT);
1719+
}
1720+
16641721
/*
16651722
* get_tabstat_entry - find or create a PgStat_TableStatus entry for rel
16661723
*/
16671724
staticPgStat_TableStatus*
16681725
get_tabstat_entry(Oidrel_id,boolisshared)
16691726
{
1727+
TabStatHashEntry*hash_entry;
16701728
PgStat_TableStatus*entry;
16711729
TabStatusArray*tsa;
1672-
TabStatusArray*prev_tsa;
1673-
inti;
1730+
boolfound;
1731+
1732+
make_sure_stat_tab_initialized();
16741733

16751734
/*
1676-
*Search the already-used tabstat slots for this relation.
1735+
*Find an entry or create a new one.
16771736
*/
1678-
prev_tsa=NULL;
1679-
for (tsa=pgStatTabList;tsa!=NULL;prev_tsa=tsa,tsa=tsa->tsa_next)
1737+
hash_entry=hash_search(pgStatTabHash,&rel_id,HASH_ENTER,&found);
1738+
if(found)
1739+
returnhash_entry->tsa_entry;
1740+
1741+
/*
1742+
* `hash_entry` was just created and now we have to fill it.
1743+
* First make sure there is a free space in a last element of pgStatTabList.
1744+
*/
1745+
tsa=pgStatTabList;
1746+
while(tsa->tsa_used==TABSTAT_QUANTUM)
16801747
{
1681-
for (i=0;i<tsa->tsa_used;i++)
1748+
if(tsa->tsa_next==NULL)
16821749
{
1683-
entry=&tsa->tsa_entries[i];
1684-
if (entry->t_id==rel_id)
1685-
returnentry;
1750+
tsa->tsa_next= (TabStatusArray*)MemoryContextAllocZero(TopMemoryContext,
1751+
sizeof(TabStatusArray));
16861752
}
16871753

1688-
if (tsa->tsa_used<TABSTAT_QUANTUM)
1689-
{
1690-
/*
1691-
* It must not be present, but we found a free slot instead. Fine,
1692-
* let's use this one. We assume the entry was already zeroed,
1693-
* either at creation or after last use.
1694-
*/
1695-
entry=&tsa->tsa_entries[tsa->tsa_used++];
1696-
entry->t_id=rel_id;
1697-
entry->t_shared=isshared;
1698-
returnentry;
1699-
}
1754+
tsa=tsa->tsa_next;
17001755
}
17011756

17021757
/*
1703-
* We ran out of tabstat slots, so allocate more. Be sure they're zeroed.
1704-
*/
1705-
tsa= (TabStatusArray*)MemoryContextAllocZero(TopMemoryContext,
1706-
sizeof(TabStatusArray));
1707-
if (prev_tsa)
1708-
prev_tsa->tsa_next=tsa;
1709-
else
1710-
pgStatTabList=tsa;
1711-
1712-
/*
1713-
* Use the first entry of the new TabStatusArray.
1758+
* Add an entry.
17141759
*/
17151760
entry=&tsa->tsa_entries[tsa->tsa_used++];
17161761
entry->t_id=rel_id;
17171762
entry->t_shared=isshared;
1763+
1764+
/*
1765+
* Add a corresponding entry to pgStatTabHash.
1766+
*/
1767+
hash_entry->tsa_entry=entry;
17181768
returnentry;
17191769
}
17201770

@@ -1726,22 +1776,19 @@ get_tabstat_entry(Oid rel_id, bool isshared)
17261776
PgStat_TableStatus*
17271777
find_tabstat_entry(Oidrel_id)
17281778
{
1729-
PgStat_TableStatus*entry;
1730-
TabStatusArray*tsa;
1731-
inti;
1779+
TabStatHashEntry*hash_entry;
17321780

1733-
for (tsa=pgStatTabList;tsa!=NULL;tsa=tsa->tsa_next)
1734-
{
1735-
for (i=0;i<tsa->tsa_used;i++)
1736-
{
1737-
entry=&tsa->tsa_entries[i];
1738-
if (entry->t_id==rel_id)
1739-
returnentry;
1740-
}
1741-
}
1781+
/*
1782+
* There are no entries at all.
1783+
*/
1784+
if(!pgStatTabHash)
1785+
returnNULL;
17421786

1743-
/* Not present */
1744-
returnNULL;
1787+
hash_entry=hash_search(pgStatTabHash,&rel_id,HASH_FIND,NULL);
1788+
if(!hash_entry)
1789+
returnNULL;
1790+
1791+
returnhash_entry->tsa_entry;
17451792
}
17461793

17471794
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp