[Commits] Rev 3336: The pilot implementation of mwl#250: Use the statistics from persistent in file:///home/igor/maria/maria-5.5-mwl248/

Igor Babaev igor at askmonty.org
Thu Apr 12 03:14:08 EEST 2012


At file:///home/igor/maria/maria-5.5-mwl248/

------------------------------------------------------------
revno: 3336
revision-id: igor at askmonty.org-20120412001406-ykeclwhdw3as70mo
parent: igor at askmonty.org-20120319083532-198bigqasfoi49mv
committer: Igor Babaev <igor at askmonty.org>
branch nick: maria-5.5-mwl248
timestamp: Wed 2012-04-11 17:14:06 -0700
message:
  The pilot implementation of mwl#250: Use the statistics from persistent
  statistical tables instead of the statistics provided by engine.
-------------- next part --------------
=== added file 'mysql-test/r/stat_tables.result'
--- a/mysql-test/r/stat_tables.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/stat_tables.result	2012-04-12 00:14:06 +0000
@@ -0,0 +1,229 @@
+set @save_optimizer_use_stat_tables=@@optimizer_use_stat_tables;
+set optimizer_use_stat_tables='preferably';
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+select * from mysql.table_stat;
+db_name	table_name	cardinality
+dbt3_s001	customer	150
+dbt3_s001	lineitem	6005
+dbt3_s001	nation	25
+dbt3_s001	orders	1500
+dbt3_s001	part	200
+dbt3_s001	partsupp	700
+dbt3_s001	region	5
+dbt3_s001	supplier	10
+select * from mysql.index_stat;
+db_name	table_name	index_name	prefix_arity	avg_frequency
+dbt3_s001	customer	PRIMARY	1	1
+dbt3_s001	customer	i_c_nationkey	1	6
+dbt3_s001	lineitem	PRIMARY	1	4.003333333333333
+dbt3_s001	lineitem	PRIMARY	2	1
+dbt3_s001	lineitem	i_l_shipdate	1	2.650044130626655
+dbt3_s001	lineitem	i_l_suppkey_partkey	1	30.025
+dbt3_s001	lineitem	i_l_suppkey_partkey	2	8.57857142857143
+dbt3_s001	lineitem	i_l_partkey	1	30.025
+dbt3_s001	lineitem	i_l_suppkey	1	600.5
+dbt3_s001	lineitem	i_l_receiptdate	1	2.6477072310405645
+dbt3_s001	lineitem	i_l_orderkey	1	4.003333333333333
+dbt3_s001	lineitem	i_l_orderkey_quantity	1	4.003333333333333
+dbt3_s001	lineitem	i_l_orderkey_quantity	2	1.0403672903672905
+dbt3_s001	lineitem	i_l_commitdate	1	2.7159656264133876
+dbt3_s001	nation	PRIMARY	1	1
+dbt3_s001	nation	i_n_regionkey	1	5
+dbt3_s001	orders	PRIMARY	1	1
+dbt3_s001	orders	i_o_orderdate	1	1.3321492007104796
+dbt3_s001	orders	i_o_custkey	1	15
+dbt3_s001	part	PRIMARY	1	1
+dbt3_s001	part	i_p_retailprice	1	1
+dbt3_s001	partsupp	PRIMARY	1	3.5
+dbt3_s001	partsupp	PRIMARY	2	1
+dbt3_s001	partsupp	i_ps_partkey	1	3.5
+dbt3_s001	partsupp	i_ps_suppkey	1	70
+dbt3_s001	region	PRIMARY	1	1
+dbt3_s001	supplier	PRIMARY	1	1
+dbt3_s001	supplier	i_s_nationkey	1	1.1111111111111112
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='index_condition_pushdown=off';
+EXPLAIN select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue
+from customer, orders, lineitem, supplier, nation, region
+where c_custkey = o_custkey and l_orderkey = o_orderkey
+and l_suppkey = s_suppkey and c_nationkey = s_nationkey
+and s_nationkey = n_nationkey and n_regionkey = r_regionkey
+and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01'
+      and o_orderdate < date '1995-01-01' + interval '1' year
+group by n_name
+order by revenue desc;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	orders	range	PRIMARY,i_o_orderdate,i_o_custkey	i_o_orderdate	4	NULL	179	Using where; Using temporary; Using filesort
+1	SIMPLE	customer	eq_ref	PRIMARY,i_c_nationkey	PRIMARY	4	dbt3_s001.orders.o_custkey	1	Using where
+1	SIMPLE	nation	eq_ref	PRIMARY,i_n_regionkey	PRIMARY	4	dbt3_s001.customer.c_nationkey	1	
+1	SIMPLE	region	ALL	PRIMARY	NULL	NULL	NULL	5	Using where; Using join buffer (flat, BNL join)
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity	PRIMARY	4	dbt3_s001.orders.o_orderkey	4	Using where
+1	SIMPLE	supplier	eq_ref	PRIMARY,i_s_nationkey	PRIMARY	4	dbt3_s001.lineitem.l_suppkey	1	Using where
+select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue
+from customer, orders, lineitem, supplier, nation, region
+where c_custkey = o_custkey and l_orderkey = o_orderkey
+and l_suppkey = s_suppkey and c_nationkey = s_nationkey
+and s_nationkey = n_nationkey and n_regionkey = r_regionkey
+and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01'
+      and o_orderdate < date '1995-01-01' + interval '1' year
+group by n_name
+order by revenue desc;
+n_name	revenue
+PERU	321915.8715
+ARGENTINA	69817.1451
+set optimizer_switch=@save_optimizer_switch;
+EXPLAIN select o_year,
+sum(case when nation = 'UNITED STATES' then volume else 0 end) /
+sum(volume) as mkt_share
+from (select extract(year from o_orderdate) as o_year,
+l_extendedprice * (1-l_discount) as volume, 
+n2.n_name as nation
+from part, supplier, lineitem, orders, customer, 
+nation n1, nation n2, region
+where p_partkey = l_partkey and s_suppkey = l_suppkey
+and l_orderkey = o_orderkey and o_custkey = c_custkey
+and c_nationkey = n1.n_nationkey and n1.n_regionkey = r_regionkey
+and r_name = 'AMERICA' and s_nationkey = n2.n_nationkey
+and o_orderdate between date '1995-01-01' and date '1996-12-31'
+            and p_type = 'STANDARD BRUSHED STEEL' ) as all_nations
+group by o_year
+order by o_year;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	orders	ALL	PRIMARY,i_o_orderdate,i_o_custkey	NULL	NULL	NULL	1500	Using where; Using temporary; Using filesort
+1	SIMPLE	customer	eq_ref	PRIMARY,i_c_nationkey	PRIMARY	4	dbt3_s001.orders.o_custkey	1	Using where
+1	SIMPLE	n1	eq_ref	PRIMARY,i_n_regionkey	PRIMARY	4	dbt3_s001.customer.c_nationkey	1	
+1	SIMPLE	region	ALL	PRIMARY	NULL	NULL	NULL	5	Using where; Using join buffer (flat, BNL join)
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity	PRIMARY	4	dbt3_s001.orders.o_orderkey	4	Using where
+1	SIMPLE	part	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.lineitem.l_partkey	1	Using where
+1	SIMPLE	supplier	eq_ref	PRIMARY,i_s_nationkey	PRIMARY	4	dbt3_s001.lineitem.l_suppkey	1	Using where
+1	SIMPLE	n2	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.supplier.s_nationkey	1	
+select o_year,
+sum(case when nation = 'UNITED STATES' then volume else 0 end) /
+sum(volume) as mkt_share
+from (select extract(year from o_orderdate) as o_year,
+l_extendedprice * (1-l_discount) as volume, 
+n2.n_name as nation
+from part, supplier, lineitem, orders, customer, 
+nation n1, nation n2, region
+where p_partkey = l_partkey and s_suppkey = l_suppkey
+and l_orderkey = o_orderkey and o_custkey = c_custkey
+and c_nationkey = n1.n_nationkey and n1.n_regionkey = r_regionkey
+and r_name = 'AMERICA' and s_nationkey = n2.n_nationkey
+and o_orderdate between date '1995-01-01' and date '1996-12-31'
+            and p_type = 'STANDARD BRUSHED STEEL' ) as all_nations
+group by o_year
+order by o_year;
+o_year	mkt_share
+1995	0.4495521838895718
+1996	0.024585468215352495
+EXPLAIN select nation, o_year, sum(amount) as sum_profit
+from (select n_name as nation, 
+extract(year from o_orderdate) as o_year,
+l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount
+from part, supplier, lineitem, partsupp, orders, nation
+where s_suppkey = l_suppkey and ps_suppkey = l_suppkey
+and ps_partkey = l_partkey and p_partkey = l_partkey
+and o_orderkey = l_orderkey and s_nationkey = n_nationkey
+and p_name like '%green%') as profit
+group by nation, o_year
+order by nation, o_year desc;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	supplier	ALL	PRIMARY,i_s_nationkey	NULL	NULL	NULL	10	Using where; Using temporary; Using filesort
+1	SIMPLE	nation	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.supplier.s_nationkey	1	
+1	SIMPLE	partsupp	ref	PRIMARY,i_ps_partkey,i_ps_suppkey	i_ps_suppkey	4	dbt3_s001.supplier.s_suppkey	70	
+1	SIMPLE	part	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.partsupp.ps_partkey	1	Using where
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity	i_l_suppkey_partkey	10	dbt3_s001.partsupp.ps_partkey,dbt3_s001.supplier.s_suppkey	8	
+1	SIMPLE	orders	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.lineitem.l_orderkey	1	
+select nation, o_year, sum(amount) as sum_profit
+from (select n_name as nation, 
+extract(year from o_orderdate) as o_year,
+l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount
+from part, supplier, lineitem, partsupp, orders, nation
+where s_suppkey = l_suppkey and ps_suppkey = l_suppkey
+and ps_partkey = l_partkey and p_partkey = l_partkey
+and o_orderkey = l_orderkey and s_nationkey = n_nationkey
+and p_name like '%green%') as profit
+group by nation, o_year
+order by nation, o_year desc;
+nation	o_year	sum_profit
+ARGENTINA	1997	18247.873399999993
+ARGENTINA	1996	7731.089399999995
+ARGENTINA	1995	134490.5697
+ARGENTINA	1994	36767.101500000004
+ARGENTINA	1993	35857.08
+ARGENTINA	1992	35740
+ETHIOPIA	1998	2758.7801999999992
+ETHIOPIA	1997	19419.294599999997
+ETHIOPIA	1995	51231.87439999999
+ETHIOPIA	1994	3578.9478999999974
+ETHIOPIA	1992	1525.8234999999986
+IRAN	1998	37817.229600000006
+IRAN	1997	52643.77359999999
+IRAN	1996	70143.7761
+IRAN	1995	84094.58260000001
+IRAN	1994	18140.925599999995
+IRAN	1993	78655.1676
+IRAN	1992	87142.23960000002
+IRAQ	1998	22860.8082
+IRAQ	1997	93676.24359999999
+IRAQ	1996	45103.3242
+IRAQ	1994	36010.728599999995
+IRAQ	1993	33221.9399
+IRAQ	1992	47755.05900000001
+KENYA	1998	44194.831999999995
+KENYA	1997	57578.36259999999
+KENYA	1996	59195.90210000001
+KENYA	1995	79262.6278
+KENYA	1994	102360.66609999999
+KENYA	1993	128422.0196
+KENYA	1992	181517.2089
+MOROCCO	1998	41797.823199999984
+MOROCCO	1997	23685.801799999994
+MOROCCO	1996	62115.19579999998
+MOROCCO	1995	42442.64300000001
+MOROCCO	1994	48655.878000000004
+MOROCCO	1993	22926.744400000003
+MOROCCO	1992	32239.8088
+PERU	1998	86999.36459999997
+PERU	1997	121110.41070000001
+PERU	1996	177040.40759999995
+PERU	1995	122247.94520000002
+PERU	1994	88046.25329999998
+PERU	1993	49379.813799999996
+PERU	1992	80646.86050000001
+UNITED KINGDOM	1998	50577.25560000001
+UNITED KINGDOM	1997	114288.8605
+UNITED KINGDOM	1996	147684.46480000002
+UNITED KINGDOM	1995	225267.65759999998
+UNITED KINGDOM	1994	140595.5864
+UNITED KINGDOM	1993	322548.49210000003
+UNITED KINGDOM	1992	67747.88279999999
+UNITED STATES	1998	3957.0431999999996
+UNITED STATES	1997	94729.5704
+UNITED STATES	1996	79297.85670000002
+UNITED STATES	1995	62201.23360000001
+UNITED STATES	1994	43075.629899999985
+UNITED STATES	1993	27168.486199999996
+UNITED STATES	1992	34092.366
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='extended_keys=on';
+EXPLAIN select o_orderkey, p_partkey
+from part, lineitem, orders
+where p_retailprice > 1100 and o_orderdate='1997-01-01' 
+and o_orderkey=l_orderkey and p_partkey=l_partkey;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	orders	ref	PRIMARY,i_o_orderdate	i_o_orderdate	4	const	1	
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_orderkey,i_l_orderkey_quantity	PRIMARY	4	dbt3_s001.orders.o_orderkey	4	Using where
+1	SIMPLE	part	eq_ref	PRIMARY,i_p_retailprice	PRIMARY	4	dbt3_s001.lineitem.l_partkey	1	Using where
+select o_orderkey, p_partkey
+from part, lineitem, orders
+where p_retailprice > 1100 and o_orderdate='1997-01-01' 
+and o_orderkey=l_orderkey and p_partkey=l_partkey;
+o_orderkey	p_partkey
+5895	200
+set optimizer_switch=@save_optimizer_switch;
+DROP DATABASE dbt3_s001;
+use test;
+set optimizer_use_stat_tables=@save_optimizer_use_stat_tables;

