Commit d42e6d3a authored by Igor Babaev's avatar Igor Babaev

Fixed bug mdev-6071.

The method JOIN_CACHE::init may fail (return 1) if some conditions on the
used join buffer is not satisfied. For example it fails if join_buffer_size
is greater than join_buffer_space_limit. The conditions should be checked
when running the EXPLAIN command for the query. That's why the method
JOIN_CACHE::init has to be called for EXPLAIN commands as well.
parent 216fbe2a
......@@ -5577,8 +5577,8 @@ EXPLAIN
SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
1 SIMPLE t2 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (incremental, BNL join)
1 SIMPLE t2 ALL NULL NULL NULL NULL 12 Using where
1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where
SELECT * FROM t1, t2 LEFT JOIN t3 ON t2.b=t3.b WHERE t1.a=t2.a;
a a b b c
3 3 30 30 300
......@@ -5703,4 +5703,27 @@ select @counter;
2
drop table t1,t2,t3;
set expensive_subquery_limit=default;
#
# mdev-6071: EXPLAIN chooses to use join buffer while execution turns it down
#
create table t1 (a int);
insert into t1 values
(7), (9), (1), (4), (2), (3), (5), (8), (11), (6), (10);
explain select count(*) from t1, t1 t2 where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 Using where; Using join buffer (flat, BNL join)
set join_buffer_space_limit=1024*8;
select @@join_buffer_space_limit;
@@join_buffer_space_limit
8192
select @@join_buffer_size;
@@join_buffer_size
131072
explain select count(*) from t1, t1 t2 where t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 Using where
set join_buffer_space_limit=default;
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
......@@ -94,6 +94,7 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
2 MATERIALIZED t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(((`test`.`t2`.`A` = `test`.`t1`.`A`) And <in_optimizer>(`test`.`t1`.`A`,`test`.`t1`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t1`.`A` in <temporAry tABle> on distinct_key where ((`test`.`t1`.`A` = `<suBquery2>`.`pk`))))))) where 1
set join_buffer_size=8*1024;
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
t1 s00, t1 s01, t1 s02, t1 s03, t1 s04,t1 s05,t1 s06,t1 s07,t1 s08,t1 s09,
......@@ -185,6 +186,7 @@ a b a b
0 0 0 0
1 1 1 1
2 2 2 2
set join_buffer_size=default;
prepare s1 from
' select * from
t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t10))
......
......@@ -107,6 +107,7 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
2 MATERIALIZED t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on(((`test`.`t2`.`A` = `test`.`t1`.`A`) And <in_optimizer>(`test`.`t1`.`A`,`test`.`t1`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t1`.`A` in <temporAry tABle> on distinct_key where ((`test`.`t1`.`A` = `<suBquery2>`.`pk`))))))) where 1
set join_buffer_size=8*1024;
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
t1 s00, t1 s01, t1 s02, t1 s03, t1 s04,t1 s05,t1 s06,t1 s07,t1 s08,t1 s09,
......@@ -198,6 +199,7 @@ a b a b
0 0 0 0
1 1 1 1
2 2 2 2
set join_buffer_size=default;
prepare s1 from
' select * from
t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t10))
......
......@@ -3700,5 +3700,26 @@ select @counter;
drop table t1,t2,t3;
set expensive_subquery_limit=default;
--echo #
--echo # mdev-6071: EXPLAIN chooses to use join buffer while execution turns it down
--echo #
create table t1 (a int);
insert into t1 values
(7), (9), (1), (4), (2), (3), (5), (8), (11), (6), (10);
explain select count(*) from t1, t1 t2 where t1.a=t2.a;
set join_buffer_space_limit=1024*8;
select @@join_buffer_space_limit;
select @@join_buffer_size;
explain select count(*) from t1, t1 t2 where t1.a=t2.a;
set join_buffer_space_limit=default;
drop table t1;
# The following command must be the last one the file
# this must be the last command in the file
set @@optimizer_switch=@save_optimizer_switch;
......@@ -79,6 +79,8 @@ select * from t1 left join (t2 A, t2 B) on ( A.a= t1.a and B.a in (select pk fro
explain extended
select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t10));
set join_buffer_size=8*1024;
--echo we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
t1 s00, t1 s01, t1 s02, t1 s03, t1 s04,t1 s05,t1 s06,t1 s07,t1 s08,t1 s09,
......@@ -97,6 +99,8 @@ select * from
t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t10))
where t1.a < 5;
set join_buffer_size=default;
#
# Prepared statements
#
......
......@@ -930,6 +930,9 @@ int JOIN_CACHE::alloc_buffer()
join_buff_space_limit))))
goto fail;
if (for_explain_only)
return 0;
for (ulong buff_size_decr= (buff_size-min_buff_size)/4 + 1; ; )
{
ulong next_buff_size;
......@@ -1023,6 +1026,7 @@ int JOIN_CACHE::realloc_buffer()
SYNOPSIS
init()
for_explain join buffer is initialized for explain only
DESCRIPTION
The function initializes the join cache structure. It supposed to be called
......@@ -1044,10 +1048,12 @@ int JOIN_CACHE::realloc_buffer()
1 otherwise
*/
int JOIN_CACHE::init()
int JOIN_CACHE::init(bool for_explain)
{
DBUG_ENTER("JOIN_CACHE::init");
for_explain_only= for_explain;
calc_record_fields();
collect_info_on_key_args();
......@@ -2632,6 +2638,7 @@ void JOIN_CACHE_BKAH::save_explain_data(struct st_explain_bka_type *explain)
SYNOPSIS
init()
for_explain join buffer is initialized for explain only
DESCRIPTION
The function initializes the cache structure with a hash table in it.
......@@ -2651,7 +2658,7 @@ void JOIN_CACHE_BKAH::save_explain_data(struct st_explain_bka_type *explain)
1 otherwise
*/
int JOIN_CACHE_HASHED::init()
int JOIN_CACHE_HASHED::init(bool for_explain)
{
int rc= 0;
TABLE_REF *ref= &join_tab->ref;
......@@ -2663,7 +2670,7 @@ int JOIN_CACHE_HASHED::init()
key_length= ref->key_length;
if ((rc= JOIN_CACHE::init()))
if ((rc= JOIN_CACHE::init(for_explain)) || for_explain)
DBUG_RETURN (rc);
if (!(key_buff= (uchar*) sql_alloc(key_length)))
......@@ -3572,6 +3579,7 @@ void JOIN_CACHE_BNL::read_next_candidate_for_match(uchar *rec_ptr)
SYNOPSIS
init
for_explain join buffer is initialized for explain only
DESCRIPTION
The function initializes the cache structure. It is supposed to be called
......@@ -3586,14 +3594,14 @@ void JOIN_CACHE_BNL::read_next_candidate_for_match(uchar *rec_ptr)
1 otherwise
*/
int JOIN_CACHE_BNL::init()
int JOIN_CACHE_BNL::init(bool for_explain)
{
DBUG_ENTER("JOIN_CACHE_BNL::init");
if (!(join_tab_scan= new JOIN_TAB_SCAN(join, join_tab)))
DBUG_RETURN(1);
DBUG_RETURN(JOIN_CACHE::init());
DBUG_RETURN(JOIN_CACHE::init(for_explain));
}
......@@ -3758,6 +3766,7 @@ void JOIN_CACHE_BNLH::read_next_candidate_for_match(uchar *rec_ptr)
SYNOPSIS
init
for_explain join buffer is initialized for explain only
DESCRIPTION
The function initializes the cache structure. It is supposed to be called
......@@ -3772,14 +3781,14 @@ void JOIN_CACHE_BNLH::read_next_candidate_for_match(uchar *rec_ptr)
1 otherwise
*/
int JOIN_CACHE_BNLH::init()
int JOIN_CACHE_BNLH::init(bool for_explain)
{
DBUG_ENTER("JOIN_CACHE_BNLH::init");
if (!(join_tab_scan= new JOIN_TAB_SCAN(join, join_tab)))
DBUG_RETURN(1);
DBUG_RETURN(JOIN_CACHE_HASHED::init());
DBUG_RETURN(JOIN_CACHE_HASHED::init(for_explain));
}
......@@ -4176,6 +4185,8 @@ Initialize the BKA join cache
SYNOPSIS
init
for_explain join buffer is initialized for explain only
DESCRIPTION
The function initializes the cache structure. It is supposed to be called
......@@ -4190,7 +4201,7 @@ RETURN VALUE
1 otherwise
*/
int JOIN_CACHE_BKA::init()
int JOIN_CACHE_BKA::init(bool for_explain)
{
int res;
bool check_only_first_match= join_tab->check_only_first_match();
......@@ -4209,7 +4220,7 @@ if (!(join_tab_scan= jsm= new JOIN_TAB_SCAN_MRR(join, join_tab,
mrr_mode, rs_funcs)))
DBUG_RETURN(1);
if ((res= JOIN_CACHE::init()))
if ((res= JOIN_CACHE::init(for_explain)))
DBUG_RETURN(res);
if (use_emb_key)
......@@ -4570,6 +4581,7 @@ if (no_association &&
SYNOPSIS
init
for_explain join buffer is initialized for explain only
DESCRIPTION
The function initializes the cache structure. It is supposed to be called
......@@ -4584,7 +4596,7 @@ if (no_association &&
1 otherwise
*/
int JOIN_CACHE_BKAH::init()
int JOIN_CACHE_BKAH::init(bool for_explain)
{
bool check_only_first_match= join_tab->check_only_first_match();
......@@ -4603,7 +4615,7 @@ int JOIN_CACHE_BKAH::init()
mrr_mode, rs_funcs)))
DBUG_RETURN(1);
DBUG_RETURN(JOIN_CACHE_HASHED::init());
DBUG_RETURN(JOIN_CACHE_HASHED::init(for_explain));
}
......
......@@ -99,6 +99,9 @@ private:
/* Size of the offset of a field within a record in the cache */
uint size_of_fld_ofs;
/* This structure is used only for explain, not for execution */
bool for_explain_only;
protected:
/* 3 functions below actually do not use the hidden parameter 'this' */
......@@ -595,7 +598,7 @@ public:
JOIN_CACHE *next_cache;
/* Shall initialize the join cache structure */
virtual int init();
virtual int init(bool for_explain);
/* Get the current size of the cache join buffer */
size_t get_join_buffer_size() { return buff_size; }
......@@ -991,7 +994,7 @@ protected:
public:
/* Initialize a hashed join cache */
int init();
int init(bool for_explain);
/* Reset the buffer of a hashed join cache for reading/writing */
void reset(bool for_writing);
......@@ -1127,7 +1130,7 @@ public:
:JOIN_CACHE(j, tab, prev) {}
/* Initialize the BNL cache */
int init();
int init(bool for_explain);
enum Join_algorithm get_join_alg() { return BNL_JOIN_ALG; }
......@@ -1194,7 +1197,7 @@ public:
: JOIN_CACHE_HASHED(j, tab, prev) {}
/* Initialize the BNLH cache */
int init();
int init(bool for_explain);
enum Join_algorithm get_join_alg() { return BNLH_JOIN_ALG; }
......@@ -1325,7 +1328,7 @@ public:
uchar **get_curr_association_ptr() { return &curr_association; }
/* Initialize the BKA cache */
int init();
int init(bool for_explain);
enum Join_algorithm get_join_alg() { return BKA_JOIN_ALG; }
......@@ -1421,7 +1424,7 @@ public:
uchar **get_curr_association_ptr() { return &curr_matching_chain; }
/* Initialize the BKAH cache */
int init();
int init(bool for_explain);
enum Join_algorithm get_join_alg() { return BKAH_JOIN_ALG; }
......
......@@ -10541,7 +10541,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
if (cache_level == 1)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BNL(join, tab, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
!tab->cache->init(options & SELECT_DESCRIBE))
{
tab->icp_other_tables_ok= FALSE;
return (2 - MY_TEST(!prev_cache));
......@@ -10576,7 +10576,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
if (cache_level == 3)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BNLH(join, tab, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
!tab->cache->init(options & SELECT_DESCRIBE))
{
tab->icp_other_tables_ok= FALSE;
return (4 - MY_TEST(!prev_cache));
......@@ -10597,7 +10597,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
if (cache_level == 5)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BKA(join, tab, flags, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
!tab->cache->init(options & SELECT_DESCRIBE))
return (6 - MY_TEST(!prev_cache));
goto no_join_cache;
}
......@@ -10606,7 +10606,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
if (cache_level == 7)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BKAH(join, tab, flags, prev_cache)) &&
((options & SELECT_DESCRIBE) || !tab->cache->init()))
!tab->cache->init(options & SELECT_DESCRIBE))
{
tab->idx_cond_fact_out= FALSE;
return (8 - MY_TEST(!prev_cache));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment