8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.170 2008/04/01 00:48:33 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.171 2008/06/27 03:56:55 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
15
15
16
16
#include "postgres.h"
17
17
18
+ #include <math.h>
19
+
18
20
#ifdef OPTIMIZER_DEBUG
19
21
#include "nodes/print.h"
20
22
#endif
@@ -263,6 +265,10 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
263
265
{
264
266
int parentRTindex = rti ;
265
267
List * subpaths = NIL ;
268
+ double parent_rows ;
269
+ double parent_size ;
270
+ double * parent_attrsizes ;
271
+ int nattrs ;
266
272
ListCell * l ;
267
273
268
274
/*
@@ -277,10 +283,23 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
277
283
errmsg ("SELECT FOR UPDATE/SHARE is not supported for inheritance queries" )));
278
284
279
285
/*
280
- * Initialize to compute size estimates for whole append relation
286
+ * Initialize to compute size estimates for whole append relation.
287
+ *
288
+ * We handle width estimates by weighting the widths of different
289
+ * child rels proportionally to their number of rows. This is sensible
290
+ * because the use of width estimates is mainly to compute the total
291
+ * relation "footprint" if we have to sort or hash it. To do this,
292
+ * we sum the total equivalent size (in "double" arithmetic) and then
293
+ * divide by the total rowcount estimate. This is done separately for
294
+ * the total rel width and each attribute.
295
+ *
296
+ * Note: if you consider changing this logic, beware that child rels could
297
+ * have zero rows and/or width, if they were excluded by constraints.
281
298
*/
282
- rel -> rows = 0 ;
283
- rel -> width = 0 ;
299
+ parent_rows = 0 ;
300
+ parent_size = 0 ;
301
+ nattrs = rel -> max_attr - rel -> min_attr + 1 ;
302
+ parent_attrsizes = (double * ) palloc0 (nattrs * sizeof (double ));
284
303
285
304
/*
286
305
* Generate access paths for each member relation, and pick the cheapest
@@ -379,38 +398,53 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
379
398
subpaths = lappend (subpaths , childpath );
380
399
381
400
/*
382
- * Propagate size information from the child back to the parent. For
383
- * simplicity, we use the largest widths from any child as the parent
384
- * estimates. (If you want to change this, beware of child
385
- * attr_widths[] entries that haven't been set and are still 0.)
401
+ * Accumulate size information from each child.
386
402
*/
387
- rel -> rows += childrel -> rows ;
388
- if (childrel -> width > rel -> width )
389
- rel -> width = childrel -> width ;
390
-
391
- forboth (parentvars , rel -> reltargetlist ,
392
- childvars , childrel -> reltargetlist )
403
+ if (childrel -> rows > 0 )
393
404
{
394
- Var * parentvar = ( Var * ) lfirst ( parentvars ) ;
395
- Var * childvar = ( Var * ) lfirst ( childvars ) ;
405
+ parent_rows += childrel -> rows ;
406
+ parent_size += childrel -> width * childrel -> rows ;
396
407
397
- if ( IsA ( parentvar , Var ) &&
398
- IsA ( childvar , Var ) )
408
+ forboth ( parentvars , rel -> reltargetlist ,
409
+ childvars , childrel -> reltargetlist )
399
410
{
400
- int pndx = parentvar -> varattno - rel -> min_attr ;
401
- int cndx = childvar -> varattno - childrel -> min_attr ;
411
+ Var * parentvar = ( Var * ) lfirst ( parentvars ) ;
412
+ Var * childvar = ( Var * ) lfirst ( childvars ) ;
402
413
403
- if (childrel -> attr_widths [cndx ] > rel -> attr_widths [pndx ])
404
- rel -> attr_widths [pndx ] = childrel -> attr_widths [cndx ];
414
+ if (IsA (parentvar , Var ) &&
415
+ IsA (childvar , Var ))
416
+ {
417
+ int pndx = parentvar -> varattno - rel -> min_attr ;
418
+ int cndx = childvar -> varattno - childrel -> min_attr ;
419
+
420
+ parent_attrsizes [pndx ] += childrel -> attr_widths [cndx ] * childrel -> rows ;
421
+ }
405
422
}
406
423
}
407
424
}
408
425
426
+ /*
427
+ * Save the finished size estimates.
428
+ */
429
+ rel -> rows = parent_rows ;
430
+ if (parent_rows > 0 )
431
+ {
432
+ int i ;
433
+
434
+ rel -> width = rint (parent_size / parent_rows );
435
+ for (i = 0 ; i < nattrs ; i ++ )
436
+ rel -> attr_widths [i ] = rint (parent_attrsizes [i ] / parent_rows );
437
+ }
438
+ else
439
+ rel -> width = 0 ; /* attr_widths should be zero already */
440
+
409
441
/*
410
442
* Set "raw tuples" count equal to "rows" for the appendrel; needed
411
443
* because some places assume rel->tuples is valid for any baserel.
412
444
*/
413
- rel -> tuples = rel -> rows ;
445
+ rel -> tuples = parent_rows ;
446
+
447
+ pfree (parent_attrsizes );
414
448
415
449
/*
416
450
* Finally, build Append path and install it as the only access path for
0 commit comments