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.
This commit is contained in:
parent
216fbe2af3
commit
d42e6d3a99
@ -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
|
||||
#
|
||||
|
@ -929,6 +929,9 @@ int JOIN_CACHE::alloc_buffer()
|
||||
join->shrink_join_buffers(join_tab, curr_buff_space_sz,
|
||||
join_buff_space_limit))))
|
||||
goto fail;
|
||||
|
||||
if (for_explain_only)
|
||||
return 0;
|
||||
|
||||
for (ulong buff_size_decr= (buff_size-min_buff_size)/4 + 1; ; )
|
||||
{
|
||||
@ -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,8 +2670,8 @@ int JOIN_CACHE_HASHED::init()
|
||||
|
||||
key_length= ref->key_length;
|
||||
|
||||
if ((rc= JOIN_CACHE::init()))
|
||||
DBUG_RETURN (rc);
|
||||
if ((rc= JOIN_CACHE::init(for_explain)) || for_explain)
|
||||
DBUG_RETURN (rc);
|
||||
|
||||
if (!(key_buff= (uchar*) sql_alloc(key_length)))
|
||||
DBUG_RETURN(1);
|
||||
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user