KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > Level2OptimizerImpl


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.Level2OptimizerImpl
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.services.sanity.SanityManager;
25
26 import org.apache.derby.iapi.error.StandardException;
27
28 import org.apache.derby.iapi.sql.compile.JoinStrategy;
29 import org.apache.derby.iapi.sql.compile.Optimizable;
30 import org.apache.derby.iapi.sql.compile.OptimizableList;
31 import org.apache.derby.iapi.sql.compile.OptimizablePredicate;
32 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
33 import org.apache.derby.iapi.sql.compile.Optimizer;
34 import org.apache.derby.iapi.sql.compile.CostEstimate;
35 import org.apache.derby.iapi.sql.compile.RequiredRowOrdering;
36 import org.apache.derby.iapi.sql.compile.RowOrdering;
37 import org.apache.derby.iapi.sql.compile.AccessPath;
38
39 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
40
41 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
42 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
43 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
44 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
45
46 import org.apache.derby.iapi.reference.SQLState;
47
48 import org.apache.derby.iapi.util.JBitSet;
49
50 import org.apache.derby.impl.sql.compile.OptimizerImpl;
51 import org.apache.derby.impl.sql.compile.CostEstimateImpl;
52
53 import java.util.Properties JavaDoc;
54
55 /**
56  * This is the Level 2 Optimizer.
57  */

