Skip to content
  • Norvald H. Ryeng's avatar
    c3a851ed
    Bug#14664077 SEVERE PERFORMANCE DEGRADATION IN SOME CASES WHEN USER · c3a851ed
    Norvald H. Ryeng authored
    VARIABLES ARE USED
    
    This is a regression introduced by the fix for bug #12408412.
    
    Problem: Performance regression when using SELECT ... INTO user
    variables and a WHERE condition on one or more variables in the INTO
    list.
    
    Since the fix for bug #12408412, Item_func_set_user_var objects for
    user variables that are in the INTO list are constructed by
    select_dumpvar::prepare(), which makes the Item_func_get_user_var
    objects for the same variables marked as non-const during optimization
    and execution. This leads to queries not taking advantage of
    optimizations that are possible when a user variable is constant
    throughout the query execution, even if the update only happens after
    the query has been executed. E.g., the optimizer may choose to do an
    index scan instead of an index lookup.
    
    Also, since the Item_func_set_user_var objects are created in
    select_dumpvar::prepare(), which is not called during EXPLAIN, the
    explained plan and the actual plan may be different, since the
    constness of Item_get_user_var objects may be different.
    
    Fix: Revert the change that marks user variables as non-const when
    used in the INTO list. This reintroduces bug #12408412.
    
    Problem in bug #12408412: A SELECT ... INTO query that stores the
    value of GROUP_CONCAT(@var) into @var crashes the server.
    
    The user variable in the SELECT list is represented by an
    Item_func_get_user_var. Item_func_get_user_var::const_item() returns
    true for this item throughout query optimization and execution since
    there are no Item_func_set_user_var items for the same variable.
    
    After query execution, in select_dumpvar::send_data(), an
    Item_func_set_user_var is created for the user variable in the INTO
    list. Item_func_set_user_var::fix_fields() calls
    Item_func_set_user_var::set_entry(), which sets update_query_id to the
    current query. This variable is used by
    Item_func_get_user_var::const_item() to determine if the variable is
    read and written in the same
    query. Item_func_set_user_var::save_item_result() is then called to
    store the result of GROUP_CONCAT, but
    Item_func_group_concat::val_str() calls walk() on its arguments with
    dump_leaf_key() as processor. In dump_leaf_key(), a decision is made
    on the constness of the Item_func_get_user_var(), which is now
    different from what it was during optimization and execution, and the
    server crashes while trying to dereference a null pointer.
    
    Fix: Add a new variable Item_func_set_user_var::delayed_non_constness
    that controls when update_query_id is set:
    
      false: by Item_func_set_user_var::fix_fields(), or
      true:  at the end of Item_func_set_user_var::save_item_result(),
             when the item has been evaluated.
    
    This allows select_dumpvar::send_data() to update the user variable
    without changing constness of the Item_func_get_user_var for the same
    variable until after the value has been read.
    c3a851ed
    Bug#14664077 SEVERE PERFORMANCE DEGRADATION IN SOME CASES WHEN USER
    Norvald H. Ryeng authored
    VARIABLES ARE USED
    
    This is a regression introduced by the fix for bug #12408412.
    
    Problem: Performance regression when using SELECT ... INTO user
    variables and a WHERE condition on one or more variables in the INTO
    list.
    
    Since the fix for bug #12408412, Item_func_set_user_var objects for
    user variables that are in the INTO list are constructed by
    select_dumpvar::prepare(), which makes the Item_func_get_user_var
    objects for the same variables marked as non-const during optimization
    and execution. This leads to queries not taking advantage of
    optimizations that are possible when a user variable is constant
    throughout the query execution, even if the update only happens after
    the query has been executed. E.g., the optimizer may choose to do an
    index scan instead of an index lookup.
    
    Also, since the Item_func_set_user_var objects are created in
    select_dumpvar::prepare(), which is not called during EXPLAIN, the
    explained plan and the actual plan may be different, since the
    constness of Item_get_user_var objects may be different.
    
    Fix: Revert the change that marks user variables as non-const when
    used in the INTO list. This reintroduces bug #12408412.
    
    Problem in bug #12408412: A SELECT ... INTO query that stores the
    value of GROUP_CONCAT(@var) into @var crashes the server.
    
    The user variable in the SELECT list is represented by an
    Item_func_get_user_var. Item_func_get_user_var::const_item() returns
    true for this item throughout query optimization and execution since
    there are no Item_func_set_user_var items for the same variable.
    
    After query execution, in select_dumpvar::send_data(), an
    Item_func_set_user_var is created for the user variable in the INTO
    list. Item_func_set_user_var::fix_fields() calls
    Item_func_set_user_var::set_entry(), which sets update_query_id to the
    current query. This variable is used by
    Item_func_get_user_var::const_item() to determine if the variable is
    read and written in the same
    query. Item_func_set_user_var::save_item_result() is then called to
    store the result of GROUP_CONCAT, but
    Item_func_group_concat::val_str() calls walk() on its arguments with
    dump_leaf_key() as processor. In dump_leaf_key(), a decision is made
    on the constness of the Item_func_get_user_var(), which is now
    different from what it was during optimization and execution, and the
    server crashes while trying to dereference a null pointer.
    
    Fix: Add a new variable Item_func_set_user_var::delayed_non_constness
    that controls when update_query_id is set:
    
      false: by Item_func_set_user_var::fix_fields(), or
      true:  at the end of Item_func_set_user_var::save_item_result(),
             when the item has been evaluated.
    
    This allows select_dumpvar::send_data() to update the user variable
    without changing constness of the Item_func_get_user_var for the same
    variable until after the value has been read.
Loading