Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8fb29d3

Browse files
author
teodor
committed
new GUC variables
1 parent f13a513 commit 8fb29d3

File tree

2 files changed

+346
-1
lines changed

2 files changed

+346
-1
lines changed

README.online_analyze

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,14 @@ online_analyze.threshold = 50
2323
online_analyze.min_interval = 10000
2424
Minimum time interval between analyze call per table (in milliseconds)
2525

26+
online_analyze.table_type = "all"
27+
Type(s) of table for onlyne analyze: all, persistent, temporary, none
28+
29+
online_analyze.exclude_tables = ""
30+
List of tables which will not online analyze
31+
32+
online_analyze.include_tables = ""
33+
List of tables which will online analyze
34+
online_analyze.include_tables overwrites online_analyze.exclude_tables.
35+
2636
Author: Teodor Sigaev <teodor@sigaev.ru>

online_analyze.c

Lines changed: 336 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "nodes/nodes.h"
3737
#include "nodes/parsenodes.h"
3838
#include "storage/bufmgr.h"
39+
#include "utils/builtins.h"
3940
#include "utils/lsyscache.h"
4041
#include "utils/guc.h"
4142

@@ -49,6 +50,238 @@ static double online_analyze_scale_factor = 0.1;
4950
static int online_analyze_threshold = 50;
5051
static double online_analyze_min_interval = 10000;
5152

