77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.34 1999/04/05 02:07:07 tgl Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.35 1999/04/30 04:01:44 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -129,28 +129,36 @@ cost_index(Oid indexid,
129129int indextuples ,
130130bool is_injoin )
131131{
132- Cost temp ;
133- double temp2 ;
134-
135- temp = (Cost )0 ;
132+ Cost temp = 0 ;
136133
137134if (!_enable_indexscan_ && !is_injoin )
138135temp += _disable_cost_ ;
139136
137+ /* We want to be sure we estimate the cost of an index scan
138+ * as more than the cost of a sequential scan (when selec == 1.0),
139+ * even if we don't have good stats. So, disbelieve zero index size.
140+ */
141+ if (expected_indexpages <=0 )
142+ expected_indexpages = 1 ;
143+ if (indextuples <=0 )
144+ indextuples = 1 ;
145+
140146/* expected index relation pages */
141147temp += expected_indexpages ;
142148
143- /* expected base relation pages */
144- temp2 = (reltuples == 0 ) ? (double )0 : (double )relpages /reltuples ;
145- temp2 = temp2 * (double )selec * indextuples ;
146-
147- temp += Min (relpages , (int )ceil (temp2 ));
149+ /* expected base relation pages
150+ * XXX this isn't really right, since we will access the table
151+ * nonsequentially and might have to fetch the same page
152+ * more than once. This calculation assumes the buffer cache
153+ * will prevent that from happening...
154+ */
155+ temp += ceil (((double )selec )* ((double )relpages ));
148156
149157/* per index tuples */
150- temp = temp + ( _cpu_index_page_wight_ * selec * indextuples ) ;
158+ temp += _cpu_index_page_wight_ * selec * indextuples ;
151159
152160/* per heap tuples */
153- temp = temp + ( _cpu_page_wight_ * selec * reltuples ) ;
161+ temp += _cpu_page_wight_ * selec * reltuples ;
154162
155163Assert (temp >=0 );
156164return temp ;
@@ -168,8 +176,13 @@ cost_index(Oid indexid,
168176 * 'pathkeys' is a list of sort keys
169177 * 'tuples' is the number of tuples in the relation
170178 * 'width' is the average tuple width in bytes
171- * 'noread' is a flag indicating that the sort result can remain on disk
172- *(i.e., the sort result is the result relation)
179+ * 'noread' is a flag indicating that the cost of reading the sort
180+ *source data should not be included (i.e., the caller
181+ *will account for it separately).
182+ *
183+ * NOTE: some callers currently pass NULL for pathkeys because they
184+ * can't conveniently supply sort keys. Since this routine doesn't
185+ * currently do anything with pathkeys anyway, that doesn't matter...
173186 *
174187 * Returns a flonum.
175188 *
@@ -179,28 +192,33 @@ cost_sort(List *pathkeys, int tuples, int width, bool noread)
179192{
180193Cost temp = 0 ;
181194int npages = page_size (tuples ,width );
182- Cost pages = (Cost )npages ;
183- Cost numTuples = tuples ;
195+ double log_npages ;
184196
185197if (!_enable_sort_ )
186198temp += _disable_cost_ ;
187- if (tuples == 0 || pathkeys == NULL )
188- {
189- Assert (temp >=0 );
190- return temp ;
191- }
192- temp += pages * base_log ((double )pages , (double )2.0 );
199+
200+ /* We want to be sure the cost of a sort is never estimated as zero,
201+ * even if passed-in tuple count is zero. Besides, mustn't do log(0)...
202+ */
203+ if (npages <=0 )
204+ npages = 1 ;
205+
206+ log_npages = ceil (base_log ((double )npages ,2.0 ));
207+ if (log_npages <=0.0 )
208+ log_npages = 1.0 ;
209+
210+ temp += npages * log_npages ;
193211
194212/*
195213 * could be base_log(pages, NBuffers), but we are only doing 2-way
196214 * merges
197215 */
198- temp += _cpu_page_wight_ * numTuples *
199- base_log ((double )pages , (double )2.0 );
216+ temp += _cpu_page_wight_ * tuples * log_npages ;
200217
201218if (!noread )
202- temp = temp + cost_seqscan (_NONAME_RELATION_ID_ ,npages ,tuples );
203- Assert (temp >=0 );
219+ temp += cost_seqscan (_NONAME_RELATION_ID_ ,npages ,tuples );
220+
221+ Assert (temp > 0 );
204222
205223return temp ;
206224}
@@ -290,9 +308,12 @@ cost_mergejoin(Cost outercost,
290308
291309temp += outercost ;
292310temp += innercost ;
293- temp += cost_sort (outersortkeys ,outersize ,outerwidth , false);
294- temp += cost_sort (innersortkeys ,innersize ,innerwidth , false);
311+ if (outersortkeys )/* do we need to sort? */
312+ temp += cost_sort (outersortkeys ,outersize ,outerwidth , true);
313+ if (innersortkeys )/* do we need to sort? */
314+ temp += cost_sort (innersortkeys ,innersize ,innerwidth , true);
295315temp += _cpu_page_wight_ * (outersize + innersize );
316+
296317Assert (temp >=0 );
297318
298319return temp ;