58
59 public class Level2OptimizerImpl extends OptimizerImpl
60 {
61     private LanguageConnectionContext lcc;
62
63     Level2OptimizerImpl(OptimizableList optimizableList,
64                   OptimizablePredicateList predicateList,
65                   DataDictionary dDictionary,
66                   boolean ruleBasedOptimization,
67                   boolean noTimeout,
68                   boolean useStatistics,
69                   int maxMemoryPerTable,
70                   JoinStrategy[] joinStrategies,
71                   int tableLockThreshold,
72                   RequiredRowOrdering requiredRowOrdering,
73                   int numTablesInQuery,
74                   LanguageConnectionContext lcc)
75         throws StandardException
76     {
77         super(optimizableList, predicateList, dDictionary,
78               ruleBasedOptimization, noTimeout, useStatistics, maxMemoryPerTable,
79               joinStrategies, tableLockThreshold, requiredRowOrdering,
80               numTablesInQuery);
81
82         // Remember whether or not optimizer trace is on;
83
optimizerTrace = lcc.getOptimizerTrace();
84         optimizerTraceHtml = lcc.getOptimizerTraceHtml();
85         this.lcc = lcc;
86
87         // Optimization started
88
if (optimizerTrace)
89         {
90             trace(STARTED, 0, 0, 0.0, null);
91         }
92     }
93
94     /** @see Optimizer#getLevel */
95     public int getLevel()
96     {
97         return 2;
98     }
99
100     /** @see Optimizer#newCostEstimate */
101     public CostEstimate newCostEstimate()
102     {
103         return new Level2CostEstimateImpl();
104     }
105
106     public CostEstimateImpl getNewCostEstimate(double theCost,
107                             double theRowCount,
108                             double theSingleScanRowCount)
109     {
110         return new Level2CostEstimateImpl(theCost, theRowCount, theSingleScanRowCount);
111     }
112
113     // Optimzer trace
114
public void trace(int traceFlag, int intParam1, int intParam2,
115                       double doubleParam, Object JavaDoc objectParam1)
116     {
117         ConglomerateDescriptor cd;
118         String JavaDoc cdString;
119         String JavaDoc traceString = null;
120
121         // We can get called from outside optimizer when tracing is off
122
if (!optimizerTrace)
123         {
124             return;
125         }
126
127         switch (traceFlag)
128         {
129             case STARTED:
130                 traceString =
131                     "Optimization started at time " +
132                     timeOptimizationStarted +
133                     " using optimizer " + this.hashCode();
134                 break;
135
136             case TIME_EXCEEDED:
137                 traceString =
138                     "Optimization time exceeded at time " +
139                             currentTime + "\n" + bestCost();
140                 break;
141
142             case NO_TABLES:
143                 traceString = "No tables to optimize.";
144                 break;
145
146             case COMPLETE_JOIN_ORDER:
147                 traceString = "We have a complete join order.";
148                 break;
149
150             case COST_OF_SORTING:
151                 traceString =
152                     "Cost of sorting is " + sortCost;
153                 break;
154
155             case NO_BEST_PLAN:
156                 traceString =
157                     "No best plan found.";
158                 break;
159
160             case MODIFYING_ACCESS_PATHS:
161                 traceString =
162                     "Modifying access paths using optimizer " + this.hashCode();
163                 break;
164
165             case SHORT_CIRCUITING:
166                 String JavaDoc basis = (timeExceeded) ? "time exceeded" : "cost";
167                 Optimizable thisOpt =
168                     optimizableList.getOptimizable(
169                                         proposedJoinOrder[joinPosition]);
170                 if (thisOpt.getBestAccessPath().getCostEstimate() == null)
171                     basis = "no best plan found";
172                 traceString =
173                     "Short circuiting based on " + basis +
174                     " at join position " + joinPosition;
175                 break;
176
177             case SKIPPING_JOIN_ORDER:
178                 traceString = buildJoinOrder("\n\nSkipping join order: ", true, intParam1,
179                                              proposedJoinOrder);
180                 break;
181
182             case ILLEGAL_USER_JOIN_ORDER:
183                 traceString =
184                     "User specified join order is not legal.";
185                 break;
186
187             case USER_JOIN_ORDER_OPTIMIZED:
188                 traceString =
189                     "User-specified join order has now been optimized.";
190                 break;
191
192             case CONSIDERING_JOIN_ORDER:
193                 traceString = buildJoinOrder("\n\nConsidering join order: ", false, intParam1,
194                                              proposedJoinOrder);
195                 break;
196
197             case TOTAL_COST_NON_SA_PLAN:
198                 traceString =
199                     "Total cost of non-sort-avoidance plan is " +
200                         currentCost;
201                 break;
202
203             case TOTAL_COST_SA_PLAN:
204                 traceString =
205                     "Total cost of sort avoidance plan is " +
206                         currentSortAvoidanceCost;
207                 break;
208
209             case TOTAL_COST_WITH_SORTING:
210                 traceString =
211                     "Total cost of non-sort-avoidance plan with sort cost added is " + currentCost;
212                 break;
213
214             case CURRENT_PLAN_IS_SA_PLAN:
215                 traceString =
216                     "Current plan is a sort avoidance plan." +
217                     "\n\tBest cost is : " + bestCost +
218                     "\n\tThis cost is : " + currentSortAvoidanceCost;
219                 break;
220
221             case CHEAPEST_PLAN_SO_FAR:
222                 traceString =
223                     "This is the cheapest plan so far.";
224                 break;
225
226             case PLAN_TYPE:
227                 traceString =
228                     "Plan is a " +
229                     (intParam1 == Optimizer.NORMAL_PLAN ?
230                         "normal" : "sort avoidance") +
231                     " plan.";
232                 break;
233
234             case COST_OF_CHEAPEST_PLAN_SO_FAR:
235                 traceString =
236                     "Cost of cheapest plan is " + currentCost;
237                 break;
238
239             case SORT_NEEDED_FOR_ORDERING:
240                 traceString =
241                     "Sort needed for ordering: " +
242                         (intParam1 != Optimizer.SORT_AVOIDANCE_PLAN) +
243                         "\n\tRow ordering: " +
244                         requiredRowOrdering;
245                 break;
246
247             case REMEMBERING_BEST_JOIN_ORDER:
248                 traceString = buildJoinOrder("\n\nRemembering join order as best: ", false, intParam1,
249                                              bestJoinOrder);
250                 break;
251
252             case SKIPPING_DUE_TO_EXCESS_MEMORY:
253                 traceString =
254                     "Skipping access path due to excess memory usage, maximum is " +
255                     maxMemoryPerTable;
256                 break;
257
258             case COST_OF_N_SCANS:
259                 traceString =
260                         "Cost of " + doubleParam +
261                         " scans is: " +
262                         objectParam1 +
263                         " for table " +
264                         intParam1;
265                 break;
266
267             case HJ_SKIP_NOT_MATERIALIZABLE:
268                 traceString = "Skipping HASH JOIN because optimizable is not materializable";
269                 break;
270
271             case HJ_SKIP_NO_JOIN_COLUMNS:
272                 traceString = "Skipping HASH JOIN because there are no hash key columns";
273                 break;
274
275             case HJ_HASH_KEY_COLUMNS:
276                 int[] hashKeyColumns = (int []) objectParam1;
277                 traceString = "# hash key columns = " + hashKeyColumns.length;
278                 for (int index = 0; index < hashKeyColumns.length; index++)
279                 {
280                     traceString =
281                         "\n" + traceString + "hashKeyColumns[" + index +
282                         "] = " + hashKeyColumns[index];
283                 }
284                 break;
285
286             case CALLING_ON_JOIN_NODE:
287                 traceString = "Calling optimizeIt() for join node";
288                 break;
289
290             case CONSIDERING_JOIN_STRATEGY:
291                 JoinStrategy js = (JoinStrategy) objectParam1;
292                 traceString =
293                     "\nConsidering join strategy " +
294                     js + " for table " + intParam1;
295                 break;
296
297             case REMEMBERING_BEST_ACCESS_PATH:
298                 traceString =
299                     "Remembering access path " +
300                     objectParam1 +
301                     " as truly the best for table " +
302                     intParam1 +
303                     " for plan type " +
304                     (intParam2 == Optimizer.NORMAL_PLAN ?
305                                         " normal " : "sort avoidance") +
306                     "\n";
307                 break;
308
309             case NO_MORE_CONGLOMERATES:
310                 traceString =
311                     "No more conglomerates to consider for table " +
312                     intParam1;
313                 break;
314
315             case CONSIDERING_CONGLOMERATE:
316                 cd = (ConglomerateDescriptor) objectParam1;
317                 cdString = dumpConglomerateDescriptor(cd);
318                 traceString =
319                     "\nConsidering conglomerate " +
320                     cdString +
321                     " for table " +
322                     intParam1;
323                 break;
324
325             case SCANNING_HEAP_FULL_MATCH_ON_UNIQUE_KEY:
326                 traceString = "Scanning heap, but we have a full match on a unique key.";
327                 break;
328
329             case ADDING_UNORDERED_OPTIMIZABLE:
330                 traceString = "Adding unordered optimizable, # of predicates = " + intParam1;
331                 break;
332
333             case CHANGING_ACCESS_PATH_FOR_TABLE:
334                 traceString = "Changing access path for table " + intParam1;
335                 break;
336
337             case TABLE_LOCK_NO_START_STOP:
338                 traceString = "Lock mode set to MODE_TABLE because no start or stop position";
339                 break;
340
341             case NON_COVERING_INDEX_COST:
342                 traceString =
343                     "Index does not cover query - cost including base row fetch is: " +
344                     doubleParam +
345                     " for table " + intParam1;
346                 break;
347
348             case ROW_LOCK_ALL_CONSTANT_START_STOP:
349                 traceString =
350                     "Lock mode set to MODE_RECORD because all start and stop positions are constant";
351                 break;
352
353             case ESTIMATING_COST_OF_CONGLOMERATE:
354                 cd = (ConglomerateDescriptor) objectParam1;
355                 cdString = dumpConglomerateDescriptor(cd);
356                 traceString =
357                     "Estimating cost of conglomerate: " +
358                     costForTable(cdString, intParam1);
359                 break;
360                 
361             case LOOKING_FOR_SPECIFIED_INDEX:
362                 traceString =
363                     "Looking for user-specified index: " +
364                     objectParam1 + " for table " +
365                     intParam1;
366                 break;
367
368             case MATCH_SINGLE_ROW_COST:
369                 traceString =
370                     "Guaranteed to match a single row - cost is: " +
371                     doubleParam + " for table " + intParam1;
372                 break;
373
374             case COST_INCLUDING_EXTRA_1ST_COL_SELECTIVITY:
375                 traceString = costIncluding(
376                                 "1st column", objectParam1, intParam1);
377                 traceString =
378                     "Cost including extra first column selectivity is : " +
379                     objectParam1 + " for table " + intParam1;
380                 break;
381
382             case CALLING_NEXT_ACCESS_PATH:
383                 traceString =
384                     "Calling nextAccessPath() for base table " +
385                     objectParam1 + " with " + intParam1 + " predicates.";
386                 break;
387
388             case TABLE_LOCK_OVER_THRESHOLD:
389                 traceString = lockModeThreshold("MODE_TABLE", "greater",
390                                                 doubleParam, intParam1);
391                 break;
392
393             case ROW_LOCK_UNDER_THRESHOLD:
394                 traceString = lockModeThreshold("MODE_RECORD", "less",
395                                                 doubleParam, intParam1);
396                 break;
397
398             case COST_INCLUDING_EXTRA_START_STOP:
399                 traceString = costIncluding(
400                                 "start/stop", objectParam1, intParam1);
401                 break;
402
403             case COST_INCLUDING_EXTRA_QUALIFIER_SELECTIVITY:
404                 traceString = costIncluding(
405                                 "qualifier", objectParam1, intParam1);
406                 break;
407
408             case COST_INCLUDING_EXTRA_NONQUALIFIER_SELECTIVITY:
409                 traceString = costIncluding(
410                                 "non-qualifier", objectParam1, intParam1);
411                 break;
412
413             case COST_INCLUDING_COMPOSITE_SEL_FROM_STATS:
414                 traceString = costIncluding("selectivity from statistics",
415                                             objectParam1, intParam1);
416                 break;
417
418             case COST_INCLUDING_STATS_FOR_INDEX:
419                 traceString = costIncluding("statistics for index being considered",
420                                             objectParam1, intParam1);
421                 break;
422             case COMPOSITE_SEL_FROM_STATS:
423                 traceString = "Selectivity from statistics found. It is " +
424                     doubleParam;
425                 break;
426
427             case COST_OF_NONCOVERING_INDEX:
428                 traceString =
429                     "Index does not cover query: cost including row fetch is: " +
430                     costForTable(objectParam1, intParam1);
431                 break;
432
433             case REMEMBERING_JOIN_STRATEGY:
434                 traceString =
435                     "\nRemembering join strategy " + objectParam1 +
436                     " as best for table " + intParam1;
437                 break;
438
439             case REMEMBERING_BEST_ACCESS_PATH_SUBSTRING:
440                 traceString =
441                     "in best access path";
442                 break;
443
444             case REMEMBERING_BEST_SORT_AVOIDANCE_ACCESS_PATH_SUBSTRING:
445                 traceString =
446                     "in best sort avoidance access path";
447                 break;
448
449             case REMEMBERING_BEST_UNKNOWN_ACCESS_PATH_SUBSTRING:
450                 traceString =
451                     "in best unknown access path";
452                 break;
453
454             case COST_OF_CONGLOMERATE_SCAN1:
455                 cd = (ConglomerateDescriptor) objectParam1;
456                 cdString = dumpConglomerateDescriptor(cd);
457                 traceString =
458                     "Cost of conglomerate " +
459                     cdString +
460                     " scan for table number " +
461                     intParam1 + " is : ";
462                 break;
463
464             case COST_OF_CONGLOMERATE_SCAN2:
465                 traceString =
466                     objectParam1.toString();
467                 break;
468
469             case COST_OF_CONGLOMERATE_SCAN3:
470                 traceString =
471                     "\tNumber of extra first column predicates is : " +
472                     intParam1 +
473                     ", extra first column selectivity is : " +
474                     doubleParam;
475                 break;
476
477             case COST_OF_CONGLOMERATE_SCAN4:
478                 traceString =
479                     "\tNumber of extra start/stop predicates is : " +
480                     intParam1 +
481                     ", extra start/stop selectivity is : " +
482                     doubleParam;
483                 break;
484
485             case COST_OF_CONGLOMERATE_SCAN5:
486                 traceString =
487                     "\tNumber of extra qualifiers is : " +
488                     intParam1 +
489                     ", extra qualifier selectivity is : " +
490                     doubleParam;
491                 break;
492
493             case COST_OF_CONGLOMERATE_SCAN6:
494                 traceString =
495                     "\tNumber of extra non-qualifiers is : " +
496                     intParam1 +
497                     ", extra non-qualifier selectivity is : " +
498                     doubleParam;
499                 break;
500
501             case COST_OF_CONGLOMERATE_SCAN7:
502                 traceString =
503                     "\tNumber of start/stop statistics predicates is : " +
504                     intParam1 +
505                     ", statistics start/stop selectivity is : " +
506                     doubleParam;
507                 break;
508         }
509         if (SanityManager.DEBUG)
510         {
511             if (traceString == null)
512             {
513                 SanityManager.THROWASSERT(
514                     "traceString expected to be non-null");
515             }
516         }
517         lcc.appendOptimizerTraceOutput(traceString + "\n");
518     }
519
520     private String JavaDoc costForTable(Object JavaDoc cost, int tableNumber)
521     {
522         return cost + " for table " + tableNumber;
523     }
524
525     private String JavaDoc bestCost()
526     {
527         return "Best cost = " + bestCost + "\n";
528     }
529
530     private String JavaDoc buildJoinOrder(String JavaDoc prefix, boolean addJoinOrderNumber,
531                                   int joinOrderNumber, int[] joinOrder)
532     {
533         String JavaDoc joinOrderString = prefix;
534
535         for (int i = 0; i <= joinPosition; i++)
536         {
537             joinOrderString = joinOrderString + " " + joinOrder[i];
538         }
539         if (addJoinOrderNumber)
540         {
541             joinOrderString = joinOrderString + " " + joinOrderNumber;
542         }
543
544         return joinOrderString + " with assignedTableMap = " + assignedTableMap + "\n\n";
545     }
546
547     private String JavaDoc lockModeThreshold(
548                         String JavaDoc lockMode, String JavaDoc relop,
549                         double rowCount, int threshold)
550     {
551         return
552             "Lock mode set to " + lockMode +
553             " because estimated row count of " + rowCount +
554             " " + relop + " than threshold of " + threshold;
555     }
556
557     private String JavaDoc costIncluding(
558                     String JavaDoc selectivityType, Object JavaDoc objectParam1, int intParam1)
559     {
560         return
561             "Cost including extra " + selectivityType +
562             " start/stop selectivity is : " +
563             costForTable(objectParam1, intParam1);
564     }
565
566     private String JavaDoc dumpConglomerateDescriptor(ConglomerateDescriptor cd)
567     {
568         if (SanityManager.DEBUG)
569         {
570             return cd.toString();
571         }
572
573         String JavaDoc keyString = "";
574         String JavaDoc[] columnNames = cd.getColumnNames();
575
576         if (cd.isIndex() && columnNames != null )
577         {
578             IndexRowGenerator irg = cd.getIndexDescriptor();
579
580             int[] keyColumns = irg.baseColumnPositions();
581
582             keyString = ", key columns = {" + columnNames[keyColumns[0] - 1];
583             for (int index = 1; index < keyColumns.length; index++)
584             {
585                 keyString = keyString + ", " + columnNames[keyColumns[index] - 1];
586             }
587             keyString = keyString + "}";
588         }
589
590         return "CD: conglomerateNumber = " + cd.getConglomerateNumber() +
591                " name = " + cd.getConglomerateName() +
592                " uuid = " + cd.getUUID() +
593                " indexable = " + cd.isIndex() +
594                keyString;
595     }
596 }
597
Popular Tags