53+
typedef enum
54+
{
55+
OATT_ALL = 0x03,
56+
OATT_PERSISTENT = 0x01,
57+
OATT_TEMPORARY = 0x02,
58+
OATT_NONE = 0x00
59+
} OnlyneAnalyzeTableType;
60+
61+
static const struct config_enum_entry online_analyze_table_type_options[] =
62+
{
63+
{"all", OATT_ALL, false},
64+
{"persistent", OATT_PERSISTENT, false},
65+
{"temporary", OATT_TEMPORARY, false},
66+
{"none", OATT_NONE, false},
67+
{NULL, 0, false},
68+
};
69+
70+
static int online_analyze_table_type = (int)OATT_ALL;
71+
72+
typedef struct TableList {
73+
int nTables;
74+
Oid *tables;
75+
char *tableStr;
76+
} TableList;
77+
78+
static TableList excludeTables = {0, NULL, NULL};
79+
static TableList includeTables = {0, NULL, NULL};
80+
81+
static int
82+
oid_cmp(const void *a, const void *b)
83+
{
84+
if (*(Oid*)a == *(Oid*)b)
85+
return 0;
86+
return (*(Oid*)a > *(Oid*)b) ? 1 : -1;
87+
}
88+
89+
static const char *
90+
tableListAssign(const char * newval, bool doit, TableList *tbl)
91+
{
92+
char *rawname;
93+
List *namelist;
94+
ListCell *l;
95+
Oid *newOids = NULL;
96+
int nOids = 0,
97+
i = 0;
98+
99+
rawname = pstrdup(newval);
100+
101+
if (!SplitIdentifierString(rawname, ',', &namelist))
102+
goto cleanup;
103+
104+
if (doit)
105+
{
106+
nOids = list_length(namelist);
107+
newOids = malloc(sizeof(Oid) * (nOids+1));
108+
if (!newOids)
109+
elog(ERROR,"could not allocate %d bytes", (int)(sizeof(Oid) * (nOids+1)));
110+
}
111+
112+
foreach(l, namelist)
113+
{
114+
char *curname = (char *) lfirst(l);
115+
Oid relOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), true);
116+
117+
if (relOid == InvalidOid)
118+
{
119+
#if PG_VERSION_NUM >= 90100
120+
if (doit == false)
121+
#endif
122+
elog(WARNING,"'%s' does not exist", curname);
123+
continue;
124+
}
125+
else if ( get_rel_relkind(relOid) != RELKIND_RELATION )
126+
{
127+
#if PG_VERSION_NUM >= 90100
128+
if (doit == false)
129+
#endif
130+
elog(WARNING,"'%s' is not an table", curname);
131+
continue;
132+
}
133+
else if (doit)
134+
{
135+
newOids[i++] = relOid;
136+
}
137+
}
138+
139+
if (doit)
140+
{
141+
tbl->nTables = i;
142+
if (tbl->tables)
143+
free(tbl->tables);
144+
tbl->tables = newOids;
145+
if (tbl->nTables > 1)
146+
qsort(tbl->tables, tbl->nTables, sizeof(tbl->tables[0]), oid_cmp);
147+
}
148+
149+
pfree(rawname);
150+
list_free(namelist);
151+
152+
return newval;
153+
154+
cleanup:
155+
if (newOids)
156+
free(newOids);
157+
pfree(rawname);
158+
list_free(namelist);
159+
return NULL;
160+
}
161+
162+
#if PG_VERSION_NUM >= 90100
163+
static bool
164+
excludeTablesCheck(char **newval, void **extra, GucSource source)
165+
{
166+
char *val;
167+
168+
val = (char*)tableListAssign(*newval, false, &excludeTables);
169+
170+
if (val)
171+
{
172+
*newval = val;
173+
return true;
174+
}
175+
176+
return false;
177+
}
178+
179+
static void
180+
excludeTablesAssign(const char *newval, void *extra)
181+
{
182+
tableListAssign(newval, true, &excludeTables);
183+
}
184+
185+
static bool
186+
includeTablesCheck(char **newval, void **extra, GucSource source)
187+
{
188+
char *val;
189+
190+
val = (char*)tableListAssign(*newval, false, &includeTables);
191+
192+
if (val)
193+
{
194+
*newval = val;
195+
return true;
196+
}
197+
198+
return false;
199+
}
200+
201+
static void
202+
includeTablesAssign(const char *newval, void *extra)
203+
{
204+
tableListAssign(newval, true, &excludeTables);
205+
}
206+
207+
#else /* PG_VERSION_NUM < 90100 */
208+
209+
static const char *
210+
excludeTablesAssign(const char * newval, bool doit, GucSource source)
211+
{
212+
return tableListAssign(newval, doit, &excludeTables);
213+
}
214+
215+
static const char *
216+
includeTablesAssign(const char * newval, bool doit, GucSource source)
217+
{
218+
return tableListAssign(newval, doit, &includeTables);
219+
}
220+
221+
#endif
222+
223+
static const char*
224+
tableListShow(TableList *tbl)
225+
{
226+
char *val, *ptr;
227+
int i,
228+
len;
229+
230+
len = 1 /* \0 */ + tbl->nTables * (2 * NAMEDATALEN + 2 /* ', ' */ + 1 /* . */);
231+
ptr = val = palloc(len);
232+
*ptr ='\0';
233+
for(i=0; i<tbl->nTables; i++)
234+
{
235+
char *relname = get_rel_name(tbl->tables[i]);
236+
Oid nspOid = get_rel_namespace(tbl->tables[i]);
237+
char *nspname = get_namespace_name(nspOid);
238+
239+
if ( relname == NULL || nspOid == InvalidOid || nspname == NULL )
240+
continue;
241+
242+
ptr += snprintf(ptr, len - (ptr - val), "%s%s.%s",
243+
(i==0) ? "" : ", ",
244+
nspname, relname);
245+
}
246+
247+
return val;
248+
}
249+
250+
static const char*
251+
excludeTablesShow(void)
252+
{
253+
return tableListShow(&excludeTables);
254+
}
255+
256+
static const char*
257+
includeTablesShow(void)
258+
{
259+
return tableListShow(&includeTables);
260+
}
261+
262+
static bool
263+
matchOid(TableList *tbl, Oid oid)
264+
{
265+
Oid *StopLow = tbl->tables,
266+
*StopHigh = tbl->tables + tbl->nTables,
267+
*StopMiddle;
268+
269+
/* Loop invariant: StopLow <= val < StopHigh */
270+
while (StopLow < StopHigh)
271+
{
272+
StopMiddle = StopLow + ((StopHigh - StopLow) >> 1);
273+
274+
if (*StopMiddle == oid)
275+
return true;
276+
else if (*StopMiddle < oid)
277+
StopLow = StopMiddle + 1;
278+
else
279+
StopHigh = StopMiddle;
280+
}
281+
282+
return false;
283+
}
284+
52285
static ExecutorEnd_hook_type oldhook = NULL;
53286

54287
static void
@@ -84,6 +317,42 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
84317
VacuumStmt vacstmt;
85318
TimestampTz startStamp, endStamp;
86319

320+
/*
321+
* includeTables overwrites excludeTables
322+
*/
323+
switch(online_analyze_table_type)
324+
{
325+
case OATT_ALL:
326+
if (matchOid(&excludeTables, relOid) == true && matchOid(&includeTables, relOid) == false)
327+
return;
328+
break;
329+
case OATT_NONE:
330+
if (matchOid(&includeTables, relOid) == false)
331+
return;
332+
break;
333+
case OATT_TEMPORARY:
334+
case OATT_PERSISTENT:
335+
default:
336+
{
337+
Relation rel;
338+
OnlyneAnalyzeTableType reltype;
339+
340+
rel = RelationIdGetRelation(relOid);
341+
reltype = (rel->rd_istemp || rel->rd_islocaltemp) ? OATT_TEMPORARY : OATT_PERSISTENT;
342+
RelationClose(rel);
343+
344+
/*
345+
* skip analyze if relation's type doesn't not match online_analyze_table_type
346+
*/
347+
if ((online_analyze_table_type & reltype) == 0 || matchOid(&excludeTables, relOid) == true)
348+
{
349+
if (matchOid(&includeTables, relOid) == false)
350+
return;
351+
}
352+
}
353+
break;
354+
}
355+
87356
vacstmt.type = T_VacuumStmt;
88357
vacstmt.freeze_min_age = -1;
89358
vacstmt.freeze_table_age = -1; /* ??? */
@@ -116,7 +385,8 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
116385

117386
endStamp = GetCurrentTimestamp();
118387
TimestampDifference(startStamp, endStamp, &secs, &microsecs);
119-
elog(INFO, "analyze \"%s\" took %.02f seconds", get_rel_name(relOid), ((double)secs) + ((double)microsecs)/1.0e6);
388+
elog(INFO, "analyze \"%s\" took %.02f seconds",
389+
get_rel_name(relOid), ((double)secs) + ((double)microsecs)/1.0e6);
120390
}
121391

122392

@@ -291,11 +561,76 @@ _PG_init(void)
291561
NULL
292562
);
293563

564+
DefineCustomEnumVariable(
565+
"online_analyze.table_type",
566+
"Type(s) of table for onlyne analyze: all(default), persistent, temporary, none",
567+
NULL,
568+
&online_analyze_table_type,
569+
#if PG_VERSION_NUM >= 80400
570+
online_analyze_table_type,
571+
#endif
572+
online_analyze_table_type_options,
573+
PGC_USERSET,
574+
#if PG_VERSION_NUM >= 80400
575+
GUC_NOT_IN_SAMPLE,
576+
#if PG_VERSION_NUM >= 90100
577+
NULL,
578+
#endif
579+
#endif
580+
NULL,
581+
NULL
582+
);
583+
584+
DefineCustomStringVariable(
585+
"online_analyze.exclude_tables",
586+
"List of tables which will not online analyze",
587+
NULL,
588+
&excludeTables.tableStr,
589+
#if PG_VERSION_NUM >= 80400
590+
"",
591+
#endif
592+
PGC_USERSET,
593+
0,
594+
#if PG_VERSION_NUM >= 90100
595+
excludeTablesCheck,
596+
excludeTablesAssign,
597+
#else
598+
excludeTablesAssign,
599+
#endif
600+
excludeTablesShow
601+
);
602+
603+
DefineCustomStringVariable(
604+
"online_analyze.include_tables",
605+
"List of tables which will online analyze",
606+
NULL,
607+
&includeTables.tableStr,
608+
#if PG_VERSION_NUM >= 80400
609+
"",
610+
#endif
611+
PGC_USERSET,
612+
0,
613+
#if PG_VERSION_NUM >= 90100
614+
includeTablesCheck,
615+
includeTablesAssign,
616+
#else
617+
includeTablesAssign,
618+
#endif
619+
includeTablesShow
620+
);
294621
}
295622

296623
void _PG_fini(void);
297624
void
298625
_PG_fini(void)
299626
{
300627
ExecutorEnd_hook = oldhook;
628+
629+
if (excludeTables.tables)
630+
free(excludeTables.tables);
631+
if (includeTables.tables)
632+
free(includeTables.tables);
633+
634+
excludeTables.tables = includeTables.tables = NULL;
635+
excludeTables.nTables = includeTables.nTables = 0;
301636
}

0 commit comments

Comments
 (0)