Commit graph

93 commits

Author SHA1 Message Date
Sergei Golubchik
10740939eb 5.5 merge 2014-03-26 22:25:38 +01:00
Sergei Golubchik
21a17536c6 5.3 merge 2014-03-25 11:09:12 +01:00
Igor Babaev
d51ee6d412 Merge. 2014-03-19 14:58:29 -07:00
Igor Babaev
06ef0bdad2 Fixed bug mdev-5191.
Corrected cost estimates when a join buffer is used and the optimizer is requested
to use condition selectivities.
2014-03-18 11:30:50 -07:00
Sergey Petrunya
8c04dd33dd MDEV-5811: Server crashes in best_access_path with materialization+semijoin and big_tables=ON
- With big_tables=ON, materialized table will use Aria (or MyISAM) SE, which
  allows prefix key reads. However, the temp.table has rec_per_key=NULL which
  causes the optimizer to crash when attempting to read index statistics for a 
  prefix index read.
- Fixed by providing a rec_per_key array with zeros (i.e. "no statistics data")
2014-03-13 12:20:57 +01:00
Sergei Golubchik
59d9d08e2b 5.5 merge 2014-02-01 00:54:03 +01:00
Alexander Barkov
ba3d0b173a Merge 5.3 -> 5.5 2014-01-27 13:14:00 +04:00
Sergey Petrunya
519c7305ac MDEV-5368: Server crashes in Item_in_subselect::optimize on ...
- convert_subq_to_sj() must connect child select's tables into 
  parent select's TABLE_LIST::next_local chain.  
