← Back to team overview

maria-developers team mailing list archive

Re: Fwd: [Commits] Rev 3296: Fix bug lp:833777 in file:///home/tsk/mprog/src/5.3-lpb833777/

 

Hi Timour,

On Fri, Nov 18, 2011 at 11:16:27PM +0200, Timour Katchaounov wrote:
> Sergey,
>
> Please review the following patch.
> Do you have any idea about the change in
> func_compress.result ? I've seen that before,
> but don't remember what was the issue.

I think in this case it is fairly clear - a warning is produced every time a
constant expression is evaluated. Your patch makes one less evaluation, so one
fewer warning is emitted.

The patch is ok to push after the below notes are addressed.

> ------------------------------------------------------------
> revno: 3296
> revision-id: timour@xxxxxxxxxxxx-20111118201920-fac3c9870u7eh898
> parent: igor@xxxxxxxxxxxx-20111118173551-78xd3uuu5h25756u
> fixes bug(s): https://launchpad.net/bugs/833777
> committer: timour@xxxxxxxxxxxx
> branch nick: 5.3-lpb833777
> timestamp: Fri 2011-11-18 22:19:20 +0200
> message:
>   Fix bug lp:833777
>
>   Analysis:
>   The optimizer distinguishes two kinds of 'constant' conditions:
>   expensive ones, and non-expensive ones. The non-expensive conditions
>   are evaluated inside make_join_select(), and if false, already the
>   optimizer detects empty query results.
>
>   In order to avoid arbitrarily expensive optimization, the evaluation of
>   expensive constant conditions is delayed until execution. These conditions
>   are attached to JOIN::exec_const_cond and evaluated in the beginning of
>   JOIN::exec. The relevant execution logic is:
>
>   JOIN::exec()
>   {
>     if (! join->exec_const_cond->val_int())
>     {
>       produce an empty result;
>       stop execution
>     }
>     continue execution
>     execute the original WHERE clause (that contains exec_const_cond)
>    ...
>   }
>
>   As a result, when an expensive constant condition is
>   TRUE, it is evaluated twice - once through
>   JOIN::exec_const_cond, and once through JOIN::cond.
>   When the expensive constant condition is a subquery,
>   predicate, the subquery is evaluated twice. If we have
>   many levels of subqueries, this logic results in a chain
>   of recursive subquery executions that walk a perfect
>   binary tree. The result is that for subquries with depth N,
>   JOIN::exec is executed O(2^N) times.
>
>   Solution:
>   Notice that the second execution of the constant conditions
>   happens inside do_select(), in the branch:
>   if (join->table_count == join->const_tables) { ... }
>   In this case exec_const_cond is equivalent to the whole WHERE
>   clause, therefore the WHERE clause has already been checked in
>   the beginnig of JOIN::exec, and has been found to be true.
>   The bug is addressed by not evaluating the WHERE clause if there
>   was exec_const_conds, and it was TRUE.

> === modified file 'mysql-test/r/func_compress.result'
> --- a/mysql-test/r/func_compress.result	2011-02-03 15:00:28 +0000
> +++ b/mysql-test/r/func_compress.result	2011-11-18 20:19:20 +0000
> @@ -103,7 +103,6 @@ foo
>  Warnings:
>  Error   1259    ZLIB: Input data corrupted
>  Error   1259    ZLIB: Input data corrupted
> -Error   1259    ZLIB: Input data corrupted
>  explain select *, uncompress(a) from t1;
>  id      select_type     table   type    possible_keys   key     key_len ref     rows    Extra
>  1       SIMPLE  t1      system  NULL    NULL    NULL    NULL    1       
> 
> === modified file 'mysql-test/r/subselect.result'
> --- a/mysql-test/r/subselect.result	2011-11-15 21:03:00 +0000
> +++ b/mysql-test/r/subselect.result	2011-11-18 20:19:20 +0000
> @@ -5665,4 +5665,14 @@ ERROR 21000: Subquery returns more than
>  SET SESSION sql_mode=@old_sql_mode;
>  DEALLOCATE PREPARE stmt;
>  DROP TABLE t1;
> +#
> +# LP BUG#833777 Performance regression with deeply nested subqueries
> +#
> +create table t1 (a int not null, b char(10) not null);
> +insert into t1 values (1, 'a');
> +set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
> +select benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1))))))))))))))))))))))))))))))))));
> +benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a 
> +0

Why use 'benchmark' function? It seems totally redundant. Please change the
test to look like:
select
  (select a from t1 where a in 
  (select a from t1 where a in 
  (select a from t1 where a in
  ...
  (select a from t1)
))))))))))))))))))))))))))))))))) AS foo;

to make it less cluttered.