=== added file 'mysql-test/r/stat_tables_innodb.result'
--- a/mysql-test/r/stat_tables_innodb.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/stat_tables_innodb.result	2012-04-12 00:14:06 +0000
@@ -0,0 +1,231 @@
+SET SESSION STORAGE_ENGINE='InnoDB';
+set @save_optimizer_use_stat_tables=@@optimizer_use_stat_tables;
+set optimizer_use_stat_tables='preferably';
+DROP DATABASE IF EXISTS dbt3_s001;
+CREATE DATABASE dbt3_s001;
+use dbt3_s001;
+select * from mysql.table_stat;
+db_name	table_name	cardinality
+dbt3_s001	customer	150
+dbt3_s001	lineitem	6005
+dbt3_s001	nation	25
+dbt3_s001	orders	1500
+dbt3_s001	part	200
+dbt3_s001	partsupp	700
+dbt3_s001	region	5
+dbt3_s001	supplier	10
+select * from mysql.index_stat;
+db_name	table_name	index_name	prefix_arity	avg_frequency
+dbt3_s001	customer	PRIMARY	1	1
+dbt3_s001	customer	i_c_nationkey	1	6
+dbt3_s001	lineitem	PRIMARY	1	4.003333333333333
+dbt3_s001	lineitem	PRIMARY	2	1
+dbt3_s001	lineitem	i_l_shipdate	1	2.650044130626655
+dbt3_s001	lineitem	i_l_suppkey_partkey	1	30.025
+dbt3_s001	lineitem	i_l_suppkey_partkey	2	8.57857142857143
+dbt3_s001	lineitem	i_l_partkey	1	30.025
+dbt3_s001	lineitem	i_l_suppkey	1	600.5
+dbt3_s001	lineitem	i_l_receiptdate	1	2.6477072310405645
+dbt3_s001	lineitem	i_l_orderkey	1	4.003333333333333
+dbt3_s001	lineitem	i_l_orderkey_quantity	1	4.003333333333333
+dbt3_s001	lineitem	i_l_orderkey_quantity	2	1.0403672903672905
+dbt3_s001	lineitem	i_l_commitdate	1	2.7159656264133876
+dbt3_s001	nation	PRIMARY	1	1
+dbt3_s001	nation	i_n_regionkey	1	5
+dbt3_s001	orders	PRIMARY	1	1
+dbt3_s001	orders	i_o_orderdate	1	1.3321492007104796
+dbt3_s001	orders	i_o_custkey	1	15
+dbt3_s001	part	PRIMARY	1	1
+dbt3_s001	part	i_p_retailprice	1	1
+dbt3_s001	partsupp	PRIMARY	1	3.5
+dbt3_s001	partsupp	PRIMARY	2	1
+dbt3_s001	partsupp	i_ps_partkey	1	3.5
+dbt3_s001	partsupp	i_ps_suppkey	1	70
+dbt3_s001	region	PRIMARY	1	1
+dbt3_s001	supplier	PRIMARY	1	1
+dbt3_s001	supplier	i_s_nationkey	1	1.1111111111111112
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='index_condition_pushdown=off';
+EXPLAIN select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue
+from customer, orders, lineitem, supplier, nation, region
+where c_custkey = o_custkey and l_orderkey = o_orderkey
+and l_suppkey = s_suppkey and c_nationkey = s_nationkey
+and s_nationkey = n_nationkey and n_regionkey = r_regionkey
+and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01'
+      and o_orderdate < date '1995-01-01' + interval '1' year
+group by n_name
+order by revenue desc;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	orders	range	PRIMARY,i_o_orderdate,i_o_custkey	i_o_orderdate	4	NULL	211	Using where; Using temporary; Using filesort
+1	SIMPLE	customer	eq_ref	PRIMARY,i_c_nationkey	PRIMARY	4	dbt3_s001.orders.o_custkey	1	Using where
+1	SIMPLE	nation	eq_ref	PRIMARY,i_n_regionkey	PRIMARY	4	dbt3_s001.customer.c_nationkey	1	
+1	SIMPLE	supplier	ref	PRIMARY,i_s_nationkey	i_s_nationkey	5	dbt3_s001.customer.c_nationkey	1	Using index
+1	SIMPLE	region	ALL	PRIMARY	NULL	NULL	NULL	5	Using where; Using join buffer (flat, BNL join)
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity	PRIMARY	4	dbt3_s001.orders.o_orderkey	4	Using where
+select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue
+from customer, orders, lineitem, supplier, nation, region
+where c_custkey = o_custkey and l_orderkey = o_orderkey
+and l_suppkey = s_suppkey and c_nationkey = s_nationkey
+and s_nationkey = n_nationkey and n_regionkey = r_regionkey
+and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01'
+      and o_orderdate < date '1995-01-01' + interval '1' year
+group by n_name
+order by revenue desc;
+n_name	revenue
+PERU	321915.8715
+ARGENTINA	69817.1451
+set optimizer_switch=@save_optimizer_switch;
+EXPLAIN select o_year,
+sum(case when nation = 'UNITED STATES' then volume else 0 end) /
+sum(volume) as mkt_share
+from (select extract(year from o_orderdate) as o_year,
+l_extendedprice * (1-l_discount) as volume, 
+n2.n_name as nation
+from part, supplier, lineitem, orders, customer, 
+nation n1, nation n2, region
+where p_partkey = l_partkey and s_suppkey = l_suppkey
+and l_orderkey = o_orderkey and o_custkey = c_custkey
+and c_nationkey = n1.n_nationkey and n1.n_regionkey = r_regionkey
+and r_name = 'AMERICA' and s_nationkey = n2.n_nationkey
+and o_orderdate between date '1995-01-01' and date '1996-12-31'
+            and p_type = 'STANDARD BRUSHED STEEL' ) as all_nations
+group by o_year
+order by o_year;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	orders	ALL	PRIMARY,i_o_orderdate,i_o_custkey	NULL	NULL	NULL	1500	Using where; Using temporary; Using filesort
+1	SIMPLE	customer	eq_ref	PRIMARY,i_c_nationkey	PRIMARY	4	dbt3_s001.orders.o_custkey	1	Using where
+1	SIMPLE	n1	eq_ref	PRIMARY,i_n_regionkey	PRIMARY	4	dbt3_s001.customer.c_nationkey	1	
+1	SIMPLE	region	ALL	PRIMARY	NULL	NULL	NULL	5	Using where; Using join buffer (flat, BNL join)
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity	PRIMARY	4	dbt3_s001.orders.o_orderkey	4	Using where
+1	SIMPLE	part	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.lineitem.l_partkey	1	Using where
+1	SIMPLE	supplier	eq_ref	PRIMARY,i_s_nationkey	PRIMARY	4	dbt3_s001.lineitem.l_suppkey	1	Using where
+1	SIMPLE	n2	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.supplier.s_nationkey	1	
+select o_year,
+sum(case when nation = 'UNITED STATES' then volume else 0 end) /
+sum(volume) as mkt_share
+from (select extract(year from o_orderdate) as o_year,
+l_extendedprice * (1-l_discount) as volume, 
+n2.n_name as nation
+from part, supplier, lineitem, orders, customer, 
+nation n1, nation n2, region
+where p_partkey = l_partkey and s_suppkey = l_suppkey
+and l_orderkey = o_orderkey and o_custkey = c_custkey
+and c_nationkey = n1.n_nationkey and n1.n_regionkey = r_regionkey
+and r_name = 'AMERICA' and s_nationkey = n2.n_nationkey
+and o_orderdate between date '1995-01-01' and date '1996-12-31'
+            and p_type = 'STANDARD BRUSHED STEEL' ) as all_nations
+group by o_year
+order by o_year;
+o_year	mkt_share
+1995	0.4495521838895718
+1996	0.024585468215352495
+EXPLAIN select nation, o_year, sum(amount) as sum_profit
+from (select n_name as nation, 
+extract(year from o_orderdate) as o_year,
+l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount
+from part, supplier, lineitem, partsupp, orders, nation
+where s_suppkey = l_suppkey and ps_suppkey = l_suppkey
+and ps_partkey = l_partkey and p_partkey = l_partkey
+and o_orderkey = l_orderkey and s_nationkey = n_nationkey
+and p_name like '%green%') as profit
+group by nation, o_year
+order by nation, o_year desc;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	supplier	index	PRIMARY,i_s_nationkey	i_s_nationkey	5	NULL	10	Using where; Using index; Using temporary; Using filesort
+1	SIMPLE	nation	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.supplier.s_nationkey	1	
+1	SIMPLE	partsupp	ref	PRIMARY,i_ps_partkey,i_ps_suppkey	i_ps_suppkey	4	dbt3_s001.supplier.s_suppkey	70	
+1	SIMPLE	part	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.partsupp.ps_partkey	1	Using where
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_suppkey,i_l_orderkey,i_l_orderkey_quantity	i_l_suppkey_partkey	10	dbt3_s001.partsupp.ps_partkey,dbt3_s001.supplier.s_suppkey	8	
+1	SIMPLE	orders	eq_ref	PRIMARY	PRIMARY	4	dbt3_s001.lineitem.l_orderkey	1	
+select nation, o_year, sum(amount) as sum_profit
+from (select n_name as nation, 
+extract(year from o_orderdate) as o_year,
+l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount
+from part, supplier, lineitem, partsupp, orders, nation
+where s_suppkey = l_suppkey and ps_suppkey = l_suppkey
+and ps_partkey = l_partkey and p_partkey = l_partkey
+and o_orderkey = l_orderkey and s_nationkey = n_nationkey
+and p_name like '%green%') as profit
+group by nation, o_year
+order by nation, o_year desc;
+nation	o_year	sum_profit
+ARGENTINA	1997	18247.873399999993
+ARGENTINA	1996	7731.089399999995
+ARGENTINA	1995	134490.5697
+ARGENTINA	1994	36767.101500000004
+ARGENTINA	1993	35857.08
+ARGENTINA	1992	35740
+ETHIOPIA	1998	2758.7801999999992
+ETHIOPIA	1997	19419.294599999997
+ETHIOPIA	1995	51231.87439999999
+ETHIOPIA	1994	3578.9478999999974
+ETHIOPIA	1992	1525.8234999999986
+IRAN	1998	37817.229600000006
+IRAN	1997	52643.77359999999
+IRAN	1996	70143.7761
+IRAN	1995	84094.58260000001
+IRAN	1994	18140.925599999995
+IRAN	1993	78655.1676
+IRAN	1992	87142.23960000002
+IRAQ	1998	22860.8082
+IRAQ	1997	93676.24359999999
+IRAQ	1996	45103.3242
+IRAQ	1994	36010.728599999995
+IRAQ	1993	33221.9399
+IRAQ	1992	47755.05900000001
+KENYA	1998	44194.831999999995
+KENYA	1997	57578.36259999999
+KENYA	1996	59195.90210000001
+KENYA	1995	79262.6278
+KENYA	1994	102360.66609999999
+KENYA	1993	128422.0196
+KENYA	1992	181517.2089
+MOROCCO	1998	41797.823199999984
+MOROCCO	1997	23685.801799999994
+MOROCCO	1996	62115.19579999998
+MOROCCO	1995	42442.64300000001
+MOROCCO	1994	48655.878000000004
+MOROCCO	1993	22926.744400000003
+MOROCCO	1992	32239.8088
+PERU	1998	86999.36459999997
+PERU	1997	121110.41070000001
+PERU	1996	177040.40759999995
+PERU	1995	122247.94520000002
+PERU	1994	88046.25329999998
+PERU	1993	49379.813799999996
+PERU	1992	80646.86050000001
+UNITED KINGDOM	1998	50577.25560000001
+UNITED KINGDOM	1997	114288.8605
+UNITED KINGDOM	1996	147684.46480000002
+UNITED KINGDOM	1995	225267.65759999998
+UNITED KINGDOM	1994	140595.5864
+UNITED KINGDOM	1993	322548.49210000003
+UNITED KINGDOM	1992	67747.88279999999
+UNITED STATES	1998	3957.0431999999996
+UNITED STATES	1997	94729.5704
+UNITED STATES	1996	79297.85670000002
+UNITED STATES	1995	62201.23360000001
+UNITED STATES	1994	43075.629899999985
+UNITED STATES	1993	27168.486199999996
+UNITED STATES	1992	34092.366
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='extended_keys=on';
+EXPLAIN select o_orderkey, p_partkey
+from part, lineitem, orders
+where p_retailprice > 1100 and o_orderdate='1997-01-01' 
+and o_orderkey=l_orderkey and p_partkey=l_partkey;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	part	range	PRIMARY,i_p_retailprice	i_p_retailprice	9	NULL	1	Using where; Using index
+1	SIMPLE	orders	ref	PRIMARY,i_o_orderdate	i_o_orderdate	4	const	1	Using index
+1	SIMPLE	lineitem	ref	PRIMARY,i_l_suppkey_partkey,i_l_partkey,i_l_orderkey,i_l_orderkey_quantity	i_l_partkey	9	dbt3_s001.part.p_partkey,dbt3_s001.orders.o_orderkey	1	Using index
+select o_orderkey, p_partkey
+from part, lineitem, orders
+where p_retailprice > 1100 and o_orderdate='1997-01-01' 
+and o_orderkey=l_orderkey and p_partkey=l_partkey;
+o_orderkey	p_partkey
+5895	200
+set optimizer_switch=@save_optimizer_switch;
+DROP DATABASE dbt3_s001;
+use test;
+set optimizer_use_stat_tables=@save_optimizer_use_stat_tables;
+SET SESSION STORAGE_ENGINE=DEFAULT;

=== added file 'mysql-test/t/stat_tables.test'
--- a/mysql-test/t/stat_tables.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/stat_tables.test	2012-04-12 00:14:06 +0000
@@ -0,0 +1,108 @@
+
+set @save_optimizer_use_stat_tables=@@optimizer_use_stat_tables;
+
+set optimizer_use_stat_tables='preferably';
+
+--disable_warnings
+DROP DATABASE IF EXISTS dbt3_s001;
+--enable_warnings
+
+CREATE DATABASE dbt3_s001;
+
+use dbt3_s001;
+ 
+--disable_query_log
+--disable_result_log
+--disable_warnings
+--source include/dbt3_s001.inc
+create index i_p_retailprice on part(p_retailprice);
+ANALYZE TABLE
+customer, lineitem, nation, orders, part, partsupp, region, supplier;
+FLUSH TABLES customer, lineitem, nation, orders, part, partsupp, region, supplier;
+--enable_warnings
+--enable_result_log
+--enable_query_log
+
+select * from mysql.table_stat;
+select * from mysql.index_stat;
+
+
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='index_condition_pushdown=off';
+
+let $Q5=
+select n_name, sum(l_extendedprice * (1 - l_discount)) as revenue
+from customer, orders, lineitem, supplier, nation, region
+where c_custkey = o_custkey and l_orderkey = o_orderkey
+      and l_suppkey = s_suppkey and c_nationkey = s_nationkey
+      and s_nationkey = n_nationkey and n_regionkey = r_regionkey
+      and r_name = 'AMERICA' and o_orderdate >= date '1995-01-01'
+      and o_orderdate < date '1995-01-01' + interval '1' year
+group by n_name
+order by revenue desc;
+
+eval EXPLAIN $Q5;
+eval $Q5;
+
+set optimizer_switch=@save_optimizer_switch;
+
+
+let $Q8=
+select o_year,
+       sum(case when nation = 'UNITED STATES' then volume else 0 end) /
+       sum(volume) as mkt_share
+from (select extract(year from o_orderdate) as o_year,
+             l_extendedprice * (1-l_discount) as volume, 
+             n2.n_name as nation
+      from part, supplier, lineitem, orders, customer, 
+           nation n1, nation n2, region
+      where p_partkey = l_partkey and s_suppkey = l_suppkey
+            and l_orderkey = o_orderkey and o_custkey = c_custkey
+            and c_nationkey = n1.n_nationkey and n1.n_regionkey = r_regionkey
+            and r_name = 'AMERICA' and s_nationkey = n2.n_nationkey
+            and o_orderdate between date '1995-01-01' and date '1996-12-31'
+            and p_type = 'STANDARD BRUSHED STEEL' ) as all_nations
+group by o_year
+order by o_year;
+
+eval EXPLAIN $Q8;
+eval $Q8;
+
+
+let $Q9=
+select nation, o_year, sum(amount) as sum_profit
+from (select n_name as nation, 
+      extract(year from o_orderdate) as o_year,
+      l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount
+      from part, supplier, lineitem, partsupp, orders, nation
+      where s_suppkey = l_suppkey and ps_suppkey = l_suppkey
+            and ps_partkey = l_partkey and p_partkey = l_partkey
+            and o_orderkey = l_orderkey and s_nationkey = n_nationkey
+            and p_name like '%green%') as profit
+group by nation, o_year
+order by nation, o_year desc;
+
+eval EXPLAIN $Q9;
+eval $Q9;
+
+
+set @save_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='extended_keys=on';
+
+let $QQ1=
+select o_orderkey, p_partkey
+  from part, lineitem, orders
+  where p_retailprice > 1100 and o_orderdate='1997-01-01' 
+        and o_orderkey=l_orderkey and p_partkey=l_partkey;
+
+eval EXPLAIN $QQ1;
+eval $QQ1;
+
+set optimizer_switch=@save_optimizer_switch;
+
+
+DROP DATABASE dbt3_s001;
+
+use test;
+
+set optimizer_use_stat_tables=@save_optimizer_use_stat_tables;

=== added file 'mysql-test/t/stat_tables_innodb.test'
--- a/mysql-test/t/stat_tables_innodb.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/stat_tables_innodb.test	2012-04-12 00:14:06 +0000
@@ -0,0 +1,7 @@
+--source include/have_innodb.inc
+
+SET SESSION STORAGE_ENGINE='InnoDB';
+
+--source stat_tables.test
+
+SET SESSION STORAGE_ENGINE=DEFAULT;

=== modified file 'sql/multi_range_read.cc'
--- a/sql/multi_range_read.cc	2012-02-24 13:37:00 +0000
+++ b/sql/multi_range_read.cc	2012-04-12 00:14:06 +0000
@@ -1201,7 +1201,7 @@
   uint parts= my_count_bits(key_tuple_map);
   ulong rpc;
   ulonglong rowids_size= rowid_buf_elem_size;
-  if ((rpc= key_info->rec_per_key[parts - 1]))
+  if ((rpc= key_info->real_rec_per_key(parts - 1)))
     rowids_size= rowid_buf_elem_size * rpc;
 
   double fraction_for_rowids=

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2012-03-19 08:35:32 +0000
+++ b/sql/mysqld.cc	2012-04-12 00:14:06 +0000
@@ -4869,11 +4869,6 @@
     check_performance_schema();
 #endif
 