- The problem was that it took child's leaf_tables.head() which
  is different. This could cause certain tables (in this bug's case,
  child select's non-merged semi-join) not to be present in 
  TABLE_LIST::next_local chain.  Which would cause non-merged semi-join
  not to be initialized in setup_tables(), which would lead to 
  NULL pointer dereference.
2014-01-23 21:26:04 +04:00
Sergey Petrunya
f0fa66a26d MDEV-5368: Server crashes in Item_in_subselect::optimize on ...
- convert_subq_to_sj() must connect child select's tables into 
  parent select's TABLE_LIST::next_local chain.  
- The problem was that it took child's leaf_tables.head() which
  is different. This could cause certain tables (in this bug's case,
  child select's non-merged semi-join) not to be present in 
  TABLE_LIST::next_local chain.  Which would cause non-merged semi-join
  not to be initialized in setup_tables(), which would lead to 
  NULL pointer dereference.
2014-01-23 15:41:51 +04:00
Sergei Golubchik
bdd883ed9a 5.5. merge 2013-11-13 14:07:58 +01:00
Sergey Petrunya
229aa1d4bf MDEV-5056: Wrong result (extra rows) with materialization+semijoin, IN subqueries
Apply fix suggested by Igor:
- When eliminate_item_equal() generates pair-wise equalities from a 
  multi-equality,  do generate a "bridge" equality between the first 
  field inside SJM nest and the field that's first in the overall multi-equality.
2013-11-13 07:40:46 +04:00
timour@askmonty.org
afed809297 MDEV-5123 Remove duplicated conditions pushed both to join_tab->select_cond and join_tab->cache_select->cond for blocked joins.
BNL and BNLH joins pre-filter the records from a joined table via JOIN_TAB::cache_select->cond.
There is no need to re-evaluate the same conditions via JOIN_TAB::select_cond. This patch removes
the duplicated conditions from the top-level conjuncts of each pushed condition.

The added "Using where" in few EXPLAINs is due to taking into account tab->cache_select->cond
in addition to tab->select_cond in JOIN::save_explain_data_intern.
2013-10-18 11:45:25 +03:00
Sergey Petrunya
33f807fd91 Merge 5.3 -> 5.5 2013-09-12 13:54:46 +04:00
Sergey Petrunya
7e4845beea MDEV-5011: ERROR Plugin 'MEMORY' has ref_count=1 after shutdown for SJM queries
- Provide a special execution path for cleanup of degenerate 
  non-merged semi-join children of degenerate selects.
2013-09-12 13:53:13 +04:00
Igor Babaev
2ead54d0fb Merge 2013-08-21 12:34:58 -07:00
unknown
f8af4423b4 MDEV-4908: Assertion `((Item_cond *) cond)->functype() == ((Item_cond *) new_item)->functype()' fails on a query with IN and equal conditions, AND/OR, materialization+semijoin
A new AND Item should be prepared (fix_field() call) before using.
2013-08-21 17:42:09 +03:00
Sergey Petrunya
6ed00c4d8a MDEV-4465: Reproducible crash (mysqld got signal 11) in multi_delete::initialize_tables...
- make multi_delete::initialize_tables() take into account that the JOIN structure may have
  semi-join nests (which are not fully initialized when this function is called, they have 
  tab->table=NULL which caused the crash)
- Also checked multi_update::initialize_tables(): it has a different logic and needed no fixing.
2013-05-03 00:10:43 +04:00
Sergei Golubchik
213f1c76a0 5.3->5.5 merge 2013-02-28 22:47:29 +01:00
Igor Babaev
c9b63e6a49 Fixed bug mdev-3913.
The wrong result set returned by the left join query  from
the bug test case happened due to several inconsistencies 
and bugs of the legacy mysql code.

The bug test case uses an execution plan that employs a scan
of a materialized IN subquery from the WHERE condition.
When materializing such an IN- subquery the optimizer injects
additional equalities  into the WHERE clause. These equalities
express the constraints imposed by the subquery predicate.
The injected equality of the query in the  test case happens
to belong to the same equality class, and a new equality 
imposing a condition on the rows of the materialized subquery
is inferred from this class. Simultaneously the multiple
equality is added to the ON expression of the LEFT JOIN
used in the main query.
  
The inferred equality of the form f1=f2 is taken into account
when optimizing the scan of  the rows the temporary table 
that is the result of the subquery materialization: only the 
values of the field f1 are read from the table into the record 
buffer. Meanwhile the inferred equality is removed from the
WHERE conditions altogether as a constraint on the fields
of the temporary table that has been used when filling this table. 
This equality is supposed to be removed from the ON expression
when the multiple equalities of the ON expression are converted
into an optimal set of equality predicates. It supposed to be
removed from the ON expression as an equality inferred from only
equalities of the WHERE condition. Yet, it did not happened
due to the following bug in the code.

Erroneously the code tried to build multiple equality for ON
expression twice: the first time, when it called optimize_cond()
for the WHERE condition, the second time, when it called
this function for the HAVING condition. When executing
optimize_con() for the WHERE condition  a reference
to the multiple equality of the WHERE condition is set
in the multiple equality of the  ON expression. This reference
would allow later to convert multiple equalities of the
ON expression into equality predicates. However the 
the second call of build_equal_items() for the ON expression
that happened when optimize_cond() was called for the
HAVING condition reset this reference to NULL.

This bug fix blocks calling build_equal_items() for ON
expressions for the second time. In general, it will be
beneficial for many queries as it removes from ON 
expressions any equalities that are to be checked for the
WHERE condition.
The patch also fixes two bugs in the list manipulation
operations and a bug in the function  
substitute_for_best_equal_field() that resulted
in passing wrong reference to the multiple equalities
of where conditions when processing multiple
equalities  of ON expressions.

The code of substitute_for_best_equal_field() and
the code the helper function eliminate_item_equal()
were also streamlined and cleaned up.
Now the conversion of the multiple equalities into
an optimal set of equality predicates first produces
the sequence of the all equalities processing multiple
equalities one by one, and, only after this, it inserts
the equalities at the beginning of the other conditions.

The multiple changes in the output of EXPLAIN
EXTENDED are mainly the result of this streamlining,
but in some cases is the result of the removal of
unneeded equalities from ON expressions. In
some test cases this removal were reflected in the
output of EXPLAIN resulted in disappearance of 
“Using where” in some rows of the execution plans.
2013-02-20 18:01:36 -08:00
unknown
0b93b444b6 Merged the fix for bug lp:944706, mdev-193 2012-06-19 15:06:45 +03:00
unknown
c2677de7ac Merge the fix for lp:944706, mdev-193 2012-06-06 22:26:40 +03:00
unknown
8efc63ba5d Merge 2012-06-06 16:19:48 +03:00
unknown
f1ab00891a Fixed bug lp:1000649
Analysis:

When the method JOIN::choose_subquery_plan() decided to apply
the IN-TO-EXISTS strategy, it set the unit and select_lex
uncacheable flag to UNCACHEABLE_DEPENDENT_INJECTED unconditionally.
As result, even if IN-TO-EXISTS injected non-correlated predicates,
the subquery was still treated as correlated.

Solution:
Set the subquery as correlated only if the injected predicate(s) depend
on the outer query.
2012-06-05 17:25:10 +03:00
unknown
941018f8d1 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.
2012-05-30 00:18:53 +03:00
Sergey Petrunya
02c4c5f735 BUG#1000269: Wrong result (extra rows) with semijoin+materialization, IN subqueries, join_cache_level>0
- make make_cond_after_sjm() correctly handle OR clauses where one branch refers to the semi-join table
  while the other branch refers to the non-semijoin table.
2012-05-18 16:24:12 +04:00
unknown
da5214831d Fix for bug lp:944706, task MDEV-193
The patch enables back constant subquery execution during
query optimization after it was disabled during the development
of MWL#89 (cost-based choice of IN-TO-EXISTS vs MATERIALIZATION).

The main idea is that constant subqueries are allowed to be executed
during optimization if their execution is not expensive.

The approach is as follows:
- Constant subqueries are recursively optimized in the beginning of
  JOIN::optimize of the outer query. This is done by the new method
  JOIN::optimize_constant_subqueries(). This is done so that the cost
  of executing these queries can be estimated.
- Optimization of the outer query proceeds normally. During this phase
  the optimizer may request execution of non-expensive constant subqueries.
  Each place where the optimizer may potentially execute an expensive
  expression is guarded with the predicate Item::is_expensive().
- The implementation of Item_subselect::is_expensive has been extended
  to use the number of examined rows (estimated by the optimizer) as a
  way to determine whether the subquery is expensive or not.
- The new system variable "expensive_subquery_limit" controls how many
  examined rows are considered to be not expensive. The default is 100.

In addition, multiple changes were needed to make this solution work
in the light of the changes made by MWL#89. These changes were needed
to fix various crashes and wrong results, and legacy bugs discovered
during development.
2012-05-17 13:46:05 +03:00
Sergei Golubchik
1185420da0 5.3 merge 2012-05-21 20:54:41 +02:00
Sergei Golubchik
f860b2aad4 merge 2012-04-07 15:58:46 +02:00
Sergey Petrunya
2a16e7674b BUG#913030: Optimizer chooses a suboptimal excution plan for Q18 from DBT-3
- When doing join optimization, pre-sort the tables so that they mimic the execution
  order we've had with 'semijoin=off'. 
- That way, we will not get regressions when there are two query plans (the old and the
  new) that have indentical costs but different execution times (because of factors that
  the optimizer was not able to take into account).
2012-04-02 21:41:54 +04:00
Igor Babaev
5d954e7cd0 Merge 5.3->5.5 2012-03-17 01:26:58 -07:00
Sergey Petrunya
50ff30d892 Merge 2012-03-12 18:08:40 +04:00
Sergey Petrunya
d028d986a9 BUG#952297: Server crashes on 2nd execution of PS in Field::is_null with semijoin+materialization
- The bug would show up 
   - when using PS (so that we get re-execution)
   - the left_expr of the subquery is a reference to viewname.column_name, so that it crashes
      when one tries to use it without having called fix_fields for it.
   - when using SJ-Materialization, which makes use of sj_subq_pred->left_expr expression

- The fix is to have setup_conds() fix sj_subq_pred->left_expr for semi-join nests it finds.
2012-03-12 17:41:22 +04:00
Sergei Golubchik
18c51eee35 5.3 merge 2012-03-06 20:46:07 +01:00
Igor Babaev
04ee30e75a Fixed LP bug #946055.
The function create_hj_key_for_table() that builds the descriptor of
the hash join key to access a table of a materialized subquery must
ignore any equi-join predicate depending on the tables not belonging
to the subquery.
2012-03-05 20:32:28 -08:00
Igor Babaev
8b469eb515 Merge 5.3->5.5. 2012-03-01 14:22:22 -08:00
Igor Babaev
000deedf3b Fixed LP bug #943543.
This bug appeared after the patch for bug 939009 that in the
function merge_key_fields forgot to reset a proper value for
the val field in the result of the merge operation of the key
field created for a regular key access and  the key field
created to look for a NULL key.

Adjusted the results of the test case for bug 939009 that
actually were incorrect.
2012-02-29 23:28:16 -08:00
Igor Babaev
b161b2e110 Merge. 2012-02-24 18:35:58 -08:00
Igor Babaev
841a74a4d6 Fixed LP bug #939009.
The result of materialization of the right part of an IN subquery predicate
is placed into a temporary table. Each row of the materialized table is
distinct. A unique key over all fields of the temporary table is defined and
created. It allows to perform key look-ups into the table.
The table created for a materialized subquery can be accessed by key as
any other table. The function best_access-path search for the best access
to join a table to a given partial join. With some where conditions this
function considers a possibility of a ref_or_null access. If such access
employs the unique key on the temporary table then when estimating
the cost this access the function tries to use the array rec_per_key. Yet,
such array is not built for this unique key. This causes a crash of the server.

Rows returned by the subquery that contain nulls don't have to be placed
into temporary table, as they cannot be match any row produced by the
left part of the subquery predicate. So all fields of the temporary table
can be defined as non-nullable. In this case any ref_or_null access
to the temporary table does not make any sense and it does not make sense
to estimate such an access.

The fix makes sure that the temporary table for a materialized IN subquery
is defined with columns that are all non-nullable. The also ensures that 
any row with nulls returned by the subquery is not placed into the
temporary table.
2012-02-24 16:50:22 -08:00
Sergey Petrunya
8871806788 BUG#938131: Subquery materialization is not used in CREATE TABLE SELECT
- Enable subquery materialization for CREATE TABLE ... SELECT.
2012-02-24 22:42:37 +04:00
Sergey Petrunya
fecad7c945 BUG#933407: Valgrind warnings in mark_as_null_row with materialization+semijoin, STRAIGHT_JOIN, impossible WHERE
- In return_zero_rows(), don't call mark_as_null_row() for semi-join 
  materialized tables, because 1) they may have been already freed, and 
  2)there is no real need to call mark_as_null_row() for them.
2012-02-20 15:30:54 +04:00
Sergey Petrunya
c9355dc279 BUG#928048: Query containing IN subquery with OR in the where clause returns a wrong result
- Make equality propagation work correctly when done inside the OR branches
2012-02-14 13:58:57 +04:00
Sergei Golubchik
edab37cd68 5.3 merge 2012-02-21 20:51:56 +01:00
Sergei Golubchik
25609313ff 5.3.4 merge 2012-02-15 18:08:08 +01:00
Sergey Petrunya
53fde5bb6f BUG#922254: Assertion `0' failed at item_cmpfunc.cc:5899: Item* Item_equal::get_first(JOIN_TAB*, Item*)
Fixed Item* Item_equal::get_first(JOIN_TAB *context, Item *field_item) to work correctly in the case where:
- context!= NO_PARTICULAR_TAB, it points to a table within SJ-Materialization nest
- field_item points to an item_equal that has a constant Item_field but does not have any fields
  from tables that are within semi-join nests.
2012-01-27 17:35:26 +04:00
Sergei Golubchik
4f435bddfd 5.3 merge 2012-01-13 15:50:02 +01:00
unknown
072073c09e Backport of WL#5953 from MySQL 5.6
The patch differs from the original MySQL patch as follows:
- All test case differences have been reviewed one by one, and
  care has been taken to restore the original plan so that each
  test case executes the code path it was designed for.
- A bug was found and fixed in MariaDB 5.3 in
  Item_allany_subselect::cleanup().
- ORDER BY is not removed because we are unsure of all effects,
  and it would prevent enabling ORDER BY ... LIMIT subqueries.
- ref_pointer_array.m_size is not adjusted because we don't do
  array bounds checking, and because it looks risky.

Original comment by Jorgen Loland:
-------------------------------------------------------------
WL#5953 - Optimize away useless subquery clauses
      
For IN/ALL/ANY/SOME/EXISTS subqueries, the following clauses are 
meaningless:
      
* ORDER BY (since we don't support LIMIT in these subqueries)
* DISTINCT
* GROUP BY if there is no HAVING clause and no aggregate 
  functions
      
This WL detects and optimizes away these useless parts of the
query during JOIN::prepare()
2011-12-19 23:05:44 +02:00
Sergey Petrunya
be3e52984f BUG#904432: Wrong result with LEFT JOIN, constant table, semijoin=ON,materialization=ON
- Correct handling for SJ-Materialization + outer joins (details in the comments in the code)
2011-12-19 20:58:55 +04:00
Igor Babaev
a910e8ef5b Made join_cache_level == 2 by default. 2011-12-15 14:26:59 -08:00
Sergey Petrunya
efb57a8ebf Merge 2011-12-14 04:56:54 +04:00
Sergey Petrunya
05e0127478 BUG#901506: Crash in TABLE_LIST::print on EXPLAIN EXTENDED
- Let JTBM optimization code handle the case where the subquery is degenerate and doesn't have a 
  join query plan. Regular materialization would fall back to IN->EXISTS for such cases. Semi-Join
  materialization does not have such option, instead we introduce and use "constant JTBM join tabs".
2011-12-14 04:39:29 +04:00