> +drop table t1;
>  set optimizer_switch=@subselect_tmp;
> 
> === modified file 'mysql-test/r/subselect_no_mat.result'
> --- a/mysql-test/r/subselect_no_mat.result	2011-11-15 21:03:00 +0000
> +++ b/mysql-test/r/subselect_no_mat.result	2011-11-18 20:19:20 +0000
> @@ -5670,6 +5670,16 @@ ERROR 21000: Subquery returns more than
>  SET SESSION sql_mode=@old_sql_mode;
>  DEALLOCATE PREPARE stmt;
>  DROP TABLE t1;
> +#
> +# LP BUG#833777 Performance regression with deeply nested subqueries
> +#
> +create table t1 (a int not null, b char(10) not null);
> +insert into t1 values (1, 'a');
> +set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
> +select benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1))))))))))))))))))))))))))))))))));
> +benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a 
> +0
> +drop table t1;
>  set optimizer_switch=@subselect_tmp;
>  set optimizer_switch=default;
>  select @@optimizer_switch like '%materialization=on%';
> 
> === modified file 'mysql-test/r/subselect_no_opts.result'
> --- a/mysql-test/r/subselect_no_opts.result	2011-11-15 21:03:00 +0000
> +++ b/mysql-test/r/subselect_no_opts.result	2011-11-18 20:19:20 +0000
> @@ -5666,5 +5666,15 @@ ERROR 21000: Subquery returns more than
>  SET SESSION sql_mode=@old_sql_mode;
>  DEALLOCATE PREPARE stmt;
>  DROP TABLE t1;
> +#
> +# LP BUG#833777 Performance regression with deeply nested subqueries
> +#
> +create table t1 (a int not null, b char(10) not null);
> +insert into t1 values (1, 'a');
> +set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
> +select benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1))))))))))))))))))))))))))))))))));
> +benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a 
> +0
> +drop table t1;
>  set optimizer_switch=@subselect_tmp;
>  set @optimizer_switch_for_subselect_test=null;
> 
> === modified file 'mysql-test/r/subselect_no_scache.result'
> --- a/mysql-test/r/subselect_no_scache.result	2011-11-15 21:03:00 +0000
> +++ b/mysql-test/r/subselect_no_scache.result	2011-11-18 20:19:20 +0000
> @@ -5669,6 +5669,16 @@ ERROR 21000: Subquery returns more than
>  SET SESSION sql_mode=@old_sql_mode;
>  DEALLOCATE PREPARE stmt;
>  DROP TABLE t1;
> +#
> +# LP BUG#833777 Performance regression with deeply nested subqueries
> +#
> +create table t1 (a int not null, b char(10) not null);
> +insert into t1 values (1, 'a');
> +set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
> +select benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1))))))))))))))))))))))))))))))))));
> +benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a 
> +0
> +drop table t1;
>  set optimizer_switch=@subselect_tmp;
>  set optimizer_switch=default;
>  select @@optimizer_switch like '%subquery_cache=on%';
> 
> === modified file 'mysql-test/r/subselect_no_semijoin.result'
> --- a/mysql-test/r/subselect_no_semijoin.result	2011-11-15 21:03:00 +0000
> +++ b/mysql-test/r/subselect_no_semijoin.result	2011-11-18 20:19:20 +0000
> @@ -5666,5 +5666,15 @@ ERROR 21000: Subquery returns more than
>  SET SESSION sql_mode=@old_sql_mode;
>  DEALLOCATE PREPARE stmt;
>  DROP TABLE t1;
> +#
> +# LP BUG#833777 Performance regression with deeply nested subqueries
> +#
> +create table t1 (a int not null, b char(10) not null);
> +insert into t1 values (1, 'a');
> +set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
> +select benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1))))))))))))))))))))))))))))))))));
> +benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a 
> +0
> +drop table t1;
>  set optimizer_switch=@subselect_tmp;
>  set @optimizer_switch_for_subselect_test=null;
> 
> === modified file 'mysql-test/t/subselect.test'
> --- a/mysql-test/t/subselect.test	2011-11-15 21:03:00 +0000
> +++ b/mysql-test/t/subselect.test	2011-11-18 20:19:20 +0000
> @@ -4768,4 +4768,14 @@ SET SESSION sql_mode=@old_sql_mode;
>  DEALLOCATE PREPARE stmt;
>  DROP TABLE t1;
>  
> +--echo #
> +--echo # LP BUG#833777 Performance regression with deeply nested subqueries
> +--echo #
> +
> +create table t1 (a int not null, b char(10) not null);
> +insert into t1 values (1, 'a');
> +set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
> +select benchmark(1, (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1))))))))))))))))))))))))))))))))));
> +drop table t1;
> +
>  set optimizer_switch=@subselect_tmp;
> 
> === modified file 'sql/sql_select.cc'
> --- a/sql/sql_select.cc	2011-11-15 21:03:00 +0000
> +++ b/sql/sql_select.cc	2011-11-18 20:19:20 +0000
> @@ -14782,9 +14782,15 @@ do_select(JOIN *join,List<Item> *fields,
>    {
>      /*
>        HAVING will be checked after processing aggregate functions,
> -      But WHERE should checkd here (we alredy have read tables)
> +      But WHERE should checkd here (we alredy have read tables).
> +      If there is join->exec_const_cond, and all tables are constant, then it
> +      is equivalent to join->conds. exec_const_cond is already checked in the
> +      beginning of JOIN::exec. If it is false, JOIN::exec returns zero
> +      result already there, therefore execution reaches this point only if
> +      exec_const_cond is TRUE. Since it is equvalent to join->conds, then
> +      join->conds is also TRUE.
>      */
> -    if (!join->conds || join->conds->val_int())
> +    if (!join->conds || join->exec_const_cond || join->conds->val_int())
>      {
>        error= (*end_select)(join, 0, 0);
>        if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT)
> 

> _______________________________________________
> commits mailing list
> commits@xxxxxxxxxxx
> https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits


-- 
BR
 Sergei
-- 
Sergei Petrunia, Software Developer
Monty Program AB, http://askmonty.org
Blog: http://s.petrunia.net/blog