1 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.TableDescriptor; 44 45 import org.apache.derby.catalog.IndexDescriptor; 46 import org.apache.derby.iapi.reference.SQLState; 47 48 import org.apache.derby.iapi.util.JBitSet; 49 import org.apache.derby.iapi.util.StringUtil; 50 51 import java.util.Properties ; 52 import java.util.HashMap ; 53 54 71 72 public class OptimizerImpl implements Optimizer 73 { 74 75 DataDictionary dDictionary; 76 77 int numTablesInQuery; 78 79 int numOptimizables; 80 81 84 protected JBitSet assignedTableMap; 85 protected OptimizableList optimizableList; 86 OptimizablePredicateList predicateList; 87 JBitSet nonCorrelatedTableMap; 88 89 protected int[] proposedJoinOrder; 90 protected int[] bestJoinOrder; 91 protected int joinPosition; 92 boolean desiredJoinOrderFound; 93 94 101 private static final int NO_JUMP = 0; 102 private static final int READY_TO_JUMP = 1; 103 private static final int JUMPING = 2; 104 private static final int WALK_HIGH = 3; 105 private static final int WALK_LOW = 4; 106 private int permuteState; 107 private int[] firstLookOrder; 108 109 private boolean ruleBasedOptimization; 110 111 private CostEstimateImpl outermostCostEstimate; 112 protected CostEstimateImpl currentCost; 113 protected CostEstimateImpl currentSortAvoidanceCost; 114 protected CostEstimateImpl bestCost; 115 116 protected long timeOptimizationStarted; 117 protected long currentTime; 118 protected boolean timeExceeded; 119 private boolean noTimeout; 120 private boolean useStatistics; 121 private int tableLockThreshold; 122 123 private JoinStrategy[] joinStrategies; 124 125 protected RequiredRowOrdering requiredRowOrdering; 126 127 private boolean foundABestPlan; 128 129 protected CostEstimate sortCost; 130 131 private RowOrdering currentRowOrdering = new RowOrderingImpl(); 132 private RowOrdering bestRowOrdering = new RowOrderingImpl(); 133 134 private boolean conglomerate_OneRowResultSet; 135 136 protected boolean optimizerTrace; 138 protected boolean optimizerTraceHtml; 139 140 protected int maxMemoryPerTable; 142 143 private boolean reloadBestPlan; 150 151 private HashMap savedJoinOrders; 158 159 protected double timeLimit; 162 163 CostEstimate finalCostEstimate; 166 167 182 private boolean usingPredsPushedFromAbove; 183 private boolean bestJoinOrderUsedPredsFromAbove; 184 185 protected OptimizerImpl(OptimizableList optimizableList, 186 OptimizablePredicateList predicateList, 187 DataDictionary dDictionary, 188 boolean ruleBasedOptimization, 189 boolean noTimeout, 190 boolean useStatistics, 191 int maxMemoryPerTable, 192 JoinStrategy[] joinStrategies, 193 int tableLockThreshold, 194 RequiredRowOrdering requiredRowOrdering, 195 int numTablesInQuery) 196 throws StandardException 197 { 198 if (SanityManager.DEBUG) { 199 SanityManager.ASSERT(optimizableList != null, 200 "optimizableList is not expected to be null"); 201 } 202 203 outermostCostEstimate = getNewCostEstimate(0.0d, 1.0d, 1.0d); 204 205 currentCost = getNewCostEstimate(0.0d, 0.0d, 0.0d); 206 207 currentSortAvoidanceCost = getNewCostEstimate(0.0d, 0.0d, 0.0d); 208 209 bestCost = getNewCostEstimate(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); 210 211 optimizableList.verifyProperties(dDictionary); 213 214 this.numTablesInQuery = numTablesInQuery; 215 numOptimizables = optimizableList.size(); 216 proposedJoinOrder = new int[numOptimizables]; 217 if (numTablesInQuery > 6) 218 { 219 permuteState = READY_TO_JUMP; 220 firstLookOrder = new int[numOptimizables]; 221 } 222 else 223 permuteState = NO_JUMP; 224 225 226 for (int i = 0; i < numOptimizables; i++) 227 proposedJoinOrder[i] = -1; 228 229 bestJoinOrder = new int[numOptimizables]; 230 joinPosition = -1; 231 this.optimizableList = optimizableList; 232 this.predicateList = predicateList; 233 this.dDictionary = dDictionary; 234 this.ruleBasedOptimization = ruleBasedOptimization; 235 this.noTimeout = noTimeout; 236 this.maxMemoryPerTable = maxMemoryPerTable; 237 this.joinStrategies = joinStrategies; 238 this.tableLockThreshold = tableLockThreshold; 239 this.requiredRowOrdering = requiredRowOrdering; 240 this.useStatistics = useStatistics; 241 242 243 assignedTableMap = new JBitSet(numTablesInQuery); 244 245 251 nonCorrelatedTableMap = new JBitSet(numTablesInQuery); 252 for (int tabCtr = 0; tabCtr < numOptimizables; tabCtr++) 253 { 254 Optimizable curTable = optimizableList.getOptimizable(tabCtr); 255 nonCorrelatedTableMap.or(curTable.getReferencedTableMap()); 256 } 257 258 259 timeOptimizationStarted = System.currentTimeMillis(); 260 reloadBestPlan = false; 261 savedJoinOrders = null; 262 timeLimit = Double.MAX_VALUE; 263 264 usingPredsPushedFromAbove = false; 265 bestJoinOrderUsedPredsFromAbove = false; 266 } 267 268 277 public void prepForNextRound() 278 { 279 reloadBestPlan = false; 285 286 307 bestCost = getNewCostEstimate( 308 Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE); 309 310 325 usingPredsPushedFromAbove = false; 326 if ((predicateList != null) && (predicateList.size() > 0)) 327 { 328 for (int i = predicateList.size() - 1; i >= 0; i--) 329 { 330 if (((Predicate)predicateList. 333 getOptPredicate(i)).isScopedForPush()) 334 { 335 usingPredsPushedFromAbove = true; 336 break; 337 } 338 } 339 } 340 341 if (usingPredsPushedFromAbove) 342 { 343 timeOptimizationStarted = System.currentTimeMillis(); 344 timeExceeded = false; 345 } 346 347 356 desiredJoinOrderFound = false; 357 } 358 359 public int getMaxMemoryPerTable() 360 { 361 return maxMemoryPerTable; 362 } 363 364 369 public boolean getNextPermutation() 370 throws StandardException 371 { 372 373 if (numOptimizables < 1) 374 { 375 if (optimizerTrace) 376 { 377 trace(NO_TABLES, 0, 0, 0.0, null); 378 } 379 380 endOfRoundCleanup(); 381 return false; 382 } 383 384 388 optimizableList.initAccessPaths(this); 389 390 397 if ( ( ! timeExceeded ) && 398 (numTablesInQuery > 6) && 399 ( ! noTimeout) ) 400 { 401 405 currentTime = System.currentTimeMillis(); 406 timeExceeded = (currentTime - timeOptimizationStarted) > timeLimit; 407 408 if (optimizerTrace && timeExceeded) 409 { 410 trace(TIME_EXCEEDED, 0, 0, 0.0, null); 411 } 412 } 413 414 if (bestCost.isUninitialized() && foundABestPlan && 415 ((!usingPredsPushedFromAbove && !bestJoinOrderUsedPredsFromAbove) 416 || timeExceeded)) 417 { 418 455 if (permuteState != JUMPING) 456 { 457 if (firstLookOrder == null) 463 firstLookOrder = new int[numOptimizables]; 464 for (int i = 0; i < numOptimizables; i++) 465 firstLookOrder[i] = bestJoinOrder[i]; 466 permuteState = JUMPING; 467 468 482 if (joinPosition >= 0) 483 { 484 rewindJoinOrder(); 485 joinPosition = -1; 486 } 487 } 488 489 timeExceeded = false; 496 } 497 498 506 boolean joinPosAdvanced = false; 507 508 523 boolean alreadyCostsMore = 524 !bestCost.isUninitialized() && 525 (currentCost.compare(bestCost) > 0) && 526 ((requiredRowOrdering == null) || 527 (currentSortAvoidanceCost.compare(bestCost) > 0)); 528 529 if ((joinPosition < (numOptimizables - 1)) && 530 !alreadyCostsMore && 531 ( ! timeExceeded ) 532 ) 533 { 534 540 if ((joinPosition < 0) || 541 optimizableList.getOptimizable( 542 proposedJoinOrder[joinPosition]). 543 getBestAccessPath().getCostEstimate() != null) 544 { 545 joinPosition++; 546 joinPosAdvanced = true; 547 548 553 bestRowOrdering.copy(currentRowOrdering); 554 } 555 } 556 else 557 { 558 if (optimizerTrace) 559 { 560 564 if (joinPosition < (numOptimizables - 1)) 565 { 566 trace(SHORT_CIRCUITING, 0, 0, 0.0, null); 567 } 568 } 569 570 if (joinPosition < (numOptimizables - 1)) 578 reloadBestPlan = true; 579 } 580 581 if (permuteState == JUMPING && !joinPosAdvanced && joinPosition >= 0) 582 { 583 reloadBestPlan = true; 589 rewindJoinOrder(); permuteState = NO_JUMP; } 592 593 597 while (joinPosition >= 0) 598 { 599 int nextOptimizable = 0; 600 601 if (desiredJoinOrderFound || timeExceeded) 602 { 603 612 nextOptimizable = numOptimizables; 613 } 614 else if (permuteState == JUMPING) { 616 675 676 int idealOptimizable = firstLookOrder[joinPosition]; 677 nextOptimizable = idealOptimizable; 678 int lookPos = numOptimizables; 679 int lastSwappedOpt = -1; 680 681 Optimizable nextOpt; 682 for (nextOpt = optimizableList.getOptimizable(nextOptimizable); 683 !(nextOpt.legalJoinOrder(assignedTableMap)); 684 nextOpt = optimizableList.getOptimizable(nextOptimizable)) 685 { 686 if (lastSwappedOpt >= 0) { 688 firstLookOrder[joinPosition] = idealOptimizable; 689 firstLookOrder[lookPos] = lastSwappedOpt; 690 } 691 692 if (lookPos > joinPosition + 1) { 693 lastSwappedOpt = firstLookOrder[--lookPos]; 696 firstLookOrder[joinPosition] = lastSwappedOpt; 697 firstLookOrder[lookPos] = idealOptimizable; 698 nextOptimizable = lastSwappedOpt; 699 } 700 else { 701 if (joinPosition > 0) { 709 joinPosition--; 710 reloadBestPlan = true; 711 rewindJoinOrder(); 712 } 713 permuteState = NO_JUMP; 714 break; 715 } 716 } 717 718 if (permuteState == NO_JUMP) 719 continue; 720 721 if (joinPosition == numOptimizables - 1) { 722 permuteState = WALK_HIGH; 735 } 736 } 737 else 738 { 739 740 nextOptimizable = proposedJoinOrder[joinPosition] + 1; 741 742 for ( ; nextOptimizable < numOptimizables; nextOptimizable++) 743 { 744 boolean found = false; 745 for (int posn = 0; posn < joinPosition; posn++) 746 { 747 751 if (proposedJoinOrder[posn] == nextOptimizable) 752 { 753 found = true; 754 break; 755 } 756 } 757 758 761 if (nextOptimizable < numOptimizables) 762 { 763 Optimizable nextOpt = 764 optimizableList.getOptimizable(nextOptimizable); 765 if (! (nextOpt.legalJoinOrder(assignedTableMap))) 766 { 767 if (optimizerTrace) 768 { 769 trace(SKIPPING_JOIN_ORDER, nextOptimizable, 0, 0.0, null); 770 } 771 772 775 if ( ! optimizableList.optimizeJoinOrder()) 776 { 777 if (optimizerTrace) 778 { 779 trace(ILLEGAL_USER_JOIN_ORDER, 0, 0, 0.0, null); 780 } 781 782 throw StandardException.newException(SQLState.LANG_ILLEGAL_FORCED_JOIN_ORDER); 783 } 784 continue; 785 } 786 } 787 788 if (! found) 789 { 790 break; 791 } 792 } 793 794 } 795 796 800 if (proposedJoinOrder[joinPosition] >= 0) 801 { 802 809 Optimizable pullMe = 810 optimizableList.getOptimizable( 811 proposedJoinOrder[joinPosition]); 812 813 821 double prevRowCount; 822 double prevSingleScanRowCount; 823 int prevPosition = 0; 824 if (joinPosition == 0) 825 { 826 prevRowCount = outermostCostEstimate.rowCount(); 827 prevSingleScanRowCount = outermostCostEstimate.singleScanRowCount(); 828 } 829 else 830 { 831 prevPosition = proposedJoinOrder[joinPosition - 1]; 832 CostEstimate localCE = 833 optimizableList. 834 getOptimizable(prevPosition). 835 getBestAccessPath(). 836 getCostEstimate(); 837 prevRowCount = localCE.rowCount(); 838 prevSingleScanRowCount = localCE.singleScanRowCount(); 839 } 840 841 848 double newCost = currentCost.getEstimatedCost(); 849 double pullCost = 0.0; 850 CostEstimate pullCostEstimate = 851 pullMe.getBestAccessPath().getCostEstimate(); 852 if (pullCostEstimate != null) 853 { 854 pullCost = pullCostEstimate.getEstimatedCost(); 855 856 newCost -= pullCost; 857 858 862 if (newCost < 0.0) 863 newCost = 0.0; 864 } 865 866 871 if (joinPosition == 0) 872 { 873 if (outermostCostEstimate != null) 874 { 875 newCost = outermostCostEstimate.getEstimatedCost(); 876 } 877 else 878 { 879 newCost = 0.0; 880 } 881 } 882 883 currentCost.setCost( 884 newCost, 885 prevRowCount, 886 prevSingleScanRowCount); 887 888 897 if (requiredRowOrdering != null) 898 { 899 if (pullMe.considerSortAvoidancePath()) 900 { 901 AccessPath ap = pullMe.getBestSortAvoidancePath(); 902 double prevEstimatedCost = 0.0d; 903 904 913 if (joinPosition == 0) 914 { 915 prevRowCount = outermostCostEstimate.rowCount(); 916 prevSingleScanRowCount = outermostCostEstimate.singleScanRowCount(); 917 922 prevEstimatedCost = outermostCostEstimate.getEstimatedCost(); 923 } 924 else 925 { 926 CostEstimate localCE = 927 optimizableList. 928 getOptimizable(prevPosition). 929 getBestSortAvoidancePath(). 930 getCostEstimate(); 931 prevRowCount = localCE.rowCount(); 932 prevSingleScanRowCount = localCE.singleScanRowCount(); 933 prevEstimatedCost = currentSortAvoidanceCost.getEstimatedCost() - 934 ap.getCostEstimate().getEstimatedCost(); 935 } 936 937 currentSortAvoidanceCost.setCost( 938 prevEstimatedCost, 939 prevRowCount, 940 prevSingleScanRowCount); 941 942 949 bestRowOrdering.removeOptimizable( 950 pullMe.getTableNumber()); 951 952 958 bestRowOrdering.copy(currentRowOrdering); 959 } 960 } 961 962 971 pullMe.pullOptPredicates(predicateList); 972 973 997 if (reloadBestPlan) 998 pullMe.updateBestPlanMap(FromTable.LOAD_PLAN, this); 999 1000 1001 proposedJoinOrder[joinPosition] = -1; 1002 } 1003 1004 1005 if (nextOptimizable >= numOptimizables) 1006 { 1007 1011 if ( ! optimizableList.optimizeJoinOrder()) 1012 { 1013 if ( ! optimizableList.legalJoinOrder(numTablesInQuery)) 1015 { 1016 if (optimizerTrace) 1017 { 1018 trace(ILLEGAL_USER_JOIN_ORDER, 0, 0, 0.0, null); 1019 } 1020 1021 throw StandardException.newException(SQLState.LANG_ILLEGAL_FORCED_JOIN_ORDER); 1022 } 1023 1024 if (optimizerTrace) 1025 { 1026 trace(USER_JOIN_ORDER_OPTIMIZED, 0, 0, 0.0, null); 1027 } 1028 1029 desiredJoinOrderFound = true; 1030 } 1031 1032 if (permuteState == READY_TO_JUMP && joinPosition > 0 && joinPosition == numOptimizables-1) 1033 { 1034 permuteState = JUMPING; 1035 1036 1040 double rc[] = new double[numOptimizables]; 1041 for (int i = 0; i < numOptimizables; i++) 1042 { 1043 firstLookOrder[i] = i; 1044 CostEstimate ce = optimizableList.getOptimizable(i). 1045 getBestAccessPath().getCostEstimate(); 1046 if (ce == null) 1047 { 1048 permuteState = READY_TO_JUMP; break; 1050 } 1051 rc[i] = ce.singleScanRowCount(); 1052 } 1053 if (permuteState == JUMPING) 1054 { 1055 boolean doIt = false; 1056 int temp; 1057 for (int i = 0; i < numOptimizables; i++) { 1059 int k = i; 1060 for (int j = i+1; j < numOptimizables; j++) 1061 if (rc[j] < rc[k]) k = j; 1062 if (k != i) 1063 { 1064 rc[k] = rc[i]; temp = firstLookOrder[i]; 1066 firstLookOrder[i] = firstLookOrder[k]; 1067 firstLookOrder[k] = temp; 1068 doIt = true; 1069 } 1070 } 1071 1072 if (doIt) 1073 { 1074 joinPosition--; 1075 rewindJoinOrder(); continue; 1077 } 1078 else permuteState = NO_JUMP; } 1080 } 1081 1082 1086 1087 1088 joinPosition--; 1089 1090 1093 if (joinPosition >= 0) 1094 { 1095 Optimizable pullMe = 1096 optimizableList.getOptimizable( 1097 proposedJoinOrder[joinPosition]); 1098 1099 1104 assignedTableMap.xor(pullMe.getReferencedTableMap()); 1105 } 1106 1107 if (joinPosition < 0 && permuteState == WALK_HIGH) { 1109 joinPosition = 0; permuteState = WALK_LOW; 1111 } 1112 continue; 1113 } 1114 1115 1118 proposedJoinOrder[joinPosition] = nextOptimizable; 1119 1120 if (permuteState == WALK_LOW) 1121 { 1122 boolean finishedCycle = true; 1123 for (int i = 0; i < numOptimizables; i++) 1124 { 1125 if (proposedJoinOrder[i] < firstLookOrder[i]) 1126 { 1127 finishedCycle = false; 1128 break; 1129 } 1130 else if (proposedJoinOrder[i] > firstLookOrder[i]) break; 1132 } 1133 if (finishedCycle) 1134 { 1135 proposedJoinOrder[joinPosition] = -1; 1144 joinPosition--; 1145 if (joinPosition >= 0) 1146 { 1147 reloadBestPlan = true; 1148 rewindJoinOrder(); 1149 joinPosition = -1; 1150 } 1151 1152 permuteState = READY_TO_JUMP; 1153 endOfRoundCleanup(); 1154 return false; 1155 } 1156 } 1157 1158 1161 optimizableList.getOptimizable(nextOptimizable). 1162 getBestAccessPath().setCostEstimate((CostEstimate) null); 1163 1164 1167 assignedTableMap.clearAll(); 1168 for (int index = 0; index <= joinPosition; index++) 1169 { 1170 assignedTableMap.or(optimizableList.getOptimizable(proposedJoinOrder[index]).getReferencedTableMap()); 1171 } 1172 1173 if (optimizerTrace) 1174 { 1175 trace(CONSIDERING_JOIN_ORDER, 0, 0, 0.0, null); 1176 } 1177 1178 Optimizable nextOpt = 1179 optimizableList.getOptimizable(nextOptimizable); 1180 1181 nextOpt.startOptimizing(this, currentRowOrdering); 1182 1183 pushPredicates( 1184 optimizableList.getOptimizable(nextOptimizable), 1185 assignedTableMap); 1186 1187 return true; 1188 } 1189 1190 endOfRoundCleanup(); 1191 return false; 1192 } 1193 1194 private void rewindJoinOrder() 1195 throws StandardException 1196 { 1197 for (; ; joinPosition--) 1198 { 1199 Optimizable pullMe = 1200 optimizableList.getOptimizable( 1201 proposedJoinOrder[joinPosition]); 1202 pullMe.pullOptPredicates(predicateList); 1203 if (reloadBestPlan) 1204 pullMe.updateBestPlanMap(FromTable.LOAD_PLAN, this); 1205 proposedJoinOrder[joinPosition] = -1; 1206 if (joinPosition == 0) break; 1207 } 1208 currentCost.setCost(0.0d, 0.0d, 0.0d); 1209 currentSortAvoidanceCost.setCost(0.0d, 0.0d, 0.0d); 1210 assignedTableMap.clearAll(); 1211 } 1212 1213 1222 private void endOfRoundCleanup() 1223 throws StandardException 1224 { 1225 for (int i = 0; i < numOptimizables; i++) 1226 { 1227 optimizableList.getOptimizable(i). 1228 updateBestPlanMap(FromTable.REMOVE_PLAN, this); 1229 } 1230 } 1231 1232 1241 void pushPredicates(Optimizable curTable, JBitSet outerTables) 1242 throws StandardException 1243 { 1244 1249 1250 int numPreds = predicateList.size(); 1251 JBitSet predMap = new JBitSet(numTablesInQuery); 1252 JBitSet curTableNums = null; 1253 BaseTableNumbersVisitor btnVis = null; 1254 boolean pushPredNow = false; 1255 int tNum; 1256 Predicate pred; 1257 1258 1265 for (int predCtr = numPreds - 1; predCtr >= 0; predCtr--) 1266 { 1267 pred = (Predicate)predicateList.getOptPredicate(predCtr); 1268 1269 1270 if (! isPushable(pred)) 1271 { 1272 continue; 1273 } 1274 1275 1278 predMap.setTo(pred.getReferencedMap()); 1279 1280 1285 for (int index = 0; index < predMap.size(); index++) 1286 { 1287 if (outerTables.get(index)) 1288 { 1289 predMap.clear(index); 1290 } 1291 } 1292 1293 1297 predMap.and(nonCorrelatedTableMap); 1298 1299 1321 pushPredNow = (predMap.getFirstSetBit() == -1); 1322 1323 1359 if (pushPredNow && pred.isScopedForPush() && (numOptimizables > 1)) 1360 { 1361 if (btnVis == null) 1362 { 1363 curTableNums = new JBitSet(numTablesInQuery); 1364 btnVis = new BaseTableNumbersVisitor(curTableNums); 1365 } 1366 1367 1380 tNum = ((FromTable)curTable).getTableNumber(); 1381 curTableNums.clearAll(); 1382 btnVis.setTableMap(curTableNums); 1383 ((FromTable)curTable).accept(btnVis); 1384 if (tNum >= 0) 1385 curTableNums.set(tNum); 1386 1387 btnVis.setTableMap(predMap); 1388 pred.accept(btnVis); 1389 1390 predMap.and(curTableNums); 1391 if ((predMap.getFirstSetBit() == -1)) 1392 pushPredNow = false; 1393 } 1394 1395 1400 if (pushPredNow) 1401 { 1402 1403 if (curTable.pushOptPredicate(pred)) 1404 { 1405 predicateList.removeOptPredicate(predCtr); 1406 } 1407 } 1408 } 1409 } 1410 1411 1416 public boolean getNextDecoratedPermutation() 1417 throws StandardException 1418 { 1419 boolean retval; 1420 Optimizable curOpt = 1421 optimizableList.getOptimizable(proposedJoinOrder[joinPosition]); 1422 double originalRowCount = 0.0; 1423 1424 1426 1427 retval = curOpt.nextAccessPath(this, 1428 (OptimizablePredicateList) null, 1429 currentRowOrdering); 1430 1431 if ((curOpt.getBestAccessPath().getCostEstimate() != null) && 1437 (curOpt.getCurrentAccessPath().getCostEstimate() != null)) 1438 { 1439 if (curOpt.getBestAccessPath().getCostEstimate().compare( 1447 curOpt.getCurrentAccessPath().getCostEstimate()) != 0) 1448 { 1449 curOpt.updateBestPlanMap(FromTable.LOAD_PLAN, curOpt); 1450 } 1451 else if (curOpt.getBestAccessPath().getCostEstimate().rowCount() < 1452 curOpt.getCurrentAccessPath().getCostEstimate().rowCount()) 1453 { 1454 curOpt.updateBestPlanMap(FromTable.LOAD_PLAN, curOpt); 1460 } 1461 } 1462 1463 1468 curOpt.updateBestPlanMap(FromTable.REMOVE_PLAN, curOpt); 1469 1470 1476 CostEstimate ce = curOpt.getBestAccessPath().getCostEstimate(); 1477 if ( ( ! retval ) && (ce != null)) 1478 { 1479 1485 currentCost.setCost( 1486 currentCost.getEstimatedCost() + ce.getEstimatedCost(), 1487 ce.rowCount(), 1488 ce.singleScanRowCount()); 1489 1490 if (curOpt.considerSortAvoidancePath() && 1491 requiredRowOrdering != null) 1492 { 1493 1494 ce = curOpt.getBestSortAvoidancePath().getCostEstimate(); 1495 1496 currentSortAvoidanceCost.setCost( 1497 currentSortAvoidanceCost.getEstimatedCost() + 1498 ce.getEstimatedCost(), 1499 ce.rowCount(), 1500 ce.singleScanRowCount()); 1501 } 1502 1503 if (optimizerTrace) 1504 { 1505 trace(TOTAL_COST_NON_SA_PLAN, 0, 0, 0.0, null); 1506 if (curOpt.considerSortAvoidancePath()) 1507 { 1508 trace(TOTAL_COST_SA_PLAN, 0, 0, 0.0, null); 1509 } 1510 } 1511 1512 1513 if ( joinPosition == (numOptimizables - 1) ) 1514 { 1515 if (optimizerTrace) 1516 { 1517 trace(COMPLETE_JOIN_ORDER, 0, 0, 0.0, null); 1518 } 1519 1520 1521 if (requiredRowOrdering != null) 1522 { 1523 boolean gotSortCost = false; 1524 1525 1526 if (sortCost == null) 1527 { 1528 sortCost = newCostEstimate(); 1529 } 1530 1547 else if (requiredRowOrdering.getSortNeeded()) 1548 { 1549 if (bestCost.rowCount() > currentCost.rowCount()) 1550 { 1551 requiredRowOrdering.estimateCost( 1553 bestCost.rowCount(), 1554 bestRowOrdering, 1555 sortCost 1556 ); 1557 double oldSortCost = sortCost.getEstimatedCost(); 1558 requiredRowOrdering.estimateCost( 1559 currentCost.rowCount(), 1560 bestRowOrdering, 1561 sortCost 1562 ); 1563 gotSortCost = true; 1564 bestCost.setCost(bestCost.getEstimatedCost() - 1565 oldSortCost + 1566 sortCost.getEstimatedCost(), 1567 sortCost.rowCount(), 1568 currentCost.singleScanRowCount()); 1569 } 1570 else if (bestCost.rowCount() < currentCost.rowCount()) 1571 { 1572 currentCost.setCost(currentCost.getEstimatedCost(), 1574 bestCost.rowCount(), 1575 currentCost.singleScanRowCount()); 1576 } 1577 } 1578 1579 1583 if (! gotSortCost) 1584 { 1585 requiredRowOrdering.estimateCost( 1586 currentCost.rowCount(), 1587 bestRowOrdering, 1588 sortCost 1589 ); 1590 } 1591 1592 originalRowCount = currentCost.rowCount(); 1593 1594 currentCost.setCost(currentCost.getEstimatedCost() + 1595 sortCost.getEstimatedCost(), 1596 sortCost.rowCount(), 1597 currentCost.singleScanRowCount() 1598 ); 1599 1600 if (optimizerTrace) 1601 { 1602 trace(COST_OF_SORTING, 0, 0, 0.0, null); 1603 trace(TOTAL_COST_WITH_SORTING, 0, 0, 0.0, null); 1604 } 1605 } 1606 1607 1629 if ((! foundABestPlan) || 1630 (currentCost.compare(bestCost) < 0) || 1631 bestCost.isUninitialized()) 1632 { 1633 rememberBestCost(currentCost, Optimizer.NORMAL_PLAN); 1634 1635 reloadBestPlan = false; 1639 } 1640 else 1641 reloadBestPlan = true; 1642 1643 1644 if (requiredRowOrdering != null) 1645 { 1646 1649 double newCost = currentCost.getEstimatedCost() - 1650 sortCost.getEstimatedCost(); 1651 if (newCost < 0.0) 1652 newCost = 0.0; 1653 1654 currentCost.setCost(newCost, 1655 originalRowCount, 1656 currentCost.singleScanRowCount() 1657 ); 1658 } 1659 1660 1665 if (requiredRowOrdering != null && 1666 curOpt.considerSortAvoidancePath()) 1667 { 1668 if (requiredRowOrdering.sortRequired(bestRowOrdering) == 1669 RequiredRowOrdering.NOTHING_REQUIRED) 1670 { 1671 if (optimizerTrace) 1672 { 1673 trace(CURRENT_PLAN_IS_SA_PLAN, 0, 0, 0.0, null); 1674 } 1675 1676 if ((currentSortAvoidanceCost.compare(bestCost) <= 0) 1677 || bestCost.isUninitialized()) 1678 { 1679 rememberBestCost(currentSortAvoidanceCost, 1680 Optimizer.SORT_AVOIDANCE_PLAN); 1681 } 1682 } 1683 } 1684 } 1685 } 1686 1687 return retval; 1688 } 1689 1690 1699 private void rememberBestCost(CostEstimate currentCost, int planType) 1700 throws StandardException 1701 { 1702 foundABestPlan = true; 1703 1704 if (optimizerTrace) 1705 { 1706 trace(CHEAPEST_PLAN_SO_FAR, 0, 0, 0.0, null); 1707 trace(PLAN_TYPE, planType, 0, 0.0, null); 1708 trace(COST_OF_CHEAPEST_PLAN_SO_FAR, 0, 0, 0.0, null); 1709 } 1710 1711 1712 bestCost.setCost(currentCost); 1713 1714 if (bestCost.getEstimatedCost() < timeLimit) 1721 timeLimit = bestCost.getEstimatedCost(); 1722 1723 1730 bestJoinOrderUsedPredsFromAbove = usingPredsPushedFromAbove; 1731 for (int i = 0; i < numOptimizables; i++) 1732 { 1733 bestJoinOrder[i] = proposedJoinOrder[i]; 1734 } 1735 for (int i = 0; i < numOptimizables; i++) 1736 { 1737 optimizableList.getOptimizable(bestJoinOrder[i]). 1738 rememberAsBest(planType, this); 1739 } 1740 1741 1742 if (requiredRowOrdering != null) 1743 { 1744 if (planType == Optimizer.SORT_AVOIDANCE_PLAN) 1745 requiredRowOrdering.sortNotNeeded(); 1746 else 1747 requiredRowOrdering.sortNeeded(); 1748 } 1749 1750 if (optimizerTrace) 1751 { 1752 if (requiredRowOrdering != null) 1753 { 1754 trace(SORT_NEEDED_FOR_ORDERING, planType, 0, 0.0, null); 1755 } 1756 trace(REMEMBERING_BEST_JOIN_ORDER, 0, 0, 0.0, null); 1757 } 1758 } 1759 1760 1765 public void costPermutation() throws StandardException 1766 { 1767 1771 CostEstimate outerCost; 1772 if (joinPosition == 0) 1773 { 1774 outerCost = outermostCostEstimate; 1775 } 1776 else 1777 { 1778 1785 outerCost = 1786 optimizableList.getOptimizable( 1787 proposedJoinOrder[joinPosition - 1]). 1788 getBestAccessPath().getCostEstimate(); 1789 } 1790 1791 1797 if (SanityManager.DEBUG) 1798 { 1799 SanityManager.ASSERT(outerCost != null, 1800 "outerCost is not expected to be null"); 1801 } 1802 1803 Optimizable optimizable = optimizableList.getOptimizable(proposedJoinOrder[joinPosition]); 1804 1805 1808 if ( ! optimizable.feasibleJoinStrategy(predicateList, this)) 1809 { 1810 return; 1811 } 1812 1813 1814 optimizable.optimizeIt(this, 1815 predicateList, 1816 outerCost, 1817 currentRowOrdering); 1818 } 1819 1820 1825 public void costOptimizable(Optimizable optimizable, 1826 TableDescriptor td, 1827 ConglomerateDescriptor cd, 1828 OptimizablePredicateList predList, 1829 CostEstimate outerCost) 1830 throws StandardException 1831 { 1832 1835 if ( ! optimizable.feasibleJoinStrategy(predList, this)) 1836 { 1837 return; 1838 } 1839 1840 1847 1850 if (ruleBasedOptimization) 1851 { 1852 ruleBasedCostOptimizable(optimizable, 1853 td, 1854 cd, 1855 predList, 1856 outerCost); 1857 } 1858 else 1859 { 1860 costBasedCostOptimizable(optimizable, 1861 td, 1862 cd, 1863 predList, 1864 outerCost); 1865 } 1866 } 1867 1868 1891 private void ruleBasedCostOptimizable(Optimizable optimizable, 1892 TableDescriptor td, 1893 ConglomerateDescriptor cd, 1894 OptimizablePredicateList predList, 1895 CostEstimate outerCost) 1896 throws StandardException 1897 { 1898 1899 ConglomerateDescriptor conglomerateDescriptor = null; 1900 ConglomerateDescriptor bestConglomerateDescriptor = null; 1901 AccessPath bestAp = optimizable.getBestAccessPath(); 1902 int lockMode = optimizable.getCurrentAccessPath().getLockMode(); 1903 1904 1905 1914 1915 1919 if (predList != null && 1920 predList.useful(optimizable, cd)) 1921 { 1922 1926 boolean newCoveringIndex = optimizable.isCoveringIndex(cd); 1927 if ( ( ! bestAp.getCoveringIndexScan()) || 1928 bestAp.getNonMatchingIndexScan() || 1929 newCoveringIndex ) 1930 { 1931 bestAp.setCostEstimate( 1932 estimateTotalCost( 1933 predList, 1934 cd, 1935 outerCost, 1936 optimizable 1937 ) 1938 ); 1939 bestAp.setConglomerateDescriptor(cd); 1940 bestAp.setNonMatchingIndexScan(false); 1941 bestAp.setCoveringIndexScan(newCoveringIndex); 1942 1943 bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode()); 1944 1945 optimizable.rememberJoinStrategyAsBest(bestAp); 1946 } 1947 1948 return; 1949 } 1950 1951 1955 if (optimizable.isCoveringIndex(cd)) 1956 { 1957 bestAp.setCostEstimate( 1958 estimateTotalCost(predList, 1959 cd, 1960 outerCost, 1961 optimizable) 1962 ); 1963 bestAp.setConglomerateDescriptor(cd); 1964 bestAp.setNonMatchingIndexScan(true); 1965 bestAp.setCoveringIndexScan(true); 1966 1967 bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode()); 1968 1969 optimizable.rememberJoinStrategyAsBest(bestAp); 1970 return; 1971 } 1972 1973 1977 if ( ( ! bestAp.getCoveringIndexScan()) && 1978 bestAp.getNonMatchingIndexScan() && 1979 ( ! cd.isIndex() ) 1980 ) 1981 { 1982 bestAp.setCostEstimate( 1983 estimateTotalCost(predList, 1984 cd, 1985 outerCost, 1986 optimizable) 1987 ); 1988 1989 bestAp.setConglomerateDescriptor(cd); 1990 1991 bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode()); 1992 1993 optimizable.rememberJoinStrategyAsBest(bestAp); 1994 1995 1999 return; 2000 } 2001 2002 2003 2007 bestConglomerateDescriptor = bestAp.getConglomerateDescriptor(); 2008 if (bestConglomerateDescriptor == null) 2009 { 2010 bestAp.setCostEstimate( 2011 estimateTotalCost(predList, 2012 cd, 2013 outerCost, 2014 optimizable) 2015 ); 2016 2017 bestAp.setConglomerateDescriptor(cd); 2018 2019 2023 bestAp.setCoveringIndexScan(false); 2024 bestAp.setNonMatchingIndexScan(cd.isIndex()); 2025 2026 bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode()); 2027 2028 optimizable.rememberJoinStrategyAsBest(bestAp); 2029 } 2030 2031 return; 2032 } 2033 2034 2040 private void costBasedCostOptimizable(Optimizable optimizable, 2041 TableDescriptor td, 2042 ConglomerateDescriptor cd, 2043 OptimizablePredicateList predList, 2044 CostEstimate outerCost) 2045 throws StandardException 2046 { 2047 CostEstimate estimatedCost = estimateTotalCost(predList, 2048 cd, 2049 outerCost, 2050 optimizable); 2051 2052 optimizable.getCurrentAccessPath().setCostEstimate(estimatedCost); 2060 2061 2068 if( ! optimizable.memoryUsageOK( estimatedCost.rowCount() / outerCost.rowCount(), maxMemoryPerTable)) 2072 { 2073 if (optimizerTrace) 2074 { 2075 trace(SKIPPING_DUE_TO_EXCESS_MEMORY, 0, 0, 0.0, null); 2076 } 2077 return; 2078 } 2079 2080 2081 AccessPath ap = optimizable.getBestAccessPath(); 2082 CostEstimate bestCostEstimate = ap.getCostEstimate(); 2083 2084 if ((bestCostEstimate == null) || 2085 bestCostEstimate.isUninitialized() || 2086 (estimatedCost.compare(bestCostEstimate) < 0)) 2087 { 2088 ap.setConglomerateDescriptor(cd); 2089 ap.setCostEstimate(estimatedCost); 2090 ap.setCoveringIndexScan(optimizable.isCoveringIndex(cd)); 2091 2092 2097 ap.setNonMatchingIndexScan( 2098 (predList == null) || 2099 ( ! ( predList.useful(optimizable, cd) ) ) 2100 ); 2101 ap.setLockMode(optimizable.getCurrentAccessPath().getLockMode()); 2102 optimizable.rememberJoinStrategyAsBest(ap); 2103 } 2104 2105 2109 if (requiredRowOrdering != null) 2110 { 2111 2115 if (joinPosition == 0 || 2116 optimizableList.getOptimizable( 2117 proposedJoinOrder[joinPosition - 1]). 2118 considerSortAvoidancePath()) 2119 { 2120 2124 if (requiredRowOrdering.sortRequired(currentRowOrdering, 2125 assignedTableMap) 2126 == RequiredRowOrdering.NOTHING_REQUIRED) 2127 { 2128 ap = optimizable.getBestSortAvoidancePath(); 2129 bestCostEstimate = ap.getCostEstimate(); 2130 2131 2132 if ((bestCostEstimate == null) || 2133 bestCostEstimate.isUninitialized() || 2134 (estimatedCost.compare(bestCostEstimate) < 0)) 2135 { 2136 ap.setConglomerateDescriptor(cd); 2137 ap.setCostEstimate(estimatedCost); 2138 ap.setCoveringIndexScan( 2139 optimizable.isCoveringIndex(cd)); 2140 2141 2146 ap.setNonMatchingIndexScan( 2147 (predList == null) || 2148 ( ! (predList.useful(optimizable, cd)) ) 2149 ); 2150 ap.setLockMode( 2151 optimizable.getCurrentAccessPath().getLockMode()); 2152 optimizable.rememberJoinStrategyAsBest(ap); 2153 optimizable.rememberSortAvoidancePath(); 2154 2155 2158 currentRowOrdering.copy(bestRowOrdering); 2159 } 2160 } 2161 } 2162 } 2163 } 2164 2165 2172 public void considerCost(Optimizable optimizable, 2173 OptimizablePredicateList predList, 2174 CostEstimate estimatedCost, 2175 CostEstimate outerCost) 2176 throws StandardException 2177 { 2178 2181 if ( ! optimizable.feasibleJoinStrategy(predList, this)) 2182 { 2183 return; 2184 } 2185 2186 optimizable.getCurrentAccessPath().setCostEstimate(estimatedCost); 2194 2195 2202 2203 if( ! optimizable.memoryUsageOK( estimatedCost.rowCount() / outerCost.rowCount(), 2207 maxMemoryPerTable)) 2208 { 2209 if (optimizerTrace) 2210 { 2211 trace(SKIPPING_DUE_TO_EXCESS_MEMORY, 0, 0, 0.0, null); 2212 } 2213 return; 2214 } 2215 2216 2225 AccessPath ap = optimizable.getBestAccessPath(); 2226 CostEstimate bestCostEstimate = ap.getCostEstimate(); 2227 2228 if ((bestCostEstimate == null) || 2229 bestCostEstimate.isUninitialized() || 2230 (estimatedCost.compare(bestCostEstimate) <= 0)) 2231 { 2232 ap.setCostEstimate(estimatedCost); 2233 optimizable.rememberJoinStrategyAsBest(ap); 2234 } 2235 2236 2240 if (requiredRowOrdering != null) 2241 { 2242 2246 if (joinPosition == 0 || 2247 optimizableList.getOptimizable( 2248 proposedJoinOrder[joinPosition - 1]). 2249 considerSortAvoidancePath()) 2250 { 2251 2255 if (requiredRowOrdering.sortRequired(currentRowOrdering, 2256 assignedTableMap) 2257 == RequiredRowOrdering.NOTHING_REQUIRED) 2258 { 2259 ap = optimizable.getBestSortAvoidancePath(); 2260 bestCostEstimate = ap.getCostEstimate(); 2261 2262 2263 if ((bestCostEstimate == null) || 2264 bestCostEstimate.isUninitialized() || 2265 (estimatedCost.compare(bestCostEstimate) < 0)) 2266 { 2267 ap.setCostEstimate(estimatedCost); 2268 optimizable.rememberJoinStrategyAsBest(ap); 2269 optimizable.rememberSortAvoidancePath(); 2270 2271 2274 currentRowOrdering.copy(bestRowOrdering); 2275 } 2276 } 2277 } 2278 } 2279 } 2280 2281 2284 2285 public DataDictionary getDataDictionary() 2286 { 2287 return dDictionary; 2288 } 2289 2290 2295 public void modifyAccessPaths() throws StandardException 2296 { 2297 if (optimizerTrace) 2298 { 2299 trace(MODIFYING_ACCESS_PATHS, 0, 0, 0.0, null); 2300 } 2301 2302 if ( ! foundABestPlan) 2303 { 2304 if (optimizerTrace) 2305 { 2306 trace(NO_BEST_PLAN, 0, 0, 0.0, null); 2307 } 2308 2309 throw StandardException.newException(SQLState.LANG_NO_BEST_PLAN_FOUND); 2310 } 2311 2312 2313 optimizableList.reOrder(bestJoinOrder); 2314 2315 2316 JBitSet outerTables = new JBitSet(numOptimizables); 2317 2318 2319 for (int ictr = 0; ictr < numOptimizables; ictr++) 2320 { 2321 Optimizable optimizable = optimizableList.getOptimizable(ictr); 2322 2323 2324 outerTables.or(optimizable.getReferencedTableMap()); 2325 2326 2330 pushPredicates(optimizable, outerTables); 2331 2332 optimizableList.setOptimizable( 2333 ictr, 2334 optimizable.modifyAccessPath(outerTables)); 2335 } 2336 } 2337 2338 2339 public CostEstimate newCostEstimate() 2340 { 2341 return new CostEstimateImpl(); 2342 } 2343 2344 2345 public CostEstimate getOptimizedCost() 2346 { 2347 return bestCost; 2348 } 2349 2350 2358 public CostEstimate getFinalCost() 2359 { 2360 if (finalCostEstimate != null) 2362 return finalCostEstimate; 2363 2364 finalCostEstimate = getNewCostEstimate(0.0d, 0.0d, 0.0d); 2368 CostEstimate ce = null; 2369 for (int i = 0; i < bestJoinOrder.length; i++) 2370 { 2371 ce = optimizableList.getOptimizable(bestJoinOrder[i]) 2372 .getTrulyTheBestAccessPath().getCostEstimate(); 2373 2374 finalCostEstimate.setCost( 2375 finalCostEstimate.getEstimatedCost() + ce.getEstimatedCost(), 2376 ce.rowCount(), 2377 ce.singleScanRowCount()); 2378 } 2379 2380 return finalCostEstimate; 2381 } 2382 2383 2384 public void setOuterRows(double outerRows) 2385 { 2386 outermostCostEstimate.setCost( 2387 outermostCostEstimate.getEstimatedCost(), 2388 outerRows, 2389 outermostCostEstimate.singleScanRowCount()); 2390 } 2391 2392 2393 public int tableLockThreshold() 2394 { 2395 return tableLockThreshold; 2396 } 2397 2398 2401 public int getNumberOfJoinStrategies() 2402 { 2403 return joinStrategies.length; 2404 } 2405 2406 2407 public JoinStrategy getJoinStrategy(int whichStrategy) { 2408 if (SanityManager.DEBUG) { 2409 if (whichStrategy < 0 || whichStrategy >= joinStrategies.length) { 2410 SanityManager.THROWASSERT("whichStrategy value " + 2411 whichStrategy + 2412 " out of range - should be between 0 and " + 2413 (joinStrategies.length - 1)); 2414 } 2415 2416 if (joinStrategies[whichStrategy] == null) { 2417 SanityManager.THROWASSERT("Strategy " + whichStrategy + 2418 " not filled in."); 2419 } 2420 } 2421 2422 return joinStrategies[whichStrategy]; 2423 } 2424 2425 2426 public JoinStrategy getJoinStrategy(String whichStrategy) { 2427 JoinStrategy retval = null; 2428 String upperValue = StringUtil.SQLToUpperCase(whichStrategy); 2429 2430 for (int i = 0; i < joinStrategies.length; i++) { 2431 if (upperValue.equals(joinStrategies[i].getName())) { 2432 retval = joinStrategies[i]; 2433 } 2434 } 2435 2436 return retval; 2437 } 2438 2439 2444 public double uniqueJoinWithOuterTable(OptimizablePredicateList predList) 2445 throws StandardException 2446 { 2447 double retval = -1.0; 2448 double numUniqueKeys = 1.0; 2449 double currentRows = currentCost.rowCount(); 2450 2451 if (predList != null) 2452 { 2453 2454 for (int i = joinPosition - 1; i >= 0; i--) 2455 { 2456 Optimizable opt = optimizableList.getOptimizable( 2457 proposedJoinOrder[i]); 2458 double uniqueKeysThisOptimizable = opt.uniqueJoin(predList); 2459 if (uniqueKeysThisOptimizable > 0.0) 2460 numUniqueKeys *= opt.uniqueJoin(predList); 2461 } 2462 } 2463 2464 if (numUniqueKeys != 1.0) 2465 { 2466 retval = numUniqueKeys / currentRows; 2467 } 2468 2469 return retval; 2470 } 2471 2472 private boolean isPushable(OptimizablePredicate pred) 2473 { 2474 2477 if (pred.hasSubquery()) 2478 { 2479 return false; 2480 } 2481 else 2482 { 2483 return true; 2484 } 2485 } 2486 2487 2492 private CostEstimate estimateTotalCost(OptimizablePredicateList predList, 2493 ConglomerateDescriptor cd, 2494 CostEstimate outerCost, 2495 Optimizable optimizable) 2496 throws StandardException 2497 { 2498 2499 CostEstimate resultCost = 2500 optimizable.estimateCost(predList, 2501 cd, 2502 outerCost, 2503 this, 2504 currentRowOrdering); 2505 2506 return resultCost; 2507 } 2508 2509 2510 public int getLevel() 2511 { 2512 return 1; 2513 } 2514 2515 public CostEstimateImpl getNewCostEstimate(double theCost, 2516 double theRowCount, 2517 double theSingleScanRowCount) 2518 { 2519 return new CostEstimateImpl(theCost, theRowCount, theSingleScanRowCount); 2520 } 2521 2522 public void trace(int traceFlag, int intParam1, int intParam2, 2524 double doubleParam, Object objectParam1) 2525 { 2526 } 2527 2528 2529 public boolean useStatistics() { return useStatistics && optimizableList.useStatistics(); } 2530 2531 2546 protected void updateBestPlanMaps(short action, 2547 Object planKey) throws StandardException 2548 { 2549 if (numOptimizables > 1) 2553 { 2554 int [] joinOrder = null; 2555 if (action == FromTable.REMOVE_PLAN) 2556 { 2557 if (savedJoinOrders != null) 2558 { 2559 savedJoinOrders.remove(planKey); 2560 if (savedJoinOrders.size() == 0) 2561 savedJoinOrders = null; 2562 } 2563 } 2564 else if (action == FromTable.ADD_PLAN) 2565 { 2566 if (savedJoinOrders == null) 2569 savedJoinOrders = new HashMap (); 2570 else 2571 joinOrder = (int[])savedJoinOrders.get(planKey); 2572 2573 if (joinOrder == null) 2576 joinOrder = new int[numOptimizables]; 2577 2578 for (int i = 0; i < bestJoinOrder.length; i++) 2580 joinOrder[i] = bestJoinOrder[i]; 2581 2582 savedJoinOrders.put(planKey, joinOrder); 2583 } 2584 else 2585 { 2586 2589 if (savedJoinOrders != null) 2593 { 2594 joinOrder = (int[])savedJoinOrders.get(planKey); 2595 if (joinOrder != null) 2596 { 2597 for (int i = 0; i < joinOrder.length; i++) 2600 bestJoinOrder[i] = joinOrder[i]; 2601 } 2602 } 2603 } 2604 } 2605 2606 for (int i = optimizableList.size() - 1; i >= 0; i--) 2610 { 2611 optimizableList.getOptimizable(i). 2612 updateBestPlanMap(action, planKey); 2613 } 2614 } 2615 2616 2633 protected void addScopedPredicatesToList(PredicateList pList) 2634 throws StandardException 2635 { 2636 if ((pList == null) || (pList == predicateList)) 2637 return; 2639 2640 if (predicateList == null) 2641 predicateList = new PredicateList(); 2644 2645 Predicate pred = null; 2652 for (int i = predicateList.size() - 1; i >= 0; i--) { 2653 pred = (Predicate)predicateList.getOptPredicate(i); 2654 if (pred.isScopedForPush()) 2655 predicateList.removeOptPredicate(i); 2656 } 2657 2658 for (int i = pList.size() - 1; i >= 0; i--) 2661 { 2662 pred = (Predicate)pList.getOptPredicate(i); 2663 if (pred.isScopedToSourceResultSet()) 2664 { 2665 pred.clearScanFlags(); 2669 predicateList.addOptPredicate(pred); 2670 pList.removeOptPredicate(i); 2671 } 2672 } 2673 2674 return; 2675 } 2676 2677} 2678 | Popular Tags |