Skip to content
  • Sreeharsha Ramanavarapu's avatar
    a5c67cb6
    Bug #23259872: OPTIMIZER CHOOSES TO USE NON PRIMARY INDEX, · a5c67cb6
    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.
    a5c67cb6
    Bug #23259872: OPTIMIZER CHOOSES TO USE NON PRIMARY INDEX,
    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.
Loading