-
Sreeharsha Ramanavarapu authored
EVEN THOUGH COST IS HIGHER Issue: ------ Optimizer tries to choose between a range-access and ref-access, based on various parameters like records_per_key, CPU cost and I/O cost. When the row-estimate for ref access is inaccurate, optimizer uses the estimate from range access on the same index. In the current issue the ref access's row-estimate comes from range-access's estimate. The ref-access on a secondary index is calculated to be cheaper than the best range-access on the primary key. This will result in a bad performance. Solution (mysql-trunk): --------- Ignore the index for ref access when we have the above mentioned problem. Solution (mysql-5.7): --------- Shift from ref-access to range-access when: 1) Ref-access row estimate is overly-optimistic and it has borrowed range-access's estimate on the same index. 2) Range-access uses more index key parts than ref access. We already do this in cases where the above conditions are met and range access on the same index is the cheapest. With this fix, we shift to range-access on that index, even if it is not considered the cheapest. To do this, we run the range optimizer on that index alone. sql/sql_select.h: A new boolean 'dodgy_ref_cost' has been added to JOIN_TAB. Setting this flag means ref is using lesser number of key-parts than range and it borrows range's row estimate. sql/sql_planner.h: find_best_ref should be able to modify the flag 'dodgy_ref_cost', so removing the const. sql/sql_planner.cc: In find_best_ref, keep track of whether ref access's row-estimate is problematic and set the 'dodgy_ref_cost' flag. sql/sql_optimizer.cc: Conditions 3, 4 were earlier tested for negation. Now they are tested before 2 and false is returned. Check if the 'dodgy_ref_cost' flag is set. Then it is better we shift to range on the same index since it uses more keyparts and its row-estimate is more reliable. We do this by calling the range optimizer again on that index alone. Solution (mysql-5.6): --------- Same approach as 5.7. With the following changes: sql/sql_optimizer.cc: A new function can_switch_from_ref_to_range, similar to the one in 5.7+ has been created.
Sreeharsha Ramanavarapu authoredEVEN THOUGH COST IS HIGHER Issue: ------ Optimizer tries to choose between a range-access and ref-access, based on various parameters like records_per_key, CPU cost and I/O cost. When the row-estimate for ref access is inaccurate, optimizer uses the estimate from range access on the same index. In the current issue the ref access's row-estimate comes from range-access's estimate. The ref-access on a secondary index is calculated to be cheaper than the best range-access on the primary key. This will result in a bad performance. Solution (mysql-trunk): --------- Ignore the index for ref access when we have the above mentioned problem. Solution (mysql-5.7): --------- Shift from ref-access to range-access when: 1) Ref-access row estimate is overly-optimistic and it has borrowed range-access's estimate on the same index. 2) Range-access uses more index key parts than ref access. We already do this in cases where the above conditions are met and range access on the same index is the cheapest. With this fix, we shift to range-access on that index, even if it is not considered the cheapest. To do this, we run the range optimizer on that index alone. sql/sql_select.h: A new boolean 'dodgy_ref_cost' has been added to JOIN_TAB. Setting this flag means ref is using lesser number of key-parts than range and it borrows range's row estimate. sql/sql_planner.h: find_best_ref should be able to modify the flag 'dodgy_ref_cost', so removing the const. sql/sql_planner.cc: In find_best_ref, keep track of whether ref access's row-estimate is problematic and set the 'dodgy_ref_cost' flag. sql/sql_optimizer.cc: Conditions 3, 4 were earlier tested for negation. Now they are tested before 2 and false is returned. Check if the 'dodgy_ref_cost' flag is set. Then it is better we shift to range on the same index since it uses more keyparts and its row-estimate is more reliable. We do this by calling the range optimizer again on that index alone. Solution (mysql-5.6): --------- Same approach as 5.7. With the following changes: sql/sql_optimizer.cc: A new function can_switch_from_ref_to_range, similar to the one in 5.7+ has been created.
Loading