• unknown's avatar
    Patch for mdev-287: CHEAP SQ: A query with subquery in SELECT list, EXISTS,... · 941018f8
    unknown authored
    Patch for mdev-287: CHEAP SQ: A query with subquery in SELECT list, EXISTS, inner joins takes hundreds times longer
    
    Analysis:
    
    The fix for lp:944706 introduces early subquery optimization.
    While a subquery is being optimized some of its predicates may be
    removed. In the test case, the EXISTS subquery is constant, and is
    evaluated to TRUE. As a result the whole OR is TRUE, and thus the
    correlated condition "b = alias1.b" is optimized away. The subquery
    becomes non-correlated.
    
    The subquery cache is designed to work only for correlated subqueries.
    If constant subquery optimization is disallowed, then the constant
    subquery is not evaluated, the subquery remains correlated, and its
    execution is cached. As a result execution is fast.
    
    However, when the constant subquery was optimized away, it was neither
    cached by the subquery cache, nor it was cached by the internal subquery
    caching. The latter was due to the fact that the subquery still appeared
    as correlated to the subselect_XYZ_engine::exec methods, and they
    re-executed the subquery on each call to Item_subselect::exec.
    
    Solution:
    
    The solution is to update the correlated status of the subquery after it has
    been optimized. This status consists of:
    - st_select_lex::is_correlated
    - Item_subselect::is_correlated
    - SELECT_LEX::uncacheable
    - SELECT_LEX_UNIT::uncacheable
    The status is updated by st_select_lex::update_correlated_cache(), and its
    caller st_select_lex::optimize_unflattened_subqueries. The solution relies
    on the fact that the optimizer already called
    st_select_lex::update_used_tables() for each subquery. This allows to
    efficiently update the correlated status of each subquery without walking
    the whole subquery tree.
    
    Notice that his patch is an improvement over MySQL 5.6 and older, where
    subqueries are not pre-optimized, and the above analysis is not possible.
    941018f8
subselect_no_opts.result 230 KB