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

Commit6b013c1

Browse files
committed
Speedup an array selectivity estimation.
Cache statistics during an array selectivity estimation due to repetativeVar op Const estimations. Reduce cycles to detoast and unpack statistics,especially big ones like histogram or MCV arrays.Reuse memory allocated for array's element selectivity estimation.Remember, we have a community's patch & thread about selectivity memorycontext. But for now it is hard to say how quickly it can be pushed.So, use simple hack now. It saves almost 50% of allocated memory in the caselabelled as 'SHRDM-3141'.
1 parenta3699da commit6b013c1

File tree

3 files changed

+195
-37
lines changed

3 files changed

+195
-37
lines changed

‎src/backend/utils/adt/selfuncs.c

Lines changed: 49 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,6 +1930,8 @@ scalararraysel(PlannerInfo *root,
19301930
Datum*elem_values;
19311931
bool*elem_nulls;
19321932
inti;
1933+
List*args;
1934+
Const*c;
19331935

19341936
if (arrayisnull)/* qual can't succeed if null array */
19351937
return (Selectivity)0.0;
@@ -1957,48 +1959,56 @@ scalararraysel(PlannerInfo *root,
19571959
*/
19581960
s1=s1disjoint= (useOr ?0.0 :1.0);
19591961

1960-
for (i=0;i<num_elems;i++)
1961-
{
1962-
List*args;
1963-
Selectivitys2;
1962+
set_attstatsslot_cache_mode(true);
19641963

1965-
args=list_make2(leftop,
1966-
makeConst(nominal_element_type,
1967-
-1,
1968-
nominal_element_collation,
1969-
elmlen,
1970-
elem_values[i],
1971-
elem_nulls[i],
1972-
elmbyval));
1973-
if (is_join_clause)
1974-
s2=DatumGetFloat8(FunctionCall5Coll(&oprselproc,
1975-
clause->inputcollid,
1976-
PointerGetDatum(root),
1977-
ObjectIdGetDatum(operator),
1978-
PointerGetDatum(args),
1979-
Int16GetDatum(jointype),
1980-
PointerGetDatum(sjinfo)));
1981-
else
1982-
s2=DatumGetFloat8(FunctionCall4Coll(&oprselproc,
1983-
clause->inputcollid,
1984-
PointerGetDatum(root),
1985-
ObjectIdGetDatum(operator),
1986-
PointerGetDatum(args),
1987-
Int32GetDatum(varRelid)));
1964+
c=makeConst(nominal_element_type,-1,nominal_element_collation,
1965+
elmlen, (Datum)0, true,elmbyval);
1966+
args=list_make2(leftop,c);
19881967

1989-
if (useOr)
1990-
{
1991-
s1=s1+s2-s1*s2;
1992-
if (isEquality)
1993-
s1disjoint+=s2;
1994-
}
1995-
else
1968+
PG_TRY();
1969+
{
1970+
for (i=0;i<num_elems;i++)
19961971
{
1997-
s1=s1*s2;
1998-
if (isInequality)
1999-
s1disjoint+=s2-1.0;
1972+
Selectivitys2;
1973+
1974+
c->constvalue=elem_values[i];
1975+
c->constisnull=elem_nulls[i];
1976+
1977+
if (is_join_clause)
1978+
s2=DatumGetFloat8(FunctionCall5Coll(&oprselproc,
1979+
clause->inputcollid,
1980+
PointerGetDatum(root),
1981+
ObjectIdGetDatum(operator),
1982+
PointerGetDatum(args),
1983+
Int16GetDatum(jointype),
1984+
PointerGetDatum(sjinfo)));
1985+
else
1986+
s2=DatumGetFloat8(FunctionCall4Coll(&oprselproc,
1987+
clause->inputcollid,
1988+
PointerGetDatum(root),
1989+
ObjectIdGetDatum(operator),
1990+
PointerGetDatum(args),
1991+
Int32GetDatum(varRelid)));
1992+
1993+
if (useOr)
1994+
{
1995+
s1=s1+s2-s1*s2;
1996+
if (isEquality)
1997+
s1disjoint+=s2;
1998+
}
1999+
else
2000+
{
2001+
s1=s1*s2;
2002+
if (isInequality)
2003+
s1disjoint+=s2-1.0;
2004+
}
20002005
}
20012006
}
2007+
PG_FINALLY();
2008+
{
2009+
set_attstatsslot_cache_mode(false);
2010+
}
2011+
PG_END_TRY();
20022012

20032013
/* accept disjoint-probability estimate if in range */
20042014
if ((useOr ?isEquality :isInequality)&&
@@ -2053,6 +2063,8 @@ scalararraysel(PlannerInfo *root,
20532063
PointerGetDatum(args),
20542064
Int32GetDatum(varRelid)));
20552065

2066+
pfree(args);
2067+
20562068
if (useOr)
20572069
{
20582070
s1=s1+s2-s1*s2;

‎src/backend/utils/cache/lsyscache.c

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include"utils/builtins.h"
4545
#include"utils/catcache.h"
4646
#include"utils/datum.h"
47+
#include"utils/inval.h"
4748
#include"utils/fmgroids.h"
4849
#include"utils/lsyscache.h"
4950
#include"utils/syscache.h"
@@ -3180,6 +3181,137 @@ get_attavgwidth(Oid relid, AttrNumber attnum)
31803181
return0;
31813182
}
31823183

3184+
typedefstructAttStatSlotHashKey
3185+
{
3186+
Oidrelid;
3187+
intattnum;
3188+
intreqkind;
3189+
Oidreqop;
3190+
intflags;
3191+
}AttStatSlotHashKey;
3192+
3193+
typedefstructAttStatSlotHashEntry
3194+
{
3195+
AttStatSlotHashKeykey;
3196+
AttStatsSlotsslot;
3197+
}AttStatSlotHashEntry;
3198+
3199+
staticboolattstatsslot_needs_cache= false;
3200+
staticHTAB*slot_htab=NULL;
3201+
3202+
void
3203+
set_attstatsslot_cache_mode(boolneed_cache)
3204+
{
3205+
/* It should be a usage error or a bug */
3206+
Assert(!(need_cache&&attstatsslot_needs_cache));
3207+
3208+
if (!attstatsslot_needs_cache&& !need_cache)
3209+
/* Nothing to do */
3210+
return;
3211+
3212+
attstatsslot_needs_cache=need_cache;
3213+
3214+
if (!need_cache&&slot_htab!=NULL&&
3215+
hash_get_num_entries(slot_htab)>0)
3216+
{
3217+
HASH_SEQ_STATUShash_seq;
3218+
AttStatSlotHashEntry*entry;
3219+
3220+
/*
3221+
* It seems we have only few entries here. So, instead of removing the
3222+
* whole table, just remove entries one-by-one.
3223+
*/
3224+
3225+
hash_seq_init(&hash_seq,slot_htab);
3226+
while ((entry=hash_seq_search(&hash_seq))!=NULL)
3227+
{
3228+
boolfound;
3229+
3230+
free_attstatsslot(&entry->sslot);
3231+
3232+
(void)hash_search(slot_htab,&entry->key,HASH_REMOVE,&found);
3233+
3234+
if (!found)
3235+
elog(PANIC,"Hash table is corrupted");
3236+
}
3237+
}
3238+
}
3239+
3240+
staticvoid
3241+
cache_attstatslot(AttStatsSlot*sslot,
3242+
Oidrelid,intattnum,intreqkind,Oidreqop,intflags)
3243+
{
3244+
AttStatSlotHashEntry*entry;
3245+
AttStatSlotHashKeykey= {.relid=relid, .attnum=attnum,
3246+
.reqkind=reqkind, .reqop=reqop,
3247+
.flags=flags};
3248+
boolfound;
3249+
3250+
entry=hash_search(slot_htab,&key,HASH_ENTER,&found);
3251+
Assert(!found);
3252+
3253+
memcpy(&entry->sslot,sslot,sizeof(AttStatsSlot));
3254+
}
3255+
3256+
staticvoid
3257+
AttStatSlotCacheCallback(Datumarg,intcacheid,uint32hashvalue)
3258+
{
3259+
HASH_SEQ_STATUSstatus;
3260+
AttStatSlotHashEntry*entry;
3261+
3262+
if (slot_htab==NULL)
3263+
return;
3264+
3265+
/* Currently we just flush all entries; hard to be smarter ... */
3266+
hash_seq_init(&status,slot_htab);
3267+
3268+
while ((entry= (AttStatSlotHashEntry*)hash_seq_search(&status))!=NULL)
3269+
{
3270+
free_attstatsslot(&entry->sslot);
3271+
3272+
if (hash_search(slot_htab,
3273+
&entry->key,
3274+
HASH_REMOVE,NULL)==NULL)
3275+
elog(ERROR,"hash table corrupted");
3276+
}
3277+
}
3278+
3279+
staticbool
3280+
get_cached_attstatslot(AttStatsSlot*sslot,
3281+
Oidrelid,intattnum,intreqkind,Oidreqop,intflags)
3282+
{
3283+
AttStatSlotHashEntry*entry;
3284+
AttStatSlotHashKeykey= {.relid=relid, .attnum=attnum,
3285+
.reqkind=reqkind, .reqop=reqop,
3286+
.flags=flags};
3287+
boolfound;
3288+
3289+
if (slot_htab==NULL)
3290+
{
3291+
HASHCTLctl;
3292+
3293+
ctl.keysize=sizeof(AttStatSlotHashKey);
3294+
ctl.entrysize=sizeof(AttStatSlotHashEntry);
3295+
3296+
slot_htab=hash_create("AttStatSlot hash",16,&ctl,
3297+
HASH_ELEM |HASH_BLOBS);
3298+
3299+
/* To stay consistent clear the cache on demand */
3300+
CacheRegisterSyscacheCallback(STATRELATTINH,
3301+
AttStatSlotCacheCallback, (Datum)0);
3302+
}
3303+
3304+
entry=hash_search(slot_htab,&key,HASH_FIND,&found);
3305+
3306+
if (found)
3307+
{
3308+
memcpy(sslot,&entry->sslot,sizeof(AttStatsSlot));
3309+
return true;
3310+
}
3311+
3312+
return false;
3313+
}
3314+
31833315
/*
31843316
* get_attstatsslot
31853317
*
@@ -3246,6 +3378,12 @@ get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
32463378
/* initialize *sslot properly */
32473379
memset(sslot,0,sizeof(AttStatsSlot));
32483380

3381+
/* Try to return cached statistics */
3382+
if (attstatsslot_needs_cache&&
3383+
get_cached_attstatslot(sslot,stats->starelid,
3384+
stats->staattnum,reqkind,reqop,flags))
3385+
return true;
3386+
32493387
for (i=0;i<STATISTIC_NUM_SLOTS;i++)
32503388
{
32513389
if ((&stats->stakind1)[i]==reqkind&&
@@ -3333,6 +3471,10 @@ get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
33333471
sslot->numbers_arr=statarray;
33343472
}
33353473

3474+
if (attstatsslot_needs_cache)
3475+
cache_attstatslot(sslot,stats->starelid,
3476+
stats->staattnum,reqkind,reqop,flags);
3477+
33363478
return true;
33373479
}
33383480

@@ -3343,6 +3485,9 @@ get_attstatsslot(AttStatsSlot *sslot, HeapTuple statstuple,
33433485
void
33443486
free_attstatsslot(AttStatsSlot*sslot)
33453487
{
3488+
if (attstatsslot_needs_cache)
3489+
return;
3490+
33463491
/* The values[] array was separately palloc'd by deconstruct_array */
33473492
if (sslot->values)
33483493
pfree(sslot->values);

‎src/include/utils/lsyscache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ extern OidgetBaseType(Oid typid);
188188
externOidgetBaseTypeAndTypmod(Oidtypid,int32*typmod);
189189
externint32get_typavgwidth(Oidtypid,int32typmod);
190190
externint32get_attavgwidth(Oidrelid,AttrNumberattnum);
191+
externvoidset_attstatsslot_cache_mode(boolneed_cache);
191192
externboolget_attstatsslot(AttStatsSlot*sslot,HeapTuplestatstuple,
192193
intreqkind,Oidreqop,intflags);
193194
externvoidfree_attstatsslot(AttStatsSlot*sslot);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp