Commit fc1c8ffd authored by Igor Babaev's avatar Igor Babaev

The pilot patch for mwl#253.

parent 938d47dc
...@@ -500,6 +500,18 @@ The following options may be given as the first argument: ...@@ -500,6 +500,18 @@ The following options may be given as the first argument:
partial_match_table_scan, semijoin, semijoin_with_cache, partial_match_table_scan, semijoin, semijoin_with_cache,
subquery_cache, table_elimination, extended_keys, subquery_cache, table_elimination, extended_keys,
exists_to_in } and val is one of {on, off, default} exists_to_in } and val is one of {on, off, default}
--optimizer-use-condition-selectivity=#
Controls selectivity of which conditions the optimizer
takes into account to calculate cardinality of a partial
join when it searches for the best execution plan
Meaning: 1 - use selectivity of index backed range
conditions to calculate cardinality of the partial join
if the last joined table is accessed by full table scan
or an index scan 2 - use selectivity of index backed
range conditions to calculate cardinality of the partial
join in any case 3 - additionally always use selectivity
of range conditions that are not backed by any index to
calculate cardinality of the partial join
--performance-schema --performance-schema
Enable the performance schema. Enable the performance schema.
--performance-schema-events-waits-history-long-size=# --performance-schema-events-waits-history-long-size=#
...@@ -1004,6 +1016,7 @@ old-style-user-limits FALSE ...@@ -1004,6 +1016,7 @@ old-style-user-limits FALSE
optimizer-prune-level 1 optimizer-prune-level 1
optimizer-search-depth 62 optimizer-search-depth 62
optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
optimizer-use-condition-selectivity 1
performance-schema FALSE performance-schema FALSE
performance-schema-events-waits-history-long-size 10000 performance-schema-events-waits-history-long-size 10000
performance-schema-events-waits-history-size 10 performance-schema-events-waits-history-size 10
......
select @@global.use_stat_tables;
@@global.use_stat_tables
COMPLEMENTARY
select @@session.use_stat_tables;
@@session.use_stat_tables
COMPLEMENTARY
set @save_use_stat_tables=@@use_stat_tables;
set use_stat_tables='preferably';
DROP DATABASE IF EXISTS dbt3_s001;
CREATE DATABASE dbt3_s001;
use dbt3_s001;
set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
EXPLAIN EXTENDED select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY supplier ALL PRIMARY,i_s_nationkey NULL NULL NULL 10 100.00 Using where; Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY nation eq_ref PRIMARY PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 100.00 Using where
2 MATERIALIZED part ALL PRIMARY NULL NULL NULL 200 100.00 Using where
2 MATERIALIZED partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 4 dbt3_s001.part.p_partkey 3 100.00 Using where
4 DEPENDENT SUBQUERY lineitem ref i_l_shipdate,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey i_l_suppkey_partkey 10 dbt3_s001.partsupp.ps_partkey,dbt3_s001.partsupp.ps_suppkey 8 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where ((`dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey`) and (`dbt3_s001`.`nation`.`n_name` = 'UNITED STATES') and (`dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey`) and (`dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select (0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`)) from `dbt3_s001`.`lineitem` where ((`dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`) and (`dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey`) and (`dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date))) and (`dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>((cast('1993-01-01' as date) + interval '1' year))))))) and (`dbt3_s001`.`part`.`p_name` like 'g%')) order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
s_name s_address
Supplier#000000010 Saygah3gYWMp72i PY
set optimizer_use_condition_selectivity=3;
EXPLAIN EXTENDED select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY nation ALL PRIMARY NULL NULL NULL 25 4.00 Using where; Using temporary; Using filesort
1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED part ALL PRIMARY NULL NULL NULL 200 4.17 Using where
2 MATERIALIZED partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 4 dbt3_s001.part.p_partkey 3 100.00 Using where
4 DEPENDENT SUBQUERY lineitem ref i_l_shipdate,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey i_l_suppkey_partkey 10 dbt3_s001.partsupp.ps_partkey,dbt3_s001.partsupp.ps_suppkey 8 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where ((`dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey`) and (`dbt3_s001`.`nation`.`n_name` = 'UNITED STATES') and (`dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey`) and (`dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select (0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`)) from `dbt3_s001`.`lineitem` where ((`dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`) and (`dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey`) and (`dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date))) and (`dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>((cast('1993-01-01' as date) + interval '1' year))))))) and (`dbt3_s001`.`part`.`p_name` like 'g%')) order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
s_name s_address
Supplier#000000010 Saygah3gYWMp72i PY
DROP DATABASE dbt3_s001;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
set use_stat_tables=@save_use_stat_tables;
SET SESSION STORAGE_ENGINE='InnoDB';
set @save_optimizer_switch_for_selectivity_test=@@optimizer_switch;
set optimizer_switch='extended_keys=on';
select @@global.use_stat_tables;
@@global.use_stat_tables
COMPLEMENTARY
select @@session.use_stat_tables;
@@session.use_stat_tables
COMPLEMENTARY
set @save_use_stat_tables=@@use_stat_tables;
set use_stat_tables='preferably';
DROP DATABASE IF EXISTS dbt3_s001;
CREATE DATABASE dbt3_s001;
use dbt3_s001;
set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
EXPLAIN EXTENDED select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY supplier ALL PRIMARY,i_s_nationkey NULL NULL NULL 10 100.00 Using where; Using filesort
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY nation eq_ref PRIMARY PRIMARY 4 dbt3_s001.supplier.s_nationkey 1 100.00 Using where
2 MATERIALIZED part ALL PRIMARY NULL NULL NULL 200 100.00 Using where
2 MATERIALIZED partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 4 dbt3_s001.part.p_partkey 3 100.00 Using where
4 DEPENDENT SUBQUERY lineitem ref i_l_shipdate,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey i_l_suppkey_partkey 10 dbt3_s001.partsupp.ps_partkey,dbt3_s001.partsupp.ps_suppkey 8 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where ((`dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey`) and (`dbt3_s001`.`nation`.`n_name` = 'UNITED STATES') and (`dbt3_s001`.`nation`.`n_nationkey` = `dbt3_s001`.`supplier`.`s_nationkey`) and (`dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select (0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`)) from `dbt3_s001`.`lineitem` where ((`dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`) and (`dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey`) and (`dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date))) and (`dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>((cast('1993-01-01' as date) + interval '1' year))))))) and (`dbt3_s001`.`part`.`p_name` like 'g%')) order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
s_name s_address
Supplier#000000010 Saygah3gYWMp72i PY
set optimizer_use_condition_selectivity=3;
EXPLAIN EXTENDED select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY nation ALL PRIMARY NULL NULL NULL 25 4.00 Using where; Using temporary; Using filesort
1 PRIMARY supplier ref PRIMARY,i_s_nationkey i_s_nationkey 5 dbt3_s001.nation.n_nationkey 1 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED part ALL PRIMARY NULL NULL NULL 200 4.17 Using where
2 MATERIALIZED partsupp ref PRIMARY,i_ps_partkey,i_ps_suppkey PRIMARY 4 dbt3_s001.part.p_partkey 3 100.00 Using where
4 DEPENDENT SUBQUERY lineitem ref i_l_shipdate,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey i_l_suppkey_partkey 10 dbt3_s001.partsupp.ps_partkey,dbt3_s001.partsupp.ps_suppkey 8 100.00 Using where
Warnings:
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_partkey' of SELECT #4 was resolved in SELECT #2
Note 1276 Field or reference 'dbt3_s001.partsupp.ps_suppkey' of SELECT #4 was resolved in SELECT #2
Note 1003 select sql_calc_found_rows `dbt3_s001`.`supplier`.`s_name` AS `s_name`,`dbt3_s001`.`supplier`.`s_address` AS `s_address` from `dbt3_s001`.`supplier` semi join (`dbt3_s001`.`part` join `dbt3_s001`.`partsupp`) join `dbt3_s001`.`nation` where ((`dbt3_s001`.`partsupp`.`ps_partkey` = `dbt3_s001`.`part`.`p_partkey`) and (`dbt3_s001`.`nation`.`n_name` = 'UNITED STATES') and (`dbt3_s001`.`supplier`.`s_nationkey` = `dbt3_s001`.`nation`.`n_nationkey`) and (`dbt3_s001`.`partsupp`.`ps_availqty` > <expr_cache><`dbt3_s001`.`partsupp`.`ps_partkey`,`dbt3_s001`.`partsupp`.`ps_suppkey`>((select (0.5 * sum(`dbt3_s001`.`lineitem`.`l_quantity`)) from `dbt3_s001`.`lineitem` where ((`dbt3_s001`.`lineitem`.`l_partkey` = `dbt3_s001`.`partsupp`.`ps_partkey`) and (`dbt3_s001`.`lineitem`.`l_suppkey` = `dbt3_s001`.`partsupp`.`ps_suppkey`) and (`dbt3_s001`.`lineitem`.`l_shipDATE` >= <cache>(cast('1993-01-01' as date))) and (`dbt3_s001`.`lineitem`.`l_shipDATE` < <cache>((cast('1993-01-01' as date) + interval '1' year))))))) and (`dbt3_s001`.`part`.`p_name` like 'g%')) order by `dbt3_s001`.`supplier`.`s_name` limit 10
select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
s_name s_address
Supplier#000000010 Saygah3gYWMp72i PY
DROP DATABASE dbt3_s001;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
set use_stat_tables=@save_use_stat_tables;
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
SET SESSION STORAGE_ENGINE=DEFAULT;
SET @start_global_value = @@global.optimizer_use_condition_selectivity;
SELECT @start_global_value;
@start_global_value
1
SET @start_session_value = @@session.optimizer_use_condition_selectivity;
SELECT @start_session_value;
@start_session_value
1
'#--------------------FN_DYNVARS_115_01-------------------------#'
SET @@global.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@global.optimizer_use_condition_selectivity;
@@global.optimizer_use_condition_selectivity
1
SET @@session.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@session.optimizer_use_condition_selectivity;
@@session.optimizer_use_condition_selectivity
1
'#--------------------FN_DYNVARS_115_02-------------------------#'
SET @@global.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@global.optimizer_use_condition_selectivity = 1;
@@global.optimizer_use_condition_selectivity = 1
1
SET @@session.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@session.optimizer_use_condition_selectivity = 1;
@@session.optimizer_use_condition_selectivity = 1
1
'#--------------------FN_DYNVARS_115_03-------------------------#'
SELECT @@global.optimizer_use_condition_selectivity;
@@global.optimizer_use_condition_selectivity
1
SET @@global.optimizer_use_condition_selectivity = 1;
SELECT @@global.optimizer_use_condition_selectivity;
@@global.optimizer_use_condition_selectivity
1
SET @@global.optimizer_use_condition_selectivity = 2;
SELECT @@global.optimizer_use_condition_selectivity;
@@global.optimizer_use_condition_selectivity
2
SET @@global.optimizer_use_condition_selectivity = 3;
SELECT @@global.optimizer_use_condition_selectivity;
@@global.optimizer_use_condition_selectivity
3
'#--------------------FN_DYNVARS_115_04-------------------------#'
SELECT @@session.optimizer_use_condition_selectivity;
@@session.optimizer_use_condition_selectivity
1
SET @@session.optimizer_use_condition_selectivity = 1;
SELECT @@session.optimizer_use_condition_selectivity;
@@session.optimizer_use_condition_selectivity
1
SET @@session.optimizer_use_condition_selectivity = 2;
SELECT @@session.optimizer_use_condition_selectivity;
@@session.optimizer_use_condition_selectivity
2
SET @@session.optimizer_use_condition_selectivity = 3;
SELECT @@session.optimizer_use_condition_selectivity;
@@session.optimizer_use_condition_selectivity
3
'#------------------FN_DYNVARS_115_05-----------------------#'
SET @@global.optimizer_use_condition_selectivity = ON;
ERROR 42000: Incorrect argument type to variable 'optimizer_use_condition_selectivity'
SET @@global.optimizer_use_condition_selectivity = OFF;
ERROR 42000: Incorrect argument type to variable 'optimizer_use_condition_selectivity'
SET @@session.optimizer_use_condition_selectivity = 65530.34;
ERROR 42000: Incorrect argument type to variable 'optimizer_use_condition_selectivity'
SET @@session.optimizer_use_condition_selectivity = test;
ERROR 42000: Incorrect argument type to variable 'optimizer_use_condition_selectivity'
'#------------------FN_DYNVARS_115_06-----------------------#'
SELECT @@global.optimizer_use_condition_selectivity = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='optimizer_use_condition_selectivity';
@@global.optimizer_use_condition_selectivity = VARIABLE_VALUE
1
'#------------------FN_DYNVARS_115_07-----------------------#'
SELECT @@session.optimizer_use_condition_selectivity = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='optimizer_use_condition_selectivity';
@@session.optimizer_use_condition_selectivity = VARIABLE_VALUE
1
'#---------------------FN_DYNVARS_115_08----------------------#'
SET @@optimizer_use_condition_selectivity = 1;
SET @@global.optimizer_use_condition_selectivity = 3;
SELECT @@optimizer_use_condition_selectivity = @@global.optimizer_use_condition_selectivity;
@@optimizer_use_condition_selectivity = @@global.optimizer_use_condition_selectivity
0
'#---------------------FN_DYNVARS_115_09----------------------#'
SET @@optimizer_use_condition_selectivity = 2;
SELECT @@optimizer_use_condition_selectivity = @@local.optimizer_use_condition_selectivity;
@@optimizer_use_condition_selectivity = @@local.optimizer_use_condition_selectivity
1
SELECT @@local.optimizer_use_condition_selectivity = @@session.optimizer_use_condition_selectivity;
@@local.optimizer_use_condition_selectivity = @@session.optimizer_use_condition_selectivity
1
SET @@global.optimizer_use_condition_selectivity = @start_global_value;
SELECT @@global.optimizer_use_condition_selectivity;
@@global.optimizer_use_condition_selectivity
1
SET @@session.optimizer_use_condition_selectivity = @start_session_value;
SELECT @@session.optimizer_use_condition_selectivity;
@@session.optimizer_use_condition_selectivity
1
--source include/load_sysvars.inc
#################################################################
# START OF optimizer_use_condition_selectivity TESTS #
#################################################################
#############################################################
# Save initial value #
#############################################################
SET @start_global_value = @@global.optimizer_use_condition_selectivity;
SELECT @start_global_value;
SET @start_session_value = @@session.optimizer_use_condition_selectivity;
SELECT @start_session_value;
--echo '#--------------------FN_DYNVARS_115_01-------------------------#'
#########################################################################
# Display the DEFAULT value of optimizer_use_condition_selectivity #
#########################################################################
SET @@global.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@global.optimizer_use_condition_selectivity;
SET @@session.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@session.optimizer_use_condition_selectivity;
--echo '#--------------------FN_DYNVARS_115_02-------------------------#'
#########################################################################
# Check the DEFAULT value of optimizer_use_condition_selectivity #
#########################################################################
SET @@global.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@global.optimizer_use_condition_selectivity = 1;
SET @@session.optimizer_use_condition_selectivity = DEFAULT;
SELECT @@session.optimizer_use_condition_selectivity = 1;
--echo '#--------------------FN_DYNVARS_115_03-------------------------#'
#############################################################################################
# Change the value of optimizer_use_condition_selectivity to a valid value for GLOBAL Scope #
#############################################################################################
SELECT @@global.optimizer_use_condition_selectivity;
SET @@global.optimizer_use_condition_selectivity = 1;
SELECT @@global.optimizer_use_condition_selectivity;
SET @@global.optimizer_use_condition_selectivity = 2;
SELECT @@global.optimizer_use_condition_selectivity;
SET @@global.optimizer_use_condition_selectivity = 3;
SELECT @@global.optimizer_use_condition_selectivity;
--echo '#--------------------FN_DYNVARS_115_04-------------------------#'
#############################################################################################
# Change the value of optimizer_use_condition_selectivity to a valid value for SESSION Scope#
#############################################################################################
SELECT @@session.optimizer_use_condition_selectivity;
SET @@session.optimizer_use_condition_selectivity = 1;
SELECT @@session.optimizer_use_condition_selectivity;
SET @@session.optimizer_use_condition_selectivity = 2;
SELECT @@session.optimizer_use_condition_selectivity;
SET @@session.optimizer_use_condition_selectivity = 3;
SELECT @@session.optimizer_use_condition_selectivity;
--echo '#------------------FN_DYNVARS_115_05-----------------------#'
###############################################################################
# Change the value of optimizer_use_condition_selectivity to an invalid value #
##############################################################################
--Error ER_WRONG_TYPE_FOR_VAR
SET @@global.optimizer_use_condition_selectivity = ON;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@global.optimizer_use_condition_selectivity = OFF;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.optimizer_use_condition_selectivity = 65530.34;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.optimizer_use_condition_selectivity = test;
--echo '#------------------FN_DYNVARS_115_06-----------------------#'
####################################################################
# Check if the value in GLOBAL Table matches value in variable #
####################################################################
SELECT @@global.optimizer_use_condition_selectivity = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='optimizer_use_condition_selectivity';
--echo '#------------------FN_DYNVARS_115_07-----------------------#'
####################################################################
# Check if the value in SESSION Table matches value in variable #
####################################################################
SELECT @@session.optimizer_use_condition_selectivity = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='optimizer_use_condition_selectivity';
--echo '#---------------------FN_DYNVARS_115_08----------------------#'
###############################################################################
# Check if global and session variable are independent of each other #
###############################################################################
SET @@optimizer_use_condition_selectivity = 1;
SET @@global.optimizer_use_condition_selectivity = 3;
SELECT @@optimizer_use_condition_selectivity = @@global.optimizer_use_condition_selectivity;
--echo '#---------------------FN_DYNVARS_115_09----------------------#'
###############################################################################
# Check if accessing variable with SESSION,LOCAL and without SCOPE points #
# to same session variable #
###############################################################################
SET @@optimizer_use_condition_selectivity = 2;
SELECT @@optimizer_use_condition_selectivity = @@local.optimizer_use_condition_selectivity;
SELECT @@local.optimizer_use_condition_selectivity = @@session.optimizer_use_condition_selectivity;
####################################
# Restore initial value #
####################################
SET @@global.optimizer_use_condition_selectivity = @start_global_value;
SELECT @@global.optimizer_use_condition_selectivity;
SET @@session.optimizer_use_condition_selectivity = @start_session_value;
SELECT @@session.optimizer_use_condition_selectivity;
########################################################################
# END OF optimizer_use_condition_selectivity TESTS #
########################################################################
--source include/have_stat_tables.inc
select @@global.use_stat_tables;
select @@session.use_stat_tables;
set @save_use_stat_tables=@@use_stat_tables;
set use_stat_tables='preferably';
--disable_warnings
DROP DATABASE IF EXISTS dbt3_s001;
--enable_warnings
CREATE DATABASE dbt3_s001;
use dbt3_s001;
set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
--disable_query_log
--disable_result_log
--disable_warnings
--source include/dbt3_s001.inc
ANALYZE TABLE
customer, lineitem, nation, orders, part, partsupp, region, supplier;
FLUSH TABLE
customer, lineitem, nation, orders, part, partsupp, region, supplier;
--enable_warnings
--enable_result_log
--enable_query_log
let $Q20=
select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
where ps_partkey in (select p_partkey from part
where p_name like 'g%')
and ps_availqty >
(select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey
and l_suppkey = ps_suppkey
and l_shipdate >= date('1993-01-01')
and l_shipdate < date('1993-01-01') +
interval '1' year ))
and s_nationkey = n_nationkey
and n_name = 'UNITED STATES'
order by s_name
limit 10;
eval EXPLAIN EXTENDED $Q20;
eval $Q20;
set optimizer_use_condition_selectivity=3;
eval EXPLAIN EXTENDED $Q20;
eval $Q20;
DROP DATABASE dbt3_s001;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
set use_stat_tables=@save_use_stat_tables;
--source include/have_innodb.inc
SET SESSION STORAGE_ENGINE='InnoDB';
set @save_optimizer_switch_for_selectivity_test=@@optimizer_switch;
set optimizer_switch='extended_keys=on';
--source selectivity.test
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
SET SESSION STORAGE_ENGINE=DEFAULT;
...@@ -1273,6 +1273,20 @@ out_of_range: ...@@ -1273,6 +1273,20 @@ out_of_range:
return 1; return 1;
} }
double Field_num::middle_point_pos(Field *min, Field *max)
{
double n, d;
n= val_real() - min->val_real();
if (n < 0)
return 0.0;
d= max->val_real() - min->val_real();
if (d <= 0)
return 1.0;
return min(n/d, 1.0);
}
/** /**
Process decimal library return codes and issue warnings for overflow and Process decimal library return codes and issue warnings for overflow and
truncation. truncation.
...@@ -1344,6 +1358,8 @@ Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, ...@@ -1344,6 +1358,8 @@ Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
comment.length=0; comment.length=0;
field_index= 0; field_index= 0;
is_stat_field= FALSE; is_stat_field= FALSE;
cond_selectivity= 1.0;
next_equal_field= NULL;
} }
...@@ -6167,6 +6183,46 @@ int Field_str::store(double nr) ...@@ -6167,6 +6183,46 @@ int Field_str::store(double nr)
return store(buff, length, &my_charset_numeric); return store(buff, length, &my_charset_numeric);
} }
static
inline ulonglong char_prefix_to_ulonglong(uchar *src)
{
uint sz= sizeof(ulonglong);
for (uint i= 0; i < sz/2; i++)
{
uchar tmp= src[i];
src[i]= src[sz-1-i];
src[sz-1-i]= tmp;
}
return uint8korr(src);
}
double Field_str::middle_point_pos(Field *min, Field *max)
{
uchar mp_prefix[sizeof(ulonglong)];
uchar minp_prefix[sizeof(ulonglong)];
uchar maxp_prefix[sizeof(ulonglong)];
ulonglong mp, minp, maxp;
my_strnxfrm(charset(), mp_prefix, sizeof(mp),
ptr + length_size(), sizeof(mp) * charset()->mbmaxlen);
my_strnxfrm(charset(), minp_prefix, sizeof(minp),
min->ptr + length_size(),
sizeof(minp) * charset()->mbmaxlen);
my_strnxfrm(charset(), maxp_prefix, sizeof(maxp),
max->ptr + length_size(),
sizeof(maxp) * charset()->mbmaxlen);
mp= char_prefix_to_ulonglong(mp_prefix);
minp= char_prefix_to_ulonglong(minp_prefix);
maxp= char_prefix_to_ulonglong(maxp_prefix);
double n, d;
n= mp - minp;
if (n < 0)
return 0.0;
d= maxp - minp;
if (d <= 0)
return 1.0;
return min(n/d, 1.0);
}
uint Field::is_equal(Create_field *new_field) uint Field::is_equal(Create_field *new_field)
{ {
......
...@@ -220,7 +220,23 @@ public: ...@@ -220,7 +220,23 @@ public:
*/ */
bool is_created_from_null_item; bool is_created_from_null_item;
bool is_stat_field; /* TRUE in Field objects created for column min/max values */ /* TRUE in Field objects created for column min/max values */
bool is_stat_field;
/*
Selectivity of the range condition over this field.
When calculating this selectivity a range predicate
is taken into account only if:
- it is extracted from the WHERE clause
- it depends only on the table the field belongs to
*/
double cond_selectivity;
/*
The next field in the class of equal fields at the top AND level
of the WHERE clause
*/
Field *next_equal_field;
/* /*
This structure is used for statistical data on the column This structure is used for statistical data on the column
...@@ -703,6 +719,11 @@ public: ...@@ -703,6 +719,11 @@ public:
virtual bool hash_join_is_possible() { return TRUE; } virtual bool hash_join_is_possible() { return TRUE; }
virtual bool eq_cmp_as_binary() { return TRUE; } virtual bool eq_cmp_as_binary() { return TRUE; }
virtual double middle_point_pos(Field *min, Field *max)
{
return (double) 1.0;
}
friend int cre_myisam(char * name, register TABLE *form, uint options, friend int cre_myisam(char * name, register TABLE *form, uint options,
ulonglong auto_increment_value); ulonglong auto_increment_value);
friend class Copy_field; friend class Copy_field;
...@@ -821,6 +842,7 @@ public: ...@@ -821,6 +842,7 @@ public:
bool get_int(CHARSET_INFO *cs, const char *from, uint len, bool get_int(CHARSET_INFO *cs, const char *from, uint len,
longlong *rnd, ulonglong unsigned_max, longlong *rnd, ulonglong unsigned_max,
longlong signed_min, longlong signed_max); longlong signed_min, longlong signed_max);
double middle_point_pos(Field *min, Field *max);
}; };
...@@ -866,6 +888,8 @@ public: ...@@ -866,6 +888,8 @@ public:
virtual bool str_needs_quotes() { return TRUE; } virtual bool str_needs_quotes() { return TRUE; }
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
bool eq_cmp_as_binary() { return test(flags & BINARY_FLAG); } bool eq_cmp_as_binary() { return test(flags & BINARY_FLAG); }
virtual uint length_size() { return 0; }
double middle_point_pos(Field *min, Field *max);
}; };
/* base class for Field_string, Field_varstring and Field_blob */ /* base class for Field_string, Field_varstring and Field_blob */
...@@ -1894,6 +1918,7 @@ public: ...@@ -1894,6 +1918,7 @@ public:
uint new_null_bit); uint new_null_bit);
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
void hash(ulong *nr, ulong *nr2); void hash(ulong *nr, ulong *nr2);
uint length_size() { return length_bytes; }
private: private:
int do_save_field_metadata(uchar *first_byte); int do_save_field_metadata(uchar *first_byte);
}; };
......
...@@ -5567,7 +5567,8 @@ Item *Item_bool_rowready_func2::negated_item() ...@@ -5567,7 +5567,8 @@ Item *Item_bool_rowready_func2::negated_item()
*/ */
Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item) Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item)
: Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL) : Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL),
link_equal_fields(FALSE)
{ {
const_item_cache= 0; const_item_cache= 0;
with_const= with_const_item; with_const= with_const_item;
...@@ -5590,7 +5591,8 @@ Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item) ...@@ -5590,7 +5591,8 @@ Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item)
*/ */
Item_equal::Item_equal(Item_equal *item_equal) Item_equal::Item_equal(Item_equal *item_equal)
: Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL) : Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL),
link_equal_fields(FALSE)
{ {
const_item_cache= 0; const_item_cache= 0;
List_iterator_fast<Item> li(item_equal->equal_items); List_iterator_fast<Item> li(item_equal->equal_items);
...@@ -5833,6 +5835,9 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) ...@@ -5833,6 +5835,9 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
Item_equal_fields_iterator it(*this); Item_equal_fields_iterator it(*this);
Item *item; Item *item;
Field *first_equal_field;
Field *last_equal_field;
Field *prev_equal_field= NULL;
not_null_tables_cache= used_tables_cache= 0; not_null_tables_cache= used_tables_cache= 0;
const_item_cache= 0; const_item_cache= 0;
while ((item= it++)) while ((item= it++))
...@@ -5846,7 +5851,18 @@ bool Item_equal::fix_fields(THD *thd, Item **ref) ...@@ -5846,7 +5851,18 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
maybe_null= 1; maybe_null= 1;
if (!item->get_item_equal()) if (!item->get_item_equal())
item->set_item_equal(this); item->set_item_equal(this);
if (link_equal_fields && item->real_item()->type() == FIELD_ITEM)
{
last_equal_field= ((Item_field *) (item->real_item()))->field;
if (!prev_equal_field)
first_equal_field= last_equal_field;
else
prev_equal_field->next_equal_field= last_equal_field;
prev_equal_field= last_equal_field;
}
} }
if (prev_equal_field && last_equal_field != first_equal_field)
last_equal_field->next_equal_field= first_equal_field;
fix_length_and_dec(); fix_length_and_dec();
fixed= 1; fixed= 1;
return FALSE; return FALSE;
......
...@@ -1730,6 +1730,7 @@ class Item_equal: public Item_bool_func ...@@ -1730,6 +1730,7 @@ class Item_equal: public Item_bool_func
used in the original equality. used in the original equality.
*/ */
Item_field *context_field; Item_field *context_field;
bool link_equal_fields;
public: public:
inline Item_equal() inline Item_equal()
: Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0), : Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0),
...@@ -1762,6 +1763,7 @@ public: ...@@ -1762,6 +1763,7 @@ public:
CHARSET_INFO *compare_collation(); CHARSET_INFO *compare_collation();
void set_context_field(Item_field *ctx_field) { context_field= ctx_field; } void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }
void set_link_equal_fields(bool flag) { link_equal_fields= flag; }
friend class Item_equal_fields_iterator; friend class Item_equal_fields_iterator;
friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
Item_equal *item_equal); Item_equal *item_equal);
......
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
#include "records.h" // init_read_record, end_read_record #include "records.h" // init_read_record, end_read_record
#include <m_ctype.h> #include <m_ctype.h>
#include "sql_select.h" #include "sql_select.h"
#include "sql_statistics.h"
#include "filesort.h" // filesort_free_buffers #include "filesort.h" // filesort_free_buffers
#ifndef EXTRA_DEBUG #ifndef EXTRA_DEBUG
...@@ -3211,6 +3212,224 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -3211,6 +3212,224 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_RETURN(records ? test(quick) : -1); DBUG_RETURN(records ? test(quick) : -1);
} }
/****************************************************************************
* Condition selectivity module
****************************************************************************/
static
bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
MY_BITMAP *used_fields)
{
Field **field_ptr;
TABLE *table= param->table;
uint parts= 0;
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
if (bitmap_is_set(used_fields, (*field_ptr)->field_index))
parts++;
}
KEY_PART *key_part;
uint keys= 0;
if (!(key_part= (KEY_PART *) alloc_root(param->mem_root,
sizeof(KEY_PART) * parts)))
return TRUE;
param->key_parts= key_part;
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
if (bitmap_is_set(used_fields, (*field_ptr)->field_index))
{
Field *field= *field_ptr;
uint16 store_length;
key_part->key= keys;
key_part->part= 0;
key_part->length= (uint16) field->key_length();
store_length= key_part->length;
if (field->real_maybe_null())
store_length+= HA_KEY_NULL_LENGTH;
if (field->real_type() == MYSQL_TYPE_VARCHAR)
store_length+= HA_KEY_BLOB_LENGTH;
key_part->store_length= store_length;
key_part->field= field;
key_part->image_type= Field::itRAW;
param->key[keys]= key_part;
keys++;
key_part++;
}
}
param->keys= keys;
param->key_parts_end= key_part;
return FALSE;
}
static
double records_in_column_ranges(PARAM *param, uint idx,
SEL_ARG *tree)
{
SEL_ARG_RANGE_SEQ seq;
KEY_MULTI_RANGE range;
range_seq_t seq_it;
double rows;
Field *field;
uint flags= 0;
double total_rows= 0;
RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init,
sel_arg_range_seq_next, 0, 0};
/* Handle cases when we don't have a valid non-empty list of range */
if (!tree)
return HA_POS_ERROR;
if (tree->type == SEL_ARG::IMPOSSIBLE)
return (0L);
field= tree->field;
seq.keyno= idx;
seq.real_keyno= MAX_KEY;
seq.param= param;
seq.start= tree;
seq_it= seq_if.init((void *) &seq, 0, flags);
while (!seq_if.next(seq_it, &range))
{
key_range *min_endp, *max_endp;
min_endp= range.start_key.length? &range.start_key : NULL;
max_endp= range.end_key.length? &range.end_key : NULL;
rows= get_column_range_cardinality(field, min_endp, max_endp);
if (HA_POS_ERROR == rows)
{
total_rows= HA_POS_ERROR;
break;
}
total_rows += rows;
}
return total_rows;
}
bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond)
{
uint keynr;
uint max_quick_key_parts= 0;
MY_BITMAP *used_fields= &table->cond_set;
double table_records= table->stat_records();
DBUG_ENTER("calculate_cond_selectivity_for_table");
table->cond_selectivity= 1.0;
if (bitmap_is_clear_all(used_fields))
DBUG_RETURN(FALSE);
PARAM param;
MEM_ROOT alloc;
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
param.thd= thd;
param.mem_root= &alloc;
param.old_root= thd->mem_root;
param.table= table;
param.is_ror_scan= FALSE;
if (create_key_parts_for_pseudo_indexes(&param, used_fields))
{
free_root(&alloc, MYF(0));
DBUG_RETURN(FALSE);
}
param.prev_tables= param.read_tables= 0;
param.current_table= table->map;
param.using_real_indexes= FALSE;
param.real_keynr[0]= 0;
param.alloced_sel_args= 0;
thd->no_errors=1; // Don't warn about NULL
SEL_TREE *tree;
SEL_ARG **key, **end;
uint idx= 0;
tree= get_mm_tree(&param, cond);
if (!tree)
goto end;
for (key= tree->keys, end= key + param.keys; key != end; key++, idx++)
{
double rows;
if (*key)
{
rows= records_in_column_ranges(&param, idx, *key);
if (rows != HA_POS_ERROR)
(*key)->field->cond_selectivity= rows/table_records;
}
}
for (Field **field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *table_field= *field_ptr;
if (bitmap_is_set(table->read_set, table_field->field_index) &&
table_field->cond_selectivity < 1.0)
table->cond_selectivity*= table_field->cond_selectivity;
}
/* Calculate the selectivity of the range conditions supported by indexes */
bitmap_clear_all(used_fields);
for (keynr= 0; keynr < table->s->keys; keynr++)
{
if (table->quick_keys.is_set(keynr))
set_if_bigger(max_quick_key_parts, table->quick_key_parts[keynr]);
}
for (uint quick_key_parts= max_quick_key_parts;
quick_key_parts; quick_key_parts--)
{
for (keynr= 0; keynr < table->s->keys; keynr++)
{
if (table->quick_keys.is_set(keynr) &&
table->quick_key_parts[keynr] == quick_key_parts)
{
uint i;
uint used_key_parts= table->quick_key_parts[keynr];
double quick_cond_selectivity= table->quick_rows[keynr] /
table_records;
KEY *key_info= table->key_info + keynr;
KEY_PART_INFO* key_part= key_info->key_part;
for (i= 0; i < used_key_parts; i++, key_part++)
{
if (bitmap_is_set(used_fields, key_part->fieldnr-1))
break;
bitmap_set_bit(used_fields, key_part->fieldnr-1);
}
if (i)
{
double f1= key_info->actual_rec_per_key(i-1);
double f2= key_info->actual_rec_per_key(i);
table->cond_selectivity*= quick_cond_selectivity * f1 / f2;
}
}
}
}
end:
thd->mem_root= param.old_root;
free_root(&alloc, MYF(0));
DBUG_RETURN(FALSE);
}
/****************************************************************************
* Condition selectivity code ends
****************************************************************************/
/**************************************************************************** /****************************************************************************
* Partition pruning module * Partition pruning module
****************************************************************************/ ****************************************************************************/
......
...@@ -1042,6 +1042,8 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, ...@@ -1042,6 +1042,8 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, table_map read_tables, COND *conds,
bool allow_null_cond, int *error); bool allow_null_cond, int *error);
bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond);
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond); bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
void store_key_image_to_rec(Field *field, uchar *ptr, uint len); void store_key_image_to_rec(Field *field, uchar *ptr, uint len);
......
...@@ -268,8 +268,10 @@ walk_up_n_right: ...@@ -268,8 +268,10 @@ walk_up_n_right:
range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts); range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts);
if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag && if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
(uint)key_tree->part+1 == seq->param->table->key_info[seq->real_keyno].key_parts && (seq->real_keyno == MAX_KEY ||
(seq->param->table->key_info[seq->real_keyno].flags & HA_NOSAME) && ((uint)key_tree->part+1 ==
seq->param->table->key_info[seq->real_keyno].key_parts &&
(seq->param->table->key_info[seq->real_keyno].flags & HA_NOSAME))) &&
range->start_key.length == range->end_key.length && range->start_key.length == range->end_key.length &&
!memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length)) !memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length))
range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE); range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
......
...@@ -3889,7 +3889,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) ...@@ -3889,7 +3889,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
&tmpname, (uint) strlen(path)+1, &tmpname, (uint) strlen(path)+1,
&group_buff, (!using_unique_constraint ? &group_buff, (!using_unique_constraint ?
uniq_tuple_length_arg : 0), uniq_tuple_length_arg : 0),
&bitmaps, bitmap_buffer_size(1)*3, &bitmaps, bitmap_buffer_size(1)*5,
NullS)) NullS))
{ {
if (temp_pool_slot != MY_BIT_NONE) if (temp_pool_slot != MY_BIT_NONE)
......
...@@ -283,6 +283,7 @@ public: ...@@ -283,6 +283,7 @@ public:
{ {
pos->records_read= best_loose_scan_records; pos->records_read= best_loose_scan_records;
pos->key= best_loose_scan_start_key; pos->key= best_loose_scan_start_key;
pos->cond_selectivity= 1.0;
pos->loosescan_picker.loosescan_key= best_loose_scan_key; pos->loosescan_picker.loosescan_key= best_loose_scan_key;
pos->loosescan_picker.loosescan_parts= best_max_loose_keypart + 1; pos->loosescan_picker.loosescan_parts= best_max_loose_keypart + 1;
pos->use_join_buffer= FALSE; pos->use_join_buffer= FALSE;
......
...@@ -499,6 +499,7 @@ typedef struct system_variables ...@@ -499,6 +499,7 @@ typedef struct system_variables
ulong net_write_timeout; ulong net_write_timeout;
ulong optimizer_prune_level; ulong optimizer_prune_level;
ulong optimizer_search_depth; ulong optimizer_search_depth;
ulong optimizer_use_condition_selectivity;
ulong use_stat_tables; ulong use_stat_tables;
ulong preload_buff_size; ulong preload_buff_size;
ulong profiling_history_size; ulong profiling_history_size;
......
...@@ -228,6 +228,7 @@ template <class T> bool valid_buffer_range(T jump, ...@@ -228,6 +228,7 @@ template <class T> bool valid_buffer_range(T jump,
#define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 26) #define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 26)
#define OPTIMIZER_SWITCH_EXTENDED_KEYS (1ULL << 27) #define OPTIMIZER_SWITCH_EXTENDED_KEYS (1ULL << 27)
#define OPTIMIZER_SWITCH_EXISTS_TO_IN (1ULL << 28) #define OPTIMIZER_SWITCH_EXISTS_TO_IN (1ULL << 28)
#define OPTIMIZER_SWITCH_USE_CONDITION_SELECTIVITY (1ULL << 29)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
......
This diff is collapsed.
...@@ -292,6 +292,8 @@ typedef struct st_join_table { ...@@ -292,6 +292,8 @@ typedef struct st_join_table {
/* psergey-todo: make the below have type double, like POSITION::records_read? */ /* psergey-todo: make the below have type double, like POSITION::records_read? */
ha_rows records_read; ha_rows records_read;
double cond_selectivity;
/* Startup cost for execution */ /* Startup cost for execution */
double startup_cost; double startup_cost;
...@@ -762,6 +764,8 @@ typedef struct st_position :public Sql_alloc ...@@ -762,6 +764,8 @@ typedef struct st_position :public Sql_alloc
*/ */
double records_read; double records_read;
double cond_selectivity;
/* /*
Cost accessing the table in course of the entire complete join execution, Cost accessing the table in course of the entire complete join execution,
i.e. cost of one access method use (e.g. 'range' or 'ref' scan ) times i.e. cost of one access method use (e.g. 'range' or 'ref' scan ) times
...@@ -1804,6 +1808,8 @@ void eliminate_tables(JOIN *join); ...@@ -1804,6 +1808,8 @@ void eliminate_tables(JOIN *join);
/* Index Condition Pushdown entry point function */ /* Index Condition Pushdown entry point function */
void push_index_cond(JOIN_TAB *tab, uint keyno); void push_index_cond(JOIN_TAB *tab, uint keyno);
#define OPT_LINK_EQUAL_FIELDS 1
/**************************************************************************** /****************************************************************************
Temporary table support for SQL Runtime Temporary table support for SQL Runtime
***************************************************************************/ ***************************************************************************/
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "sql_base.h" #include "sql_base.h"
#include "key.h" #include "key.h"
#include "sql_statistics.h" #include "sql_statistics.h"
#include "opt_range.h"
#include "my_atomic.h" #include "my_atomic.h"
/* /*
...@@ -3054,3 +3055,51 @@ void set_statistics_for_table(THD *thd, TABLE *table) ...@@ -3054,3 +3055,51 @@ void set_statistics_for_table(THD *thd, TABLE *table)
key_info->read_stats->get_avg_frequency(0) > 0.5); key_info->read_stats->get_avg_frequency(0) > 0.5);
} }
} }
double get_column_avg_frequency(Field * field)
{
double res;
TABLE *table= field->table;
Column_statistics *col_stats= table->s->field[field->field_index]->read_stats;
if (!col_stats)
res= table->stat_records();
else
res= col_stats->get_avg_frequency();
return res;
}
double get_column_range_cardinality(Field *field,
key_range *min_endp,
key_range *max_endp)
{
double res;
TABLE *table= field->table;
Column_statistics *col_stats= table->field[field->field_index]->read_stats;
if (!col_stats)
res= table->stat_records();
else if (min_endp->length == max_endp->length &&
!memcmp(min_endp->key, max_endp->key, min_endp->length))
{
res= col_stats->get_avg_frequency();
}
else
{
if (col_stats->min_value && col_stats->max_value)
{
store_key_image_to_rec(field, (uchar *) min_endp->key, min_endp->length);
double min_mp_pos= field->middle_point_pos(col_stats->min_value,
col_stats->max_value);
store_key_image_to_rec(field, (uchar *) max_endp->key, max_endp->length);
double max_mp_pos= field->middle_point_pos(col_stats->min_value,
col_stats->max_value);
res= table->stat_records() * (max_mp_pos - min_mp_pos);
}
else
res= table->stat_records();
}
return res;
}
...@@ -90,6 +90,12 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col, ...@@ -90,6 +90,12 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col,
const char *new_name); const char *new_name);
void set_statistics_for_table(THD *thd, TABLE *table); void set_statistics_for_table(THD *thd, TABLE *table);
double get_column_avg_frequency(Field * field);
double get_column_range_cardinality(Field *field,
key_range *min_endp,
key_range *max_endp);
class Columns_statistics; class Columns_statistics;
class Index_statistics; class Index_statistics;
......
...@@ -1424,6 +1424,22 @@ static Sys_var_ulong Sys_optimizer_prune_level( ...@@ -1424,6 +1424,22 @@ static Sys_var_ulong Sys_optimizer_prune_level(
SESSION_VAR(optimizer_prune_level), CMD_LINE(REQUIRED_ARG), SESSION_VAR(optimizer_prune_level), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, 1), DEFAULT(1), BLOCK_SIZE(1)); VALID_RANGE(0, 1), DEFAULT(1), BLOCK_SIZE(1));
static Sys_var_ulong Sys_optimizer_use_condition_selectivity(
"optimizer_use_condition_selectivity",
"Controls selectivity of which conditions the optimizer takes into "
"account to calculate cardinality of a partial join when it searches "
"for the best execution plan "
"Meaning: "
"1 - use selectivity of index backed range conditions to calculate "
"cardinality of the partial join if the last joined table is "
"accessed by full table scan or an index scan "
"2 - use selectivity of index backed range conditions to calculate "
"cardinality of the partial join in any case "
"3 - additionally always use selectivity of range conditions that are "
"not backed by any index to calculate cardinality of the partial join",
SESSION_VAR(optimizer_use_condition_selectivity), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1, 3), DEFAULT(1), BLOCK_SIZE(1));
/** Warns about deprecated value 63 */ /** Warns about deprecated value 63 */
static bool fix_optimizer_search_depth(sys_var *self, THD *thd, static bool fix_optimizer_search_depth(sys_var *self, THD *thd,
enum_var_type type) enum_var_type type)
......
...@@ -2630,7 +2630,7 @@ partititon_err: ...@@ -2630,7 +2630,7 @@ partititon_err:
/* Allocate bitmaps */ /* Allocate bitmaps */
bitmap_size= share->column_bitmap_size; bitmap_size= share->column_bitmap_size;
if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*5))) if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*6)))
goto err; goto err;
bitmap_init(&outparam->def_read_set, bitmap_init(&outparam->def_read_set,
(my_bitmap_map*) bitmaps, share->fields, FALSE); (my_bitmap_map*) bitmaps, share->fields, FALSE);
...@@ -2642,8 +2642,12 @@ partititon_err: ...@@ -2642,8 +2642,12 @@ partititon_err:
(my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields, FALSE); (my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields, FALSE);
bitmap_init(&outparam->eq_join_set, bitmap_init(&outparam->eq_join_set,
(my_bitmap_map*) (bitmaps+bitmap_size*4), share->fields, FALSE); (my_bitmap_map*) (bitmaps+bitmap_size*4), share->fields, FALSE);
bitmap_init(&outparam->cond_set,
(my_bitmap_map*) (bitmaps+bitmap_size*5), share->fields, FALSE);
outparam->default_column_bitmaps(); outparam->default_column_bitmaps();
outparam->cond_selectivity= 1.0;
/* The table struct is now initialized; Open the table */ /* The table struct is now initialized; Open the table */
error= 2; error= 2;
if (db_stat) if (db_stat)
......
...@@ -1026,6 +1026,7 @@ public: ...@@ -1026,6 +1026,7 @@ public:
my_bitmap_map *bitmap_init_value; my_bitmap_map *bitmap_init_value;
MY_BITMAP def_read_set, def_write_set, def_vcol_set, tmp_set; MY_BITMAP def_read_set, def_write_set, def_vcol_set, tmp_set;
MY_BITMAP eq_join_set; /* used to mark equi-joined fields */ MY_BITMAP eq_join_set; /* used to mark equi-joined fields */
MY_BITMAP cond_set; /* used to mark fields from sargable conditions*/
MY_BITMAP *read_set, *write_set, *vcol_set; /* Active column sets */ MY_BITMAP *read_set, *write_set, *vcol_set; /* Active column sets */
/* /*
The ID of the query that opened and is using this table. Has different The ID of the query that opened and is using this table. Has different
...@@ -1078,6 +1079,8 @@ public: ...@@ -1078,6 +1079,8 @@ public:
*/ */
ha_rows quick_condition_rows; ha_rows quick_condition_rows;
double cond_selectivity;
table_map map; /* ID bit of table (1,2,4,8,16...) */ table_map map; /* ID bit of table (1,2,4,8,16...) */
uint lock_position; /* Position in MYSQL_LOCK.table */ uint lock_position; /* Position in MYSQL_LOCK.table */
......
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