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

Commit77698e1

Browse files
committed
Avoid repeated detoasting (and possible memory leaks) when processing
a toasted datum in VACUUM ANALYZE.
1 parent079c60a commit77698e1

File tree

2 files changed

+64
-36
lines changed

2 files changed

+64
-36
lines changed

‎src/backend/commands/analyze.c

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,18 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.9 2000/11/16 22:30:19 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.10 2000/12/02 19:38:34 tgl Exp $
1212
*
13-
1413
*-------------------------------------------------------------------------
1514
*/
15+
#include"postgres.h"
16+
1617
#include<sys/types.h>
1718
#include<sys/file.h>
1819
#include<sys/stat.h>
1920
#include<fcntl.h>
2021
#include<unistd.h>
2122

22-
#include"postgres.h"
23-
2423
#include"access/heapam.h"
2524
#include"catalog/catname.h"
2625
#include"catalog/indexing.h"
@@ -159,7 +158,8 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
159158

160159
stats=&vacattrstats[i];
161160
stats->attr=palloc(ATTRIBUTE_TUPLE_SIZE);
162-
memmove(stats->attr,attr[((attnums) ?attnums[i] :i)],ATTRIBUTE_TUPLE_SIZE);
161+
memcpy(stats->attr,attr[((attnums) ?attnums[i] :i)],
162+
ATTRIBUTE_TUPLE_SIZE);
163163
stats->best=stats->guess1=stats->guess2=0;
164164
stats->max=stats->min=0;
165165
stats->best_len=stats->guess1_len=stats->guess2_len=0;
@@ -220,6 +220,7 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
220220
/* delete existing pg_statistic rows for relation */
221221
del_stats(relid, ((attnums) ?attr_cnt :0),attnums);
222222

223+
/* scan relation to gather statistics */
223224
scan=heap_beginscan(onerel, false,SnapshotNow,0,NULL);
224225

225226
while (HeapTupleIsValid(tuple=heap_getnext(scan,0)))
@@ -237,7 +238,7 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL)
237238
}
238239

239240
/*
240-
*attr_stats() -- compute column statistics used by theoptimzer
241+
*attr_stats() -- compute column statistics used by theplanner
241242
*
242243
*We compute the column min, max, null and non-null counts.
243244
*Plus we attempt to find the count of the value that occurs most
@@ -266,6 +267,7 @@ attr_stats(Relation onerel, int attr_cnt, VacAttrStats *vacattrstats, HeapTuple
266267
for (i=0;i<attr_cnt;i++)
267268
{
268269
VacAttrStats*stats=&vacattrstats[i];
270+
Datumorigvalue;
269271
Datumvalue;
270272
boolisnull;
271273
boolvalue_hit;
@@ -278,16 +280,25 @@ attr_stats(Relation onerel, int attr_cnt, VacAttrStats *vacattrstats, HeapTuple
278280
continue;
279281
#endif/* _DROP_COLUMN_HACK__ */
280282

281-
value=heap_getattr(tuple,
282-
stats->attr->attnum,tupDesc,&isnull);
283+
origvalue=heap_getattr(tuple,stats->attr->attnum,
284+
tupDesc,&isnull);
283285

284286
if (isnull)
285287
{
286288
stats->null_cnt++;
287289
continue;
288290
}
289-
290291
stats->nonnull_cnt++;
292+
293+
/*
294+
* If the value is toasted, detoast it to avoid repeated detoastings
295+
* and resultant memory leakage inside the comparison routines.
296+
*/
297+
if (!stats->attr->attbyval&&stats->attr->attlen==-1)
298+
value=PointerGetDatum(PG_DETOAST_DATUM(origvalue));
299+
else
300+
value=origvalue;
301+
291302
if (!stats->initialized)
292303
{
293304
bucketcpy(stats->attr,value,&stats->best,&stats->best_len);
@@ -365,22 +376,26 @@ attr_stats(Relation onerel, int attr_cnt, VacAttrStats *vacattrstats, HeapTuple
365376
stats->guess1_hits=1;
366377
stats->guess2_hits=1;
367378
}
379+
380+
/* Clean up detoasted copy, if any */
381+
if (value!=origvalue)
382+
pfree(DatumGetPointer(value));
368383
}
369384
}
370385