-#if 0
-  if (! opt_bootstrap)
-    init_stat_tables_usage();
-#endif
-
   initialize_information_schema_acl();
 
   execute_ddl_log_recovery();

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2012-03-02 23:03:20 +0000
+++ b/sql/opt_range.cc	2012-04-12 00:14:06 +0000
@@ -2875,7 +2875,7 @@
   DBUG_PRINT("enter",("keys_to_use: %lu  prev_tables: %lu  const_tables: %lu",
 		      (ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
 		      (ulong) const_tables));
-  DBUG_PRINT("info", ("records: %lu", (ulong) head->file->stats.records));
+  DBUG_PRINT("info", ("records: %lu", (ulong) head->stat_records()));
   delete quick;
   quick=0;
   needed_reg.clear_all();
@@ -2883,7 +2883,7 @@
   DBUG_ASSERT(!head->is_filled_at_execution());
   if (keys_to_use.is_clear_all() || head->is_filled_at_execution())
     DBUG_RETURN(0);
-  records= head->file->stats.records;
+  records= head->stat_records();
   if (!records)
     records++;					/* purecov: inspected */
   scan_time= (double) records / TIME_FOR_COMPARE + 1;
@@ -3020,7 +3020,7 @@
     if (group_trp)
     {
       param.table->quick_condition_rows= min(group_trp->records,
-                                             head->file->stats.records);
+                                             head->stat_records());
       if (group_trp->read_cost < best_read_time)
       {
         best_trp= group_trp;
@@ -4618,7 +4618,7 @@
   DBUG_PRINT("info", ("index_merge scans cost %g", imerge_cost));
   if (imerge_too_expensive || (imerge_cost > read_time) ||
       ((non_cpk_scan_records+cpk_scan_records >=
-        param->table->file->stats.records) &&
+        param->table->stat_records()) &&
        read_time != DBL_MAX))
   {
     /*
@@ -4689,7 +4689,7 @@
       imerge_trp->read_cost= imerge_cost;
       imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
       imerge_trp->records= min(imerge_trp->records,
-                               param->table->file->stats.records);
+                               param->table->stat_records());
       imerge_trp->range_scans= range_scans;
       imerge_trp->range_scans_end= range_scans + n_child_scans;
       read_time= imerge_cost;
@@ -4760,7 +4760,7 @@
         ((TRP_ROR_INTERSECT*)(*cur_roru_plan))->index_scan_costs;
     roru_total_records += (*cur_roru_plan)->records;
     roru_intersect_part *= (*cur_roru_plan)->records /
-                           param->table->file->stats.records;
+                           param->table->stat_records();
   }
 
   /*
@@ -4770,7 +4770,7 @@
     in disjunction do not share key parts.
   */
   roru_total_records -= (ha_rows)(roru_intersect_part*
-                                  param->table->file->stats.records);
+                                  param->table->stat_records());
   /* ok, got a ROR read plan for each of the disjuncts
     Calculate cost:
     cost(index_union_scan(scan_1, ... scan_n)) =
@@ -5047,12 +5047,12 @@
 ha_rows get_table_cardinality_for_index_intersect(TABLE *table)
 {
   if (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT)
-    return table->file->stats.records;
+    return table->stat_records();
   else
   {
     ha_rows d;
     double q;
-    for (q= (double)table->file->stats.records, d= 1 ; q >= 10; q/= 10, d*= 10 ) ;
+    for (q= (double)table->stat_records(), d= 1 ; q >= 10; q/= 10, d*= 10 ) ;
     return (ha_rows) (floor(q+0.5) * d);
   } 
 }
@@ -5455,9 +5455,8 @@
     ha_rows ext_records= ext_index_scan->records;
     if (i < used_key_parts)
     {
-      ulong *rec_per_key= key_info->rec_per_key+i-1;
-      ulong f1= rec_per_key[0] ? rec_per_key[0] : 1;
-      ulong f2= rec_per_key[1] ? rec_per_key[1] : 1;
+      ulong f1= key_info->real_rec_per_key(i-1);
+      ulong f2= key_info->real_rec_per_key(i);
       ext_records= (ha_rows) ((double) ext_records / f2 * f1);
     }
     if (ext_records < table_cardinality)
@@ -5949,7 +5948,7 @@
   info->is_covering= FALSE;
   info->index_scan_costs= 0.0;
   info->index_records= 0;
-  info->out_rows= (double) param->table->file->stats.records;
+  info->out_rows= (double) param->table->stat_records();
   bitmap_clear_all(&info->covered_fields);
   return info;
 }
@@ -6075,7 +6074,7 @@
   min_range.flag= HA_READ_KEY_EXACT;
   max_range.key= key_val;
   max_range.flag= HA_READ_AFTER_KEY;
-  ha_rows prev_records= info->param->table->file->stats.records;
+  ha_rows prev_records= info->param->table->stat_records();
   DBUG_ENTER("ror_scan_selectivity");
 
   for (sel_arg= scan->sel_arg; sel_arg;
@@ -6302,7 +6301,7 @@
   double min_cost= DBL_MAX;
   DBUG_ENTER("get_best_ror_intersect");
 
-  if ((tree->n_ror_scans < 2) || !param->table->file->stats.records ||
+  if ((tree->n_ror_scans < 2) || !param->table->stat_records() ||
       !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT))
     DBUG_RETURN(NULL);
 
@@ -12570,14 +12569,14 @@
   double cpu_cost= 0; /* TODO: CPU cost of index_read calls? */
   DBUG_ENTER("cost_group_min_max");
 
-  table_records= table->file->stats.records;
+  table_records= table->stat_records();
   keys_per_block= (table->file->stats.block_size / 2 /
                    (index_info->key_length + table->file->ref_length)
                         + 1);
   num_blocks= (uint)(table_records / keys_per_block) + 1;
 
   /* Compute the number of keys in a group. */
-  keys_per_group= index_info->rec_per_key[group_key_parts - 1];
+  keys_per_group= index_info->real_rec_per_key(group_key_parts - 1);
   if (keys_per_group == 0) /* If there is no statistics try to guess */
     /* each group contains 10% of all records */
     keys_per_group= (uint)(table_records / 10) + 1;
@@ -12597,7 +12596,7 @@
       Compute the probability that two ends of a subgroup are inside
       different blocks.
     */
-    keys_per_subgroup= index_info->rec_per_key[used_key_parts - 1];
+    keys_per_subgroup= index_info->real_rec_per_key(used_key_parts - 1);
     if (keys_per_subgroup >= keys_per_block) /* If a subgroup is bigger than */
       p_overlap= 1.0;       /* a block, it will overlap at least two blocks. */
     else

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2012-03-19 08:35:32 +0000
+++ b/sql/sql_base.h	2012-04-12 00:14:06 +0000
@@ -315,6 +315,7 @@
 int read_statistics_for_table(THD *thd, TABLE *table);
 int collect_statistics_for_table(THD *thd, TABLE *table);
 int update_statistics_for_table(THD *thd, TABLE *table);
+void set_statistics_for_table(THD *thd, TABLE *table);
 
 extern "C" int simple_raw_key_cmp(void* arg, const void* key1,
                                   const void* key2);

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2012-02-15 17:08:08 +0000
+++ b/sql/sql_delete.cc	2012-04-12 00:14:06 +0000
@@ -200,6 +200,7 @@
 #endif
   /* Update the table->file->stats.records number */
   table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+  set_statistics_for_table(thd, table);
 
   table->covering_keys.clear_all();
   table->quick_keys.clear_all();		// Can't use 'only index'

=== modified file 'sql/sql_join_cache.cc'
--- a/sql/sql_join_cache.cc	2012-02-24 13:37:00 +0000
+++ b/sql/sql_join_cache.cc	2012-04-12 00:14:06 +0000
@@ -3788,7 +3788,7 @@
   uint incr= 0;
   TABLE_REF *ref= &join_tab->ref;
   TABLE *tab= join_tab->table;
-  uint rec_per_key= tab->key_info[ref->key].rec_per_key[ref->key_parts-1];
+  uint rec_per_key= tab->key_info[ref->key].real_rec_per_key(ref->key_parts-1);
   set_if_bigger(rec_per_key, 1);
   if (recno == 1)
     incr=  ref->key_length + tab->file->ref_length;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2012-03-17 08:26:58 +0000
+++ b/sql/sql_select.cc	2012-04-12 00:14:06 +0000
@@ -3121,6 +3121,7 @@
     table_vector[i]=s->table=table=tables->table;
     table->pos_in_table_list= tables;
     error= tables->fetch_number_of_rows();
+    set_statistics_for_table(join->thd, table);
 
     DBUG_EXECUTE_IF("bug11747970_raise_error",
                     {
@@ -3146,8 +3147,8 @@
 
     s->dependent= tables->dep_tables;
     if (tables->schema_table)
-      table->file->stats.records= 2;
-    table->quick_condition_rows= table->file->stats.records;
+      table->file->stats.records= table->used_stat_records= 2;
+    table->quick_condition_rows= table->stat_records();
 
     s->on_expr_ref= &tables->on_expr;
     if (*s->on_expr_ref)
@@ -3155,10 +3156,10 @@
       /* s is the only inner table of an outer join */
 #ifdef WITH_PARTITION_STORAGE_ENGINE
       if (!table->is_filled_at_execution() &&
-           (!table->file->stats.records || table->no_partitions_used) && !embedding)
+	  (!table->stat_records() || table->no_partitions_used) && !embedding)
 #else
       if (!table->is_filled_at_execution() &&
-          !table->file->stats.records && !embedding)
+          !table->stat_records() && !embedding)
 #endif
       {						// Empty table
         s->dependent= 0;                        // Ignore LEFT JOIN depend.
@@ -3205,7 +3206,7 @@
     const bool no_partitions_used= FALSE;
 #endif
     if (!table->is_filled_at_execution() && 
-        (table->s->system || table->file->stats.records <= 1 ||
+        (table->s->system || table->stat_records() <= 1 ||
          no_partitions_used) &&
 	!s->dependent &&
 	(table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
@@ -3387,7 +3388,7 @@
 	// All dep. must be constants
 	if (s->dependent & ~(found_const_table_map))
 	  continue;
-	if (table->file->stats.records <= 1L &&
+	if (table->stat_records() <= 1L &&
 	    (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) &&
             !table->pos_in_table_list->embedding &&
 	      !((outer_join & table->map) && 
@@ -5352,7 +5353,7 @@
             else
             {
               uint key_parts= table->actual_n_key_parts(keyinfo);
-              if (!(records=keyinfo->rec_per_key[key_parts-1]))
+              if (!(records= keyinfo->real_rec_per_key(key_parts-1)))
               {                                   /* Prefer longer keys */
                 records=
                   ((double) s->records / (double) rec *
@@ -5452,7 +5453,7 @@
             else
             {
               /* Check if we have statistic about the distribution */
-              if ((records= keyinfo->rec_per_key[max_key_part-1]))
+              if ((records= keyinfo->real_rec_per_key(max_key_part-1)))
               {
                 /* 
                   Fix for the case where the index statistics is too
@@ -7435,6 +7436,7 @@
   keyinfo->key_length=0;
   keyinfo->algorithm= HA_KEY_ALG_UNDEF;
   keyinfo->flags= HA_GENERATED_KEY;
+  keyinfo->is_statistics_from_stat_tables= FALSE;
   keyinfo->name= (char *) "$hj";
   keyinfo->rec_per_key= (ulong*) thd->calloc(sizeof(ulong)*key_parts);
   if (!keyinfo->rec_per_key)
@@ -10006,7 +10008,7 @@
     }
     else
     {
-      found_records= records= table->file->stats.records;
+      found_records= records= table->stat_records();
       read_time= table->file->scan_time();
       /*
         table->quick_condition_rows has already been set to
@@ -10017,7 +10019,7 @@
   }
   else
   {
-    found_records= records=table->file->stats.records;
+    found_records= records=table->stat_records();
     read_time= found_records ? (double)found_records: 10.0;// TODO:fix this stub
     res= read_time;
   }
@@ -14329,8 +14331,11 @@
     keyinfo->usable_key_parts=keyinfo->key_parts= param->group_parts;
     keyinfo->ext_key_parts= keyinfo->key_parts;
     keyinfo->key_length=0;
-    keyinfo->rec_per_key=0;
+    keyinfo->rec_per_key=NULL;
+    keyinfo->read_stat.avg_frequency= NULL;
+    keyinfo->write_stat.avg_frequency= NULL;
     keyinfo->algorithm= HA_KEY_ALG_UNDEF;
+    keyinfo->is_statistics_from_stat_tables= FALSE;
     keyinfo->name= (char*) "group_key";
     ORDER *cur_group= group;
     for (; cur_group ; cur_group= cur_group->next, key_part_info++)
@@ -14443,6 +14448,7 @@
     keyinfo->key_length= 0;  // Will compute the sum of the parts below.
     keyinfo->name= (char*) "distinct_key";
     keyinfo->algorithm= HA_KEY_ALG_UNDEF;
+    keyinfo->is_statistics_from_stat_tables= FALSE;
     keyinfo->rec_per_key=0;
 
     /*
@@ -18211,7 +18217,7 @@
     uint saved_best_key_parts= 0;
     int best_key_direction= 0;
     JOIN *join= tab->join;
-    ha_rows table_records= table->file->stats.records;
+    ha_rows table_records= table->stat_records();
 
     test_if_cheaper_ordering(tab, order, table, usable_keys,
                              ref_key, select_limit,
@@ -18327,7 +18333,7 @@
         {
           tab->ref.key= -1;
           tab->ref.key_parts= 0;
-          if (select_limit < table->file->stats.records)
+          if (select_limit < table->stat_records())
             tab->limit= select_limit;
         }
       }
@@ -18541,7 +18547,7 @@
   if (!tab->preread_init_done && tab->preread_init())
     goto err;
   if (table->s->tmp_table)
-    table->file->info(HA_STATUS_VARIABLE);	// Get record count
+    table->file->info(HA_STATUS_VARIABLE);     // Get record count
   table->sort.found_records=filesort(thd, table,join->sortorder, length,
                                      select, filesort_limit, 0,
                                      &examined_rows);
@@ -21234,7 +21240,7 @@
                 handler->info(HA_STATUS_VARIABLE) has been called in
                 make_join_statistics()
               */
-              examined_rows= tab->table->file->stats.records;
+              examined_rows= tab->table->stat_records();
             }
           }
         }
@@ -22321,7 +22327,7 @@
   int best_key= -1;
   bool is_best_covering= FALSE;
   double fanout= 1;
-  ha_rows table_records= table->file->stats.records;
+  ha_rows table_records= table->stat_records();
   bool group= join && join->group && order == join->group_list;
   ha_rows ref_key_quick_rows= HA_POS_ERROR;
 
@@ -22411,7 +22417,7 @@
           if (used_key_parts > used_index_parts)
             used_pk_parts= used_key_parts-used_index_parts;
           rec_per_key= used_key_parts ?
-                       keyinfo->rec_per_key[used_key_parts-1] : 1;
+	               keyinfo->real_rec_per_key(used_key_parts-1) : 1;
           /* Take into account the selectivity of the used pk prefix */
           if (used_pk_parts)
 	  {
@@ -22426,8 +22432,8 @@
               rec_per_key= 1;                 
             if (rec_per_key > 1)
 	    {
-              rec_per_key*= pkinfo->rec_per_key[used_pk_parts-1];
-              rec_per_key/= pkinfo->rec_per_key[0];
+              rec_per_key*= pkinfo->real_rec_per_key(used_pk_parts-1);
+              rec_per_key/= pkinfo->real_rec_per_key(0);
               /* 
                 The value of rec_per_key for the extended key has
                 to be adjusted accordingly if some components of
@@ -22441,9 +22447,9 @@
                     We presume here that for any index rec_per_key[i] != 0
                     if rec_per_key[0] != 0.
 	          */
-                  DBUG_ASSERT(pkinfo->rec_per_key[i]);
-                  rec_per_key*= pkinfo->rec_per_key[i-1];
-                  rec_per_key/= pkinfo->rec_per_key[i];
+                  DBUG_ASSERT(pkinfo->real_rec_per_key(i));
+                  rec_per_key*= pkinfo->real_rec_per_key(i-1);
+                  rec_per_key/= pkinfo->real_rec_per_key(i);
                 }
 	      }
             }    
@@ -22488,7 +22494,7 @@
           select_limit= (ha_rows) (select_limit *
                                    (double) table_records /
                                     table->quick_condition_rows);
-        rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1];
+        rec_per_key= keyinfo->real_rec_per_key(keyinfo->key_parts-1);
         set_if_bigger(rec_per_key, 1);
         /*
           Here we take into account the fact that rows are
@@ -22629,7 +22635,7 @@
       Update quick_condition_rows since single table UPDATE/DELETE procedures
       don't call make_join_statistics() and leave this variable uninitialized.
     */
-    table->quick_condition_rows= table->file->stats.records;
+    table->quick_condition_rows= table->stat_records();
     
     int key, direction;
     if (test_if_cheaper_ordering(NULL, order, table,

=== modified file 'sql/sql_statistics.cc'
--- a/sql/sql_statistics.cc	2012-03-19 08:35:32 +0000
+++ b/sql/sql_statistics.cc	2012-04-12 00:14:06 +0000
@@ -1531,7 +1531,7 @@
   now.        
 */
 
-int read_statistics_for_table(THD *thd, struct TABLE *table)
+int read_statistics_for_table(THD *thd, TABLE *table)
 {
   uint i;
   TABLE *stat_table;
@@ -1579,6 +1579,29 @@
       index_stat.set_key_fields(key_info, i+1);
       index_stat.get_stat_values();
     }
+   
+    key_part_map ext_key_part_map= key_info->ext_key_part_map;
+    if (key_info->key_parts != key_info->ext_key_parts)
+    {
+      KEY *pk_key_info= table->key_info + table->s->primary_key;
+      uint k= key_info->key_parts;
+      double k_avg_frequency= key_info->read_stat.avg_frequency[k-1];
+      uint pk_parts= pk_key_info->key_parts;
+      ha_rows n_rows= table->read_stat.cardinality;
+      for (uint j= 0; j < pk_parts; j++)
+      {
+        double avg_frequency;
+        if (!(ext_key_part_map & 1 << j))
+          continue;
+        avg_frequency= pk_key_info->read_stat.avg_frequency[j];
+        if (avg_frequency == 0 ||
+            table->read_stat.cardinality_is_null)
+          avg_frequency= 1;
+        else if (avg_frequency > 1)
+          avg_frequency= max(k_avg_frequency * avg_frequency / n_rows, 1);
+        key_info->read_stat.avg_frequency[k++]= avg_frequency;
+      }
+    }
   }
       
   close_system_tables(thd, &open_tables_backup);
@@ -1586,3 +1609,33 @@
   DBUG_RETURN(0);
 }
 
+
+/**
+  @brief
+  Set statistics for a table that will be used by the optimizer 
+
+  @param
+  thd         The thread handle
+  @param
+  table       The table to set statistics for 
+
+  @details
+  Depending on the value of thd->variables.optimizer_use_stat_tables 
+  the function performs the settings for the table that will control
+  from where the statistical data used by the optimizer will be taken.
+*/
+
+void set_statistics_for_table(THD *thd, TABLE *table)
+{
+  uint use_stat_table_mode= thd->variables.optimizer_use_stat_tables;
+  table->used_stat_records= 
+    (use_stat_table_mode <= 1 || table->read_stat.cardinality_is_null) ?
+    table->file->stats.records : table->read_stat.cardinality;
+  KEY *key_info, *key_info_end;
+  for (key_info= table->key_info, key_info_end= key_info+table->s->keys;
+       key_info < key_info_end; key_info++)
+  {
+    key_info->is_statistics_from_stat_tables=
+      (use_stat_table_mode > 1 && key_info->read_stat.avg_frequency[0] > 0.5);
+  }
+}

=== modified file 'sql/structs.h'
--- a/sql/structs.h	2012-03-19 08:35:32 +0000
+++ b/sql/structs.h	2012-04-12 00:14:06 +0000
@@ -96,6 +96,11 @@
   uint  block_size;
   uint  name_length;
   enum  ha_key_alg algorithm;
+  /* 
+    The flag is on if statistical data for the index prefixes
+    has to be taken from the system statistical tables.
+  */
+  bool is_statistics_from_stat_tables;
   /*
     Note that parser is used when the table is opened for use, and
     parser_name is used when the table is being created.
@@ -148,6 +153,15 @@
   /** reference to the list of options or NULL */
   engine_option_value *option_list;
   ha_index_option_struct *option_struct;                  /* structure with parsed options */
+
+  inline double real_rec_per_key(uint i)
+  { 
+    if (rec_per_key == 0)
+      return 0;
+    return (is_statistics_from_stat_tables ?
+            (ulong) (100 * read_stat.avg_frequency[i]) / (double) 100 :
+            (double) rec_per_key[i]);
+  }
 } KEY;
 
 

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2012-03-19 08:35:32 +0000
+++ b/sql/table.cc	2012-04-12 00:14:06 +0000
@@ -762,8 +762,8 @@
   ulong pos, record_offset; 
   ulong *rec_per_key= NULL;
   ulong rec_buff_length;
-  double *read_avg_frequency= 0;
-  double *write_avg_frequency= 0;
+  double *read_avg_frequency= NULL;
+  double *write_avg_frequency= NULL;
   handler *handler_file= 0;
   KEY	*keyinfo;
   KEY_PART_INFO *key_part= NULL;
@@ -1019,6 +1019,8 @@
         {
           *key_part++= first_key_part[j];
           *rec_per_key++= 0;
+          *read_avg_frequency++= 0;
+          *write_avg_frequency++= 0;
           keyinfo->ext_key_parts++;
           keyinfo->ext_key_part_map|= 1 << j;
         }
@@ -2406,6 +2408,8 @@
   }
 #endif
 
+  outparam->read_stat.cardinality_is_null= TRUE;
+
   if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
                                           (uint) ((share->fields+1)*
                                                   sizeof(Field*)))))
@@ -5924,6 +5928,7 @@
   keyinfo->algorithm= HA_KEY_ALG_UNDEF;
   keyinfo->flags= HA_GENERATED_KEY;
   keyinfo->ext_key_flags= keyinfo->flags;
+  keyinfo->is_statistics_from_stat_tables= FALSE;
   if (unique)
     keyinfo->flags|= HA_NOSAME;
   sprintf(buf, "key%i", key);
@@ -6619,6 +6624,7 @@
   {
     table->file->stats.records= ((select_union*)derived->result)->records;
     set_if_bigger(table->file->stats.records, 2);
+    table->used_stat_records= table->file->stats.records;
   }
   else
     error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);

=== modified file 'sql/table.h'
--- a/sql/table.h	2012-03-19 08:35:32 +0000
+++ b/sql/table.h	2012-04-12 00:14:06 +0000
@@ -1025,6 +1025,9 @@
   */
   Table_statistics write_stat;
 
+  /* The estimate of the number of records in the table used by optimizer */ 
+  ha_rows used_stat_records;
+
   /* 
     For each key that has quick_keys.is_set(key) == TRUE: estimate of #records
     and max #key parts that range access would use.
@@ -1271,6 +1274,7 @@
   bool update_const_key_parts(COND *conds);
   uint actual_n_key_parts(KEY *keyinfo);
   ulong actual_key_flags(KEY *keyinfo);
+  inline ha_rows stat_records() { return used_stat_records; }
 };
 
 



More information about the commits mailing list