371386
/*
372387
*bucketcpy() -- copy a new value into one of the statistics buckets
373-
*
374388
*/
375389
staticvoid
376390
bucketcpy(Form_pg_attributeattr,Datumvalue,Datum*bucket,int*bucket_len)
377391
{
378-
if (attr->attbyval&&attr->attlen!=-1)
392+
if (attr->attbyval)
379393
*bucket=value;
380394
else
381395
{
382396
intlen= (attr->attlen!=-1 ?attr->attlen :VARSIZE(value));
383397

398+
/* Avoid unnecessary palloc() traffic... */
384399
if (len>*bucket_len)
385400
{
386401
if (*bucket_len!=0)
@@ -396,8 +411,27 @@ bucketcpy(Form_pg_attribute attr, Datum value, Datum *bucket, int *bucket_len)
396411
/*
397412
*update_attstats() -- update attribute statistics for one relation
398413
*
399-
*Updates of pg_attribute statistics are handled by over-write,
400-
*for reasons described above. pg_statistic rows are added normally.
414+
*Statistics are stored in several places: the pg_class row for the
415+
*relation has stats about the whole relation, the pg_attribute rows
416+
*for each attribute store "dispersion", and there is a pg_statistic
417+
*row for each (non-system) attribute. (Dispersion probably ought to
418+
*be moved to pg_statistic, but it's not worth doing unless there's
419+
*another reason to have to change pg_attribute.) The pg_class values
420+
*are updated by VACUUM, not here.
421+
*
422+
*We violate no-overwrite semantics here by storing new values for
423+
*the dispersion column directly into the pg_attribute tuple that's
424+
*already on the page. The reason for this is that if we updated
425+
*these tuples in the usual way, vacuuming pg_attribute itself
426+
*wouldn't work very well --- by the time we got done with a vacuum
427+
*cycle, most of the tuples in pg_attribute would've been obsoleted.
428+
*Updating pg_attribute's own statistics would be especially tricky.
429+
*Of course, this only works for fixed-size never-null columns, but
430+
*dispersion is.
431+
*
432+
*pg_statistic rows are just added normally. This means that
433+
*pg_statistic will probably contain some deleted rows at the
434+
*completion of a vacuum cycle, unless it happens to get vacuumed last.
401435
*
402436
*To keep things simple, we punt for pg_statistic, and don't try
403437
*to compute or store rows for pg_statistic itself in pg_statistic.

‎src/backend/commands/vacuum.c

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,28 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.174 2000/11/30 08:46:22 vadim Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.175 2000/12/02 19:38:34 tgl Exp $
1212
*
13-
1413
*-------------------------------------------------------------------------
1514
*/
15+
#include"postgres.h"
16+
1617
#include<sys/types.h>
1718
#include<sys/file.h>
1819
#include<sys/stat.h>
1920
#include<fcntl.h>
2021
#include<unistd.h>
2122

22-
#include"postgres.h"
23+
#ifndefHAVE_GETRUSAGE
24+
#include"rusagestub.h"
25+
#else
26+
#include<sys/time.h>
27+
#include<sys/resource.h>
28+
#endif
2329

2430
#include"access/genam.h"
2531
#include"access/heapam.h"
32+
#include"access/xlog.h"
2633
#include"catalog/catalog.h"
2734
#include"catalog/catname.h"
2835
#include"catalog/index.h"
@@ -40,14 +47,6 @@
4047
#include"utils/syscache.h"
4148
#include"utils/temprel.h"
4249

43-
#ifndefHAVE_GETRUSAGE
44-
#include"rusagestub.h"
45-
#else
46-
#include<sys/time.h>
47-
#include<sys/resource.h>
48-
#endif
49-
50-
#include"access/xlog.h"
5150
externXLogRecPtrlog_heap_move(Relationreln,
5251
ItemPointerDatafrom,HeapTuplenewtup);
5352

@@ -62,7 +61,7 @@ static void vacuum_init(void);
6261
staticvoidvacuum_shutdown(void);
6362
staticvoidvac_vacuum(NameData*VacRelP,boolanalyze,List*anal_cols2);
6463
staticVRelListgetrels(NameData*VacRelP);
65-
staticvoidvacuum_rel(Oidrelid,boolanalyze,boolis_toastrel);
64+
staticvoidvacuum_rel(Oidrelid,boolis_toastrel);
6665
staticvoidscan_heap(VRelStats*vacrelstats,Relationonerel,VacPageListvacuum_pages,VacPageListfraged_pages);
6766
staticvoidrepair_frag(VRelStats*vacrelstats,Relationonerel,VacPageListvacuum_pages,VacPageListfraged_pages,intnindices,Relation*Irel);
6867
staticvoidvacuum_heap(VRelStats*vacrelstats,Relationonerel,VacPageListvacpagelist);
@@ -240,7 +239,7 @@ vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2)
240239
/* vacuum each heap relation */
241240
for (cur=vrl;cur!= (VRelList)NULL;cur=cur->vrl_next)
242241
{
243-
vacuum_rel(cur->vrl_relid,analyze,false);
242+
vacuum_rel(cur->vrl_relid, false);
244243
/* analyze separately so locking is minimized */
245244
if (analyze)
246245
analyze_rel(cur->vrl_relid,anal_cols2,MESSAGE_LEVEL);
@@ -352,7 +351,7 @@ getrels(NameData *VacRelP)
352351
*us to lock the entire database during one pass of the vacuum cleaner.
353352
*/
354353
staticvoid
355-
vacuum_rel(Oidrelid,boolanalyze,boolis_toastrel)
354+
vacuum_rel(Oidrelid,boolis_toastrel)
356355
{
357356
Relationonerel;
358357
VacPageListDatavacuum_pages;/* List of pages to vacuum and/or clean
@@ -532,7 +531,7 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
532531
* totally unimportant for toast relations
533532
*/
534533
if (toast_relid!=InvalidOid)
535-
vacuum_rel(toast_relid,false,true);
534+
vacuum_rel(toast_relid, true);
536535

537536
/* next command frees attribute stats */
538537
if (!is_toastrel)
@@ -2187,14 +2186,9 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
21872186
/*
21882187
*update_relstats() -- update statistics for one relation
21892188
*
2190-
*Statistics are stored in several places: the pg_class row for the
2191-
*relation has stats about the whole relation, the pg_attribute rows
2192-
*for each attribute store "dispersion", and there is a pg_statistic
2193-
*row for each (non-system) attribute. (Dispersion probably ought to
2194-
*be moved to pg_statistic, but it's not worth doing unless there's
2195-
*another reason to have to change pg_attribute.) Dispersion and
2196-
*pg_statistic values are only updated by VACUUM ANALYZE, but we
2197-
*always update the stats in pg_class.
2189+
*Update the whole-relation statistics that are kept in its pg_class
2190+
*row. There are additional stats that will be updated if we are
2191+
*doing VACUUM ANALYZE, but we always update these stats.
21982192
*
21992193
*This routine works for both index and heap relation entries in
22002194
*pg_class. We violate no-overwrite semantics here by storing new

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp