Browse Source

Merge mwl253 -> 10.0-base

pull/57/head
Igor Babaev 13 years ago
parent
commit
aa052eeb1a
  1. 25
      mysql-test/r/mysqld--help.result
  2. 1014
      mysql-test/r/selectivity.result
  3. 1024
      mysql-test/r/selectivity_innodb.result
  4. 570
      mysql-test/r/statistics.result
  5. 3
      mysql-test/r/system_mysql_db.result
  6. 7
      mysql-test/suite/funcs_1/r/is_columns_mysql.result
  7. 7
      mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result
  8. 136
      mysql-test/suite/sys_vars/r/histogram_size_basic.result
  9. 79
      mysql-test/suite/sys_vars/r/histogram_type_basic.result
  10. 109
      mysql-test/suite/sys_vars/r/optimizer_use_condition_selectivity_basic.result
  11. 142
      mysql-test/suite/sys_vars/t/histogram_size_basic.test
  12. 92
      mysql-test/suite/sys_vars/t/histogram_type_basic.test
  13. 142
      mysql-test/suite/sys_vars/t/optimizer_use_condition_selectivity_basic.test
  14. 623
      mysql-test/t/selectivity.test
  15. 12
      mysql-test/t/selectivity_innodb.test
  16. 123
      mysql-test/t/statistics.test
  17. 2
      scripts/mysql_system_tables.sql
  18. 136
      sql/field.cc
  19. 37
      sql/field.h
  20. 20
      sql/item_cmpfunc.cc
  21. 4
      sql/item_cmpfunc.h
  22. 322
      sql/opt_range.cc
  23. 2
      sql/opt_range.h
  24. 6
      sql/opt_range_mrr.cc
  25. 2
      sql/opt_subselect.cc
  26. 1
      sql/opt_subselect.h
  27. 4
      sql/sql_class.h
  28. 1
      sql/sql_priv.h
  29. 376
      sql/sql_select.cc
  30. 8
      sql/sql_select.h
  31. 596
      sql/sql_statistics.cc
  32. 194
      sql/sql_statistics.h
  33. 37
      sql/sys_vars.cc
  34. 14
      sql/table.cc
  35. 8
      sql/table.h
  36. 40
      sql/uniques.cc

25
mysql-test/r/mysqld--help.result

@ -208,6 +208,13 @@ The following options may be given as the first argument:
use a distinct domain_id. For simple tree-shaped
replication topologies, it can be left at its default, 0.
-?, --help Display this help and exit.
--histogram-size=# Number of bytes used for a histogram. If set to 0, no
histograms are created by ANALYZE.
--histogram-type=name
Specifies type of the histograms created by ANALYZE.
Possible values are: SINGLE_PREC_HB - single precision
height-balanced, DOUBLE_PREC_HB - double precision
height-balanced.
--ignore-builtin-innodb
Disable initialization of builtin InnoDB plugin
--ignore-db-dirs=name
@ -506,6 +513,21 @@ The following options may be given as the first argument:
partial_match_table_scan, semijoin, semijoin_with_cache,
subquery_cache, table_elimination, extended_keys,
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 the cardinality of a 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 the cardinality of a
partial join in any case, 3 - additionally always use
selectivity of range conditions that are not backed by
any index to calculate the cardinality of a partial join,
4 - use histograms to calculate selectivity of range
conditions that are not backed by any index to calculate
the cardinality of a partial join.
--performance-schema
Enable the performance schema.
--performance-schema-events-waits-history-long-size=#
@ -940,6 +962,8 @@ general-log FALSE
group-concat-max-len 1024
gtid-domain-id 0
help TRUE
histogram-size 0
histogram-type SINGLE_PREC_HB
ignore-builtin-innodb FALSE
ignore-db-dirs
init-connect
@ -1030,6 +1054,7 @@ old-style-user-limits FALSE
optimizer-prune-level 1
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-use-condition-selectivity 1
performance-schema FALSE
performance-schema-events-waits-history-long-size 10000
performance-schema-events-waits-history-size 10

1014
mysql-test/r/selectivity.result
File diff suppressed because it is too large
View File

1024
mysql-test/r/selectivity_innodb.result
File diff suppressed because it is too large
View File

570
mysql-test/r/statistics.result

@ -64,13 +64,13 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -87,8 +87,8 @@ COUNT(*)
40
SELECT * FROM mysql.column_stats
WHERE db_name='test' AND table_name='t1' AND column_name='a';
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
SELECT MIN(t1.a), MAX(t1.a),
(SELECT COUNT(*) FROM t1 WHERE t1.b IS NULL) /
(SELECT COUNT(*) FROM t1) AS "NULLS_RATIO(t1.a)",
@ -99,8 +99,8 @@ MIN(t1.a) MAX(t1.a) NULLS_RATIO(t1.a) AVG_FREQUENCY(t1.a)
0 49 0.2000 1.0000
SELECT * FROM mysql.column_stats
WHERE db_name='test' AND table_name='t1' AND column_name='b';
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
SELECT MIN(t1.b), MAX(t1.b),
(SELECT COUNT(*) FROM t1 WHERE t1.b IS NULL) /
(SELECT COUNT(*) FROM t1) AS "NULLS_RATIO(t1.b)",
@ -111,8 +111,8 @@ MIN(t1.b) MAX(t1.b) NULLS_RATIO(t1.b) AVG_FREQUENCY(t1.b)
vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000
SELECT * FROM mysql.column_stats
WHERE db_name='test' AND table_name='t1' AND column_name='c';
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
SELECT MIN(t1.c), MAX(t1.c),
(SELECT COUNT(*) FROM t1 WHERE t1.c IS NULL) /
(SELECT COUNT(*) FROM t1) AS "NULLS_RATIO(t1.c)",
@ -123,8 +123,8 @@ MIN(t1.c) MAX(t1.c) NULLS_RATIO(t1.c) AVG_FREQUENCY(t1.c)
aaaa dddddddd 0.1250 7.0000
SELECT * FROM mysql.column_stats
WHERE db_name='test' AND table_name='t1' AND column_name='d';
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
SELECT MIN(t1.d), MAX(t1.d),
(SELECT COUNT(*) FROM t1 WHERE t1.d IS NULL) /
(SELECT COUNT(*) FROM t1) AS "NULLS_RATIO(t1.d)",
@ -135,8 +135,8 @@ MIN(t1.d) MAX(t1.d) NULLS_RATIO(t1.d) AVG_FREQUENCY(t1.d)
1989-03-12 1999-07-23 0.1500 8.5000
SELECT * FROM mysql.column_stats
WHERE db_name='test' AND table_name='t1' AND column_name='e';
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
SELECT MIN(t1.e), MAX(t1.e),
(SELECT COUNT(*) FROM t1 WHERE t1.e IS NULL) /
(SELECT COUNT(*) FROM t1) AS "NULLS_RATIO(t1.e)",
@ -206,6 +206,47 @@ WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL)
AS 'ARITY 3';
ARITY 1 ARITY 2 ARITY 3
6.2000 1.6875 1.1304
DELETE FROM mysql.column_stats;
set histogram_size=4;
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
SELECT db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type HEX(histogram)
test t1 a 0 49 0.0000 1.0000 4 SINGLE_PREC_HB 2E62A1D0
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 4 SINGLE_PREC_HB 003FBFFF
test t1 c aaaa dddddddd 0.1250 7.0000 4 SINGLE_PREC_HB 0055AAFF
test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 4 SINGLE_PREC_HB 009393FF
test t1 e 0.01 0.112 0.2250 6.2000 4 SINGLE_PREC_HB 000564E1
test t1 f 1 5 0.2000 6.4000 4 SINGLE_PREC_HB 3F7FBFBF
DELETE FROM mysql.column_stats;
set histogram_size=8;
set histogram_type='DOUBLE_PREC_HB';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
SELECT db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type HEX(histogram)
test t1 a 0 49 0.0000 1.0000 8 DOUBLE_PREC_HB 052F4363F4A1F9D0
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 8 DOUBLE_PREC_HB 0000FF3FFFBFFFFF
test t1 c aaaa dddddddd 0.1250 7.0000 8 DOUBLE_PREC_HB 00005555AAAAFFFF
test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 8 DOUBLE_PREC_HB 000026942694FFFF
test t1 e 0.01 0.112 0.2250 6.2000 8 DOUBLE_PREC_HB 000005056464E1E1
test t1 f 1 5 0.2000 6.4000 8 DOUBLE_PREC_HB FF3FFF7FFFBFFFBF
DELETE FROM mysql.column_stats;
set histogram_size= 0;
set histogram_type=default;
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
CREATE TABLE t3 (
a int NOT NULL PRIMARY KEY,
b varchar(32),
@ -238,16 +279,16 @@ db_name table_name cardinality
test t1 40
test t3 17
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
test t3 a 0 38 0.0000 4.0000 1.0000
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -267,16 +308,16 @@ db_name table_name cardinality
test s1 40
test t3 17
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test s1 a 0 49 0.0000 4.0000 1.0000
test s1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test s1 c aaaa dddddddd 0.1250 6.6571 7.0000
test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test s1 e 0.01 0.112 0.2250 8.0000 6.2000
test s1 f 1 5 0.2000 1.0000 6.4000
test t3 a 0 38 0.0000 4.0000 1.0000
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test s1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test s1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test s1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test s1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test s1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test s1 PRIMARY 1 1.0000
@ -296,16 +337,16 @@ db_name table_name cardinality
test t1 40
test t3 17
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
test t3 a 0 38 0.0000 4.0000 1.0000
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t3 a 0 38 0.0000 4.0000 1.0000 0 NULL NULL
test t3 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.1765 18.0714 2.8000 0 NULL NULL
test t3 c aaaa dddddddd 0.1176 6.4000 3.7500 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -324,13 +365,13 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -365,13 +406,13 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`y`,`x`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 y 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 y 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
ALTER TABLE t1 CHANGE COLUMN x b varchar(32),
CHANGE COLUMN y e double;
SHOW CREATE TABLE t1;
@ -390,13 +431,13 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
ALTER TABLE t1 RENAME TO s1, CHANGE COLUMN b x varchar(32);
SHOW CREATE TABLE s1;
Table Create Table
@ -417,13 +458,13 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test s1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test s1 a 0 49 0.0000 4.0000 1.0000
test s1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test s1 c aaaa dddddddd 0.1250 6.6571 7.0000
test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test s1 e 0.01 0.112 0.2250 8.0000 6.2000
test s1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test s1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test s1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test s1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test s1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test s1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test s1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test s1 PRIMARY 1 1.0000
@ -455,13 +496,13 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -490,12 +531,12 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`x`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -519,12 +560,12 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -535,13 +576,13 @@ ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -576,12 +617,12 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`x`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -605,12 +646,12 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -624,13 +665,13 @@ LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_index_stats'
INTO TABLE mysql.index_stats
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -658,12 +699,12 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -721,12 +762,12 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -735,13 +776,13 @@ ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b NULL NULL 1.0000 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b NULL NULL 1.0000 NULL NULL 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -758,13 +799,13 @@ ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -790,12 +831,12 @@ t1 CREATE TABLE `t1` (
KEY `idx3` (`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -820,12 +861,12 @@ t1 CREATE TABLE `t1` (
KEY `idx4` (`e`,`b`,`d`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -834,13 +875,13 @@ ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4);
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -862,7 +903,7 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(c,e,b) INDEXES(idx2,idx4);
@ -872,10 +913,10 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 idx2 1 7.0000
@ -912,13 +953,13 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -942,19 +983,19 @@ db_name table_name cardinality
test t1 40
test t2 40
SELECT * FROM mysql.column_stats ORDER BY column_name;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t2 a 0 49 0.0000 4.0000 1.0000
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t2 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
test t2 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t2 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t2 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -986,13 +1027,13 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t2 40
SELECT * FROM mysql.column_stats ORDER BY column_name;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t2 a 0 49 0.0000 4.0000 1.0000
test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t2 e 0.01 0.112 0.2250 8.0000 6.2000
test t2 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t2 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t2 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t2 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats ORDER BY index_name, prefix_arity, table_name;
db_name table_name index_name prefix_arity avg_frequency
test t2 PRIMARY 1 1.0000
@ -1122,12 +1163,12 @@ MODIFY COLUMN b text,
ADD INDEX idx1 (b(4), e),
ADD INDEX idx4 (e, b(4), d);
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t2 a 0 49 0.0000 4.0000 1.0000
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t2 e 0.01 0.112 0.2250 8.0000 6.2000
test t2 f 1 5 0.2000 1.0000 6.4000
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t2 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t2 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx3 1 8.5000
@ -1143,18 +1184,18 @@ ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t2 a 0 49 0.0000 4.0000 1.0000
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t2 e 0.01 0.112 0.2250 8.0000 6.2000
test t2 f 1 5 0.2000 1.0000 6.4000
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
test t1 b NULL NULL 0.2000 17.1250 NULL
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t2 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t2 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t2 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t2 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t2 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t1 b NULL NULL 0.2000 17.1250 NULL NULL NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t2 idx3 1 8.5000
@ -1187,7 +1228,7 @@ mysql.column_stats analyze status OK
SELECT * FROM mysql.table_stats;
db_name table_name cardinality
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
set use_stat_tables='never';
@ -1198,13 +1239,13 @@ SELECT * FROM mysql.table_stats;
db_name table_name cardinality
test t1 40
SELECT * FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency
test t1 a 0 49 0.0000 4.0000 1.0000
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000
test t1 e 0.01 0.112 0.2250 8.0000 6.2000
test t1 f 1 5 0.2000 1.0000 6.4000
test t1 b NULL NULL 0.2000 17.1250 NULL
db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram
test t1 a 0 49 0.0000 4.0000 1.0000 0 NULL NULL
test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL
test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL
test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL
test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL
test t1 b NULL NULL 0.2000 17.1250 NULL NULL NULL NULL
SELECT * FROM mysql.index_stats;
db_name table_name index_name prefix_arity avg_frequency
test t1 PRIMARY 1 1.0000
@ -1426,4 +1467,87 @@ UPPER(db_name) UPPER(table_name) index_name prefix_arity avg_frequency
DELETE FROM mysql.table_stats;
DELETE FROM mysql.column_stats;
DELETE FROM mysql.index_stats;
#
# Bug mdev-4357: empty string as a value of the HIST_SIZE column
# from mysql.column_stats
#
create table t1 (a int);
insert into t1 values (1),(2),(3);
set histogram_size=10;
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
test.t1 analyze status OK
select db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type HEX(histogram)
test t1 a 1 3 0.0000 1.0000 10 SINGLE_PREC_HB 0000007F7F7F7FFFFFFF
set histogram_size=default;
drop table t1;
#
# Bug mdev-4359: wrong setting of the HIST_SIZE column
# (see also mdev-4357) from mysql.column_stats
#
create table t1 ( a int);
insert into t1 values (1),(2),(3),(4),(5);
set histogram_size=10;
set histogram_type='double_prec_hb';
show variables like 'histogram%';
Variable_name Value
histogram_size 10
histogram_type DOUBLE_PREC_HB
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
test.t1 analyze status OK
select db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type HEX(histogram)
test t1 a 1 5 0.0000 1.0000 10 DOUBLE_PREC_HB 0000FF3FFF7FFFBFFFFF
set histogram_size=default;
set histogram_type=default;
drop table t1;
#
# Bug mdev-4369: histogram for a column with many distinct values
#
CREATE TABLE t1 (id int);
CREATE TABLE t2 (id int);
INSERT INTO t1 (id) VALUES (1), (1), (1),(1);
INSERT INTO t1 (id) SELECT id FROM t1;
INSERT INTO t1 SELECT id+1 FROM t1;
INSERT INTO t1 SELECT id+2 FROM t1;
INSERT INTO t1 SELECT id+4 FROM t1;
INSERT INTO t1 SELECT id+8 FROM t1;
INSERT INTO t1 SELECT id+16 FROM t1;
INSERT INTO t1 SELECT id+32 FROM t1;
INSERT INTO t1 SELECT id+64 FROM t1;
INSERT INTO t1 SELECT id+128 FROM t1;
INSERT INTO t1 SELECT id+256 FROM t1;
INSERT INTO t1 SELECT id+512 FROM t1;
INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
SELECT COUNT(*) FROM t2;
COUNT(*)
8192
SELECT COUNT(DISTINCT id) FROM t2;
COUNT(DISTINCT id)
1024
set @@tmp_table_size=1024*16;
set @@max_heap_table_size=1024*16;
set histogram_size=63;
analyze table t2 persistent for all;
Table Op Msg_type Msg_text
test.t2 analyze status OK
select db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type HEX(histogram)
test t2 id 1 1024 0.0000 8.0000 63 SINGLE_PREC_HB 03070B0F13171B1F23272B2F33373B3F43474B4F53575B5F63676B6F73777B7F83878B8F93979B9FA3A7ABAFB3B7BBBFC3C7CBCFD3D7DBDFE3E7EBEFF3F7FB
set histogram_size=default;
drop table t1, t2;
set use_stat_tables=@save_use_stat_tables;

3
mysql-test/r/system_mysql_db.result

@ -287,6 +287,9 @@ column_stats CREATE TABLE `column_stats` (
`nulls_ratio` decimal(12,4) DEFAULT NULL,
`avg_length` decimal(12,4) DEFAULT NULL,
`avg_frequency` decimal(12,4) DEFAULT NULL,
`hist_size` tinyint(3) unsigned DEFAULT NULL,
`hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8_bin DEFAULT NULL,
`histogram` varbinary(255) DEFAULT NULL,
PRIMARY KEY (`db_name`,`table_name`,`column_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Statistics on Columns'
show create table index_stats;

7
mysql-test/suite/funcs_1/r/is_columns_mysql.result

@ -13,6 +13,9 @@ def mysql column_stats avg_frequency 8 NULL YES decimal NULL NULL 12 4 NULL NULL
def mysql column_stats avg_length 7 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4) select,insert,update,references
def mysql column_stats column_name 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references
def mysql column_stats db_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references
def mysql column_stats histogram 11 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) select,insert,update,references
def mysql column_stats hist_size 9 NULL YES tinyint NULL NULL 3 0 NULL NULL NULL tinyint(3) unsigned select,insert,update,references
def mysql column_stats hist_type 10 NULL YES enum 14 42 NULL NULL NULL utf8 utf8_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') select,insert,update,references
def mysql column_stats max_value 5 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_bin varchar(255) select,insert,update,references
def mysql column_stats min_value 4 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_bin varchar(255) select,insert,update,references
def mysql column_stats nulls_ratio 6 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4) select,insert,update,references
@ -260,6 +263,7 @@ ORDER BY CHARACTER_SET_NAME, COLLATION_NAME, COL_CML;
COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME
1.0000 blob NULL NULL
1.0000 longblob NULL NULL
1.0000 varbinary NULL NULL
1.0000 char latin1 latin1_bin
1.0000 char latin1 latin1_swedish_ci
1.0000 varchar latin1 latin1_swedish_ci
@ -332,6 +336,9 @@ NULL mysql columns_priv Timestamp timestamp NULL NULL NULL NULL timestamp
NULL mysql column_stats nulls_ratio decimal NULL NULL NULL NULL decimal(12,4)
NULL mysql column_stats avg_length decimal NULL NULL NULL NULL decimal(12,4)
NULL mysql column_stats avg_frequency decimal NULL NULL NULL NULL decimal(12,4)
NULL mysql column_stats hist_size tinyint NULL NULL NULL NULL tinyint(3) unsigned
3.0000 mysql column_stats hist_type enum 14 42 utf8 utf8_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB')
1.0000 mysql column_stats histogram varbinary 255 255 NULL NULL varbinary(255)
3.0000 mysql db Host char 60 180 utf8 utf8_bin char(60)
3.0000 mysql db Db char 64 192 utf8 utf8_bin char(64)
3.0000 mysql db User char 16 48 utf8 utf8_bin char(16)

7
mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result

@ -13,6 +13,9 @@ def mysql column_stats avg_frequency 8 NULL YES decimal NULL NULL 12 4 NULL NULL
def mysql column_stats avg_length 7 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4)
def mysql column_stats column_name 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI
def mysql column_stats db_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI
def mysql column_stats histogram 11 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255)
def mysql column_stats hist_size 9 NULL YES tinyint NULL NULL 3 0 NULL NULL NULL tinyint(3) unsigned
def mysql column_stats hist_type 10 NULL YES enum 14 42 NULL NULL NULL utf8 utf8_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB')
def mysql column_stats max_value 5 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_bin varchar(255)
def mysql column_stats min_value 4 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_bin varchar(255)
def mysql column_stats nulls_ratio 6 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4)
@ -260,6 +263,7 @@ ORDER BY CHARACTER_SET_NAME, COLLATION_NAME, COL_CML;
COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME
1.0000 blob NULL NULL
1.0000 longblob NULL NULL
1.0000 varbinary NULL NULL
1.0000 char latin1 latin1_bin
1.0000 char latin1 latin1_swedish_ci
1.0000 varchar latin1 latin1_swedish_ci
@ -332,6 +336,9 @@ NULL mysql columns_priv Timestamp timestamp NULL NULL NULL NULL timestamp
NULL mysql column_stats nulls_ratio decimal NULL NULL NULL NULL decimal(12,4)
NULL mysql column_stats avg_length decimal NULL NULL NULL NULL decimal(12,4)
NULL mysql column_stats avg_frequency decimal NULL NULL NULL NULL decimal(12,4)
NULL mysql column_stats hist_size tinyint NULL NULL NULL NULL tinyint(3) unsigned
3.0000 mysql column_stats hist_type enum 14 42 utf8 utf8_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB')
1.0000 mysql column_stats histogram varbinary 255 255 NULL NULL varbinary(255)
3.0000 mysql db Host char 60 180 utf8 utf8_bin char(60)
3.0000 mysql db Db char 64 192 utf8 utf8_bin char(64)
3.0000 mysql db User char 16 48 utf8 utf8_bin char(16)

136
mysql-test/suite/sys_vars/r/histogram_size_basic.result

@ -0,0 +1,136 @@
SET @start_global_value = @@global.histogram_size;
SELECT @start_global_value;
@start_global_value
0
SET @start_session_value = @@session.histogram_size;
SELECT @start_session_value;
@start_session_value
0
'#--------------------FN_DYNVARS_053_01-------------------------#'
SET @@global.histogram_size = DEFAULT;
SELECT @@global.histogram_size;
@@global.histogram_size
0
SET @@session.histogram_size = DEFAULT;
SELECT @@session.histogram_size;
@@session.histogram_size
0
'#--------------------FN_DYNVARS_053_03-------------------------#'
SET @@global.histogram_size = 1;
SELECT @@global.histogram_size;
@@global.histogram_size
1
SET @@global.histogram_size = 31;
SELECT @@global.histogram_size;
@@global.histogram_size
31
SET @@global.histogram_size = 255;
SELECT @@global.histogram_size;
@@global.histogram_size
255
'#--------------------FN_DYNVARS_053_04-------------------------#'
SET @@session.histogram_size = 1;
SELECT @@session.histogram_size;
@@session.histogram_size
1
SET @@session.histogram_size = 31;
SELECT @@session.histogram_size;
@@session.histogram_size
31
SET @@session.histogram_size = 255;
SELECT @@session.histogram_size;
@@session.histogram_size
255
'#------------------FN_DYNVARS_053_05-----------------------#'
SET @@global.histogram_size = -1;
Warnings:
Warning 1292 Truncated incorrect histogram_size value: '-1'
SELECT @@global.histogram_size;
@@global.histogram_size
0
SET @@global.histogram_size = 256;
Warnings:
Warning 1292 Truncated incorrect histogram_size value: '256'
SELECT @@global.histogram_size;
@@global.histogram_size
255
SET @@global.histogram_size = 1024;
Warnings:
Warning 1292 Truncated incorrect histogram_size value: '1024'
SELECT @@global.histogram_size;
@@global.histogram_size
255
SET @@global.histogram_size = 4.5;
ERROR 42000: Incorrect argument type to variable 'histogram_size'
SELECT @@global.histogram_size;
@@global.histogram_size
255
SET @@global.histogram_size = test;
ERROR 42000: Incorrect argument type to variable 'histogram_size'
SELECT @@global.histogram_size;
@@global.histogram_size
255
SET @@session.histogram_size = -1;
Warnings:
Warning 1292 Truncated incorrect histogram_size value: '-1'
SELECT @@session.histogram_size;
@@session.histogram_size
0
SET @@session.histogram_size = 256;
Warnings:
Warning 1292 Truncated incorrect histogram_size value: '256'
SELECT @@session.histogram_size;
@@session.histogram_size
255
SET @@session.histogram_size = 1024;
Warnings:
Warning 1292 Truncated incorrect histogram_size value: '1024'
SELECT @@session.histogram_size;
@@session.histogram_size
255
SET @@session.histogram_size = 4.5;
ERROR 42000: Incorrect argument type to variable 'histogram_size'
SELECT @@session.histogram_size;
@@session.histogram_size
255
SET @@session.histogram_size = test;
ERROR 42000: Incorrect argument type to variable 'histogram_size'
SELECT @@session.histogram_size;
@@session.histogram_size
255
'#------------------FN_DYNVARS_053_06-----------------------#'
SELECT @@global.histogram_size = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='histogram_size';
@@global.histogram_size = VARIABLE_VALUE
1
'#------------------FN_DYNVARS_053_07-----------------------#'
SELECT @@session.histogram_size = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='histogram_size';
@@session.histogram_size = VARIABLE_VALUE
1
'#------------------FN_DYNVARS_053_08-----------------------#'
SET @@global.histogram_size = TRUE;
SET @@global.histogram_size = FALSE;
'#---------------------FN_DYNVARS_001_09----------------------#'
SET @@global.histogram_size = 10;
SELECT @@histogram_size = @@global.histogram_size;
@@histogram_size = @@global.histogram_size
0
'#---------------------FN_DYNVARS_001_10----------------------#'
SET @@histogram_size = 100;
SELECT @@histogram_size = @@local.histogram_size;
@@histogram_size = @@local.histogram_size
1
SELECT @@local.histogram_size = @@session.histogram_size;
@@local.histogram_size = @@session.histogram_size
1
SET @@global.histogram_size = @start_global_value;
SELECT @@global.histogram_size;
@@global.histogram_size
0
SET @@session.histogram_size = @start_session_value;
SELECT @@session.histogram_size;
@@session.histogram_size
0

79
mysql-test/suite/sys_vars/r/histogram_type_basic.result

@ -0,0 +1,79 @@
SET @start_global_value = @@global.histogram_type;
SELECT @start_global_value;
@start_global_value
SINGLE_PREC_HB
SET @start_session_value = @@session.histogram_type;
SELECT @start_session_value;
@start_session_value
SINGLE_PREC_HB
SET @@global.histogram_type = 1;
SET @@global.histogram_type = DEFAULT;
SELECT @@global.histogram_type;
@@global.histogram_type
SINGLE_PREC_HB
SET @@global.histogram_type = 0;
SELECT @@global.histogram_type;
@@global.histogram_type
SINGLE_PREC_HB
SET @@global.histogram_type = 1;
SELECT @@global.histogram_type;
@@global.histogram_type
DOUBLE_PREC_HB
SET @@global.histogram_type = SINGLE_PREC_HB;
SELECT @@global.histogram_type;
@@global.histogram_type
SINGLE_PREC_HB
SET @@global.histogram_type = DOUBLE_PREC_HB;
SELECT @@global.histogram_type;
@@global.histogram_type
DOUBLE_PREC_HB
SET @@session.histogram_type = 0;
SELECT @@session.histogram_type;
@@session.histogram_type
SINGLE_PREC_HB
SET @@session.histogram_type = 1;
SELECT @@session.histogram_type;
@@session.histogram_type
DOUBLE_PREC_HB
SET @@session.histogram_type = SINGLE_PREC_HB;
SELECT @@session.histogram_type;
@@session.histogram_type
SINGLE_PREC_HB
SET @@session.histogram_type = DOUBLE_PREC_HB;
SELECT @@session.histogram_type;
@@session.histogram_type
DOUBLE_PREC_HB
set sql_mode=TRADITIONAL;
SET @@global.histogram_type = 10;
ERROR 42000: Variable 'histogram_type' can't be set to the value of '10'
SET @@global.histogram_type = -1024;
ERROR 42000: Variable 'histogram_type' can't be set to the value of '-1024'
SET @@global.histogram_type = 2.4;
ERROR 42000: Incorrect argument type to variable 'histogram_type'
SET @@global.histogram_type = OFF;
ERROR 42000: Variable 'histogram_type' can't be set to the value of 'OFF'
SET @@session.histogram_type = 10;
ERROR 42000: Variable 'histogram_type' can't be set to the value of '10'
SET @@session.histogram_type = -2;
ERROR 42000: Variable 'histogram_type' can't be set to the value of '-2'
SET @@session.histogram_type = 1.2;
ERROR 42000: Incorrect argument type to variable 'histogram_type'
SET @@session.histogram_type = ON;
ERROR 42000: Variable 'histogram_type' can't be set to the value of 'ON'
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='histogram_type';
VARIABLE_NAME VARIABLE_VALUE
HISTOGRAM_TYPE DOUBLE_PREC_HB
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='histogram_type';
VARIABLE_NAME VARIABLE_VALUE
HISTOGRAM_TYPE DOUBLE_PREC_HB
SET @@global.histogram_type = @start_global_value;
SELECT @@global.histogram_type;
@@global.histogram_type
SINGLE_PREC_HB
SET @@session.histogram_type = @start_session_value;
SELECT @@session.histogram_type;
@@session.histogram_type
SINGLE_PREC_HB
set sql_mode='';

109
mysql-test/suite/sys_vars/r/optimizer_use_condition_selectivity_basic.result

@ -0,0 +1,109 @@
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
SET @@global.optimizer_use_condition_selectivity = 4;
SELECT @@global.optimizer_use_condition_selectivity;
@@global.optimizer_use_condition_selectivity
4
'#--------------------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
SET @@session.optimizer_use_condition_selectivity = 4;
SELECT @@session.optimizer_use_condition_selectivity;
@@session.optimizer_use_condition_selectivity
4
'#------------------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

142
mysql-test/suite/sys_vars/t/histogram_size_basic.test

@ -0,0 +1,142 @@
--source include/load_sysvars.inc
##############################################################
# START OF histogram_size TESTS #
##############################################################
#############################################################
# Save initial value #
#############################################################
SET @start_global_value = @@global.histogram_size;
SELECT @start_global_value;
SET @start_session_value = @@session.histogram_size;
SELECT @start_session_value;
--echo '#--------------------FN_DYNVARS_053_01-------------------------#'
################################################################
# Display the DEFAULT value of histogram_size #
################################################################
SET @@global.histogram_size = DEFAULT;
SELECT @@global.histogram_size;
SET @@session.histogram_size = DEFAULT;
SELECT @@session.histogram_size;
--echo '#--------------------FN_DYNVARS_053_03-------------------------#'
########################################################################
# Change the value of histogram_size to a valid value for GLOBAL Scope #
########################################################################
SET @@global.histogram_size = 1;
SELECT @@global.histogram_size;
SET @@global.histogram_size = 31;
SELECT @@global.histogram_size;
SET @@global.histogram_size = 255;
SELECT @@global.histogram_size;
--echo '#--------------------FN_DYNVARS_053_04-------------------------#'
#########################################################################
# Change the value of histogram_size to a valid value for SESSION Scope #
#########################################################################
SET @@session.histogram_size = 1;
SELECT @@session.histogram_size;
SET @@session.histogram_size = 31;
SELECT @@session.histogram_size;
SET @@session.histogram_size = 255;
SELECT @@session.histogram_size;
--echo '#------------------FN_DYNVARS_053_05-----------------------#'
##########################################################
# Change the value of histogram_size to an invalid value #
###########################################################
SET @@global.histogram_size = -1;
SELECT @@global.histogram_size;
SET @@global.histogram_size = 256;
SELECT @@global.histogram_size;
SET @@global.histogram_size = 1024;
SELECT @@global.histogram_size;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@global.histogram_size = 4.5;
SELECT @@global.histogram_size;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@global.histogram_size = test;
SELECT @@global.histogram_size;
SET @@session.histogram_size = -1;
SELECT @@session.histogram_size;
SET @@session.histogram_size = 256;
SELECT @@session.histogram_size;
SET @@session.histogram_size = 1024;
SELECT @@session.histogram_size;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.histogram_size = 4.5;
SELECT @@session.histogram_size;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.histogram_size = test;
SELECT @@session.histogram_size;
--echo '#------------------FN_DYNVARS_053_06-----------------------#'
####################################################################
# Check if the value in GLOBAL Table matches value in variable #
####################################################################
SELECT @@global.histogram_size = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='histogram_size';
--echo '#------------------FN_DYNVARS_053_07-----------------------#'
####################################################################
# Check if the value in SESSION Table matches value in variable #
####################################################################
SELECT @@session.histogram_size = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='histogram_size';
--echo '#------------------FN_DYNVARS_053_08-----------------------#'
####################################################################
# Check if TRUE and FALSE values can be used on variable #
####################################################################
SET @@global.histogram_size = TRUE;
SET @@global.histogram_size = FALSE;
--echo '#---------------------FN_DYNVARS_001_09----------------------#'
#################################################################################
# Check if accessing variable with and without GLOBAL point to same variable #
#################################################################################
SET @@global.histogram_size = 10;
SELECT @@histogram_size = @@global.histogram_size;
--echo '#---------------------FN_DYNVARS_001_10----------------------#'
########################################################################################################
# Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable #
########################################################################################################
SET @@histogram_size = 100;
SELECT @@histogram_size = @@local.histogram_size;
SELECT @@local.histogram_size = @@session.histogram_size;
####################################
# Restore initial value #
####################################
SET @@global.histogram_size = @start_global_value;
SELECT @@global.histogram_size;
SET @@session.histogram_size = @start_session_value;
SELECT @@session.histogram_size;
###################################################
# END OF histogram_size TESTS #
###################################################

92
mysql-test/suite/sys_vars/t/histogram_type_basic.test

@ -0,0 +1,92 @@
--source include/load_sysvars.inc
#############################################################
# Save initial value #
#############################################################
SET @start_global_value = @@global.histogram_type;
SELECT @start_global_value;
SET @start_session_value = @@session.histogram_type;
SELECT @start_session_value;
##############################################################
# Display the DEFAULT value of histogram_type #
##############################################################
SET @@global.histogram_type = 1;
SET @@global.histogram_type = DEFAULT;
SELECT @@global.histogram_type;
#################################################################################
# Change the value of histogram_type to a valid value for GLOBAL Scope #
#################################################################################
SET @@global.histogram_type = 0;
SELECT @@global.histogram_type;
SET @@global.histogram_type = 1;
SELECT @@global.histogram_type;
SET @@global.histogram_type = SINGLE_PREC_HB;
SELECT @@global.histogram_type;
SET @@global.histogram_type = DOUBLE_PREC_HB;
SELECT @@global.histogram_type;
###################################################################################
# Change the value of histogram_type to a valid value for SESSION Scope #
###################################################################################
SET @@session.histogram_type = 0;
SELECT @@session.histogram_type;
SET @@session.histogram_type = 1;
SELECT @@session.histogram_type;
SET @@session.histogram_type = SINGLE_PREC_HB;
SELECT @@session.histogram_type;
SET @@session.histogram_type = DOUBLE_PREC_HB;
SELECT @@session.histogram_type;
####################################################################
# Change the value of histogram_type to an invalid value #
####################################################################
set sql_mode=TRADITIONAL;
--Error ER_WRONG_VALUE_FOR_VAR
SET @@global.histogram_type = 10;
--Error ER_WRONG_VALUE_FOR_VAR
SET @@global.histogram_type = -1024;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@global.histogram_type = 2.4;
--Error ER_WRONG_VALUE_FOR_VAR
SET @@global.histogram_type = OFF;
--Error ER_WRONG_VALUE_FOR_VAR
SET @@session.histogram_type = 10;
--Error ER_WRONG_VALUE_FOR_VAR
SET @@session.histogram_type = -2;
--Error ER_WRONG_TYPE_FOR_VAR
SET @@session.histogram_type = 1.2;
--Error ER_WRONG_VALUE_FOR_VAR
SET @@session.histogram_type = ON;
###############################################################################
# Check if the value in GLOBAL & SESSION Tables matches value in variable #
###############################################################################
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='histogram_type';
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES
WHERE VARIABLE_NAME='histogram_type';
####################################
# Restore initial value #
####################################
SET @@global.histogram_type = @start_global_value;
SELECT @@global.histogram_type;
SET @@session.histogram_type = @start_session_value;
SELECT @@session.histogram_type;
set sql_mode='';
#####################################################
# END OF histogram_type TESTS #
#####################################################

142
mysql-test/suite/sys_vars/t/optimizer_use_condition_selectivity_basic.test

@ -0,0 +1,142 @@
--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;
SET @@global.optimizer_use_condition_selectivity = 4;
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;
SET @@session.optimizer_use_condition_selectivity = 4;
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 #
########################################################################

623
mysql-test/t/selectivity.test

@ -0,0 +1,623 @@
--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';
set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity;
set @save_histogram_size=@@histogram_size;
set @save_histogram_type=@@histogram_type;
# check that statistics on nulls is used
set optimizer_use_condition_selectivity=3;
create table t1 (a int);
insert into t1 values
(9), (3), (2), (NULL), (NULL), (2), (NULL), (1), (5), (NULL);
analyze table t1;
select * from mysql.column_stats;
flush table t1;
explain extended
select * from t1 where a is null;
explain extended
select * from t1 where a is not null;
drop table t1;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
--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
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
--echo === Q15 ===
create view revenue0 (supplier_no, total_revenue) as
select l_suppkey, sum(l_extendedprice * (1 - l_discount))
from lineitem
where
l_shipdate >= '1995-08-01'
and l_shipdate < date_add('1995-08-01', interval 90 day)
group by l_suppkey;
let $Q15=
select s_suppkey, s_name, s_address, s_phone, total_revenue
from supplier, revenue0
where s_suppkey = supplier_no
and total_revenue = (select max(total_revenue) from revenue0)
order by s_suppkey;
set @save_optimizer_switch=@@optimizer_switch;
set optimizer_switch='index_condition_pushdown=off';
set optimizer_use_condition_selectivity=1;
eval EXPLAIN EXTENDED $Q15;
eval $Q15;
set optimizer_use_condition_selectivity=3;
eval EXPLAIN EXTENDED $Q15;
eval $Q15;
set optimizer_switch=@save_optimizer_switch;
drop view revenue0;
--echo === Q16 ===
let $Q16=
select p_brand, p_type, p_size, count(distinct ps_suppkey) as supplier_cnt
from partsupp, part
where p_partkey = ps_partkey
and p_brand <> 'Brand#11'
and p_type not like 'SMALL POLISHED%'
and p_size in (49, 37, 27, 5, 40, 6, 22, 8)
and ps_suppkey not in (select s_suppkey from supplier
where s_comment like '%Customer%Complaints%')
group by p_brand, p_type, p_size
order by supplier_cnt desc, p_brand, p_type, p_size;
set optimizer_use_condition_selectivity=1;
eval EXPLAIN EXTENDED $Q16;
eval $Q16;
set optimizer_use_condition_selectivity=3;
eval EXPLAIN EXTENDED $Q16;
eval $Q16;
set optimizer_use_condition_selectivity=4;
eval EXPLAIN EXTENDED $Q16;
eval $Q16;
--echo === Q18 ===
let $Q18=
select
c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice, sum(l_quantity)
from customer, orders, lineitem
where
o_orderkey in (select l_orderkey from lineitem
group by l_orderkey having sum(l_quantity) > 250)
and c_custkey = o_custkey
and o_orderkey = l_orderkey
group by c_name, c_custkey, o_orderkey, o_orderdate, o_totalprice
order by o_totalprice desc, o_orderdate;
set optimizer_use_condition_selectivity=1;
eval EXPLAIN EXTENDED $Q18;
eval $Q18;
set optimizer_use_condition_selectivity=3;
eval EXPLAIN EXTENDED $Q18;
eval $Q18;
--echo === Q22 ===
let $Q22=
select cntrycode, count(*) as numcust, sum(c_acctbal) as totacctbal
from (
select substr(c_phone, 1, 2) as cntrycode, c_acctbal
from customer
where
substr(c_phone, 1, 2) in ('10', '20', '14', '19', '11', '28', '25')
and c_acctbal > (select avg(c_acctbal) from customer
where c_acctbal > 0.00
and substr(c_phone, 1, 2) in
('10', '20', '14', '19', '11', '28', '25'))
and not exists (select * from orders where o_custkey = c_custkey)
) as vip
group by cntrycode
order by cntrycode;
set optimizer_use_condition_selectivity=1;
eval EXPLAIN EXTENDED $Q22;
eval $Q22;
set optimizer_use_condition_selectivity=3;
eval EXPLAIN EXTENDED $Q22;
eval $Q22;
--echo === Q20 ===
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;
set optimizer_use_condition_selectivity=1;
eval EXPLAIN EXTENDED $Q20;
eval $Q20;
SELECT ((SELECT COUNT(*) FROM part WHERE p_name LIKE 'g%') /
(SELECT COUNT(*) FROM part)) AS sel;
set optimizer_use_condition_selectivity=3;
eval EXPLAIN EXTENDED $Q20;
eval $Q20;
set histogram_size=127;
ANALYZE TABLE part PERSISTENT FOR COLUMNS(p_name) INDEXES();
flush table part;
set optimizer_use_condition_selectivity=4;
eval EXPLAIN EXTENDED $Q20;
eval $Q20;
set histogram_type='DOUBLE_PREC_HB';
set histogram_size=126;
ANALYZE TABLE part PERSISTENT FOR COLUMNS(p_name) INDEXES();
flush table part;
eval EXPLAIN EXTENDED $Q20;
eval $Q20;
set histogram_type='SINGLE_PREC_HB';
set histogram_size=24;
ANALYZE TABLE nation PERSISTENT FOR COLUMNS(n_name) INDEXES();
flush table nation;
eval EXPLAIN EXTENDED $Q20;
eval $Q20;
DROP DATABASE dbt3_s001;
set histogram_type=@save_histogram_type;
set histogram_size=@save_histogram_size;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
use test;
--echo #
--echo # Bug mdev-4348: using view with use_condition_selectivity > 1
--echo #
set @tmp_use_stat_tables=@@use_stat_tables;
set use_stat_tables='never';
set optimizer_use_condition_selectivity=3;
CREATE TABLE t1 (a int, b int);
INSERT t1 VALUES (7,1), (0,7);
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1;
CREATE TABLE t2 (c int, d int, index idx(d));
INSERT INTO t2 VALUES
(0,4), (8,6), (1,3), (8,5), (9,3), (2,2), (6,2),
(1,9), (6,3), (2,8), (4,1), (0,7), (4,8), (4,5);
EXPLAIN EXTENDED
SELECT * FROM v1 INNER JOIN t2 ON ( a = c AND b = d );
SELECT * FROM v1 INNER JOIN t2 ON ( a = c AND b = d );
DROP VIEW v1;
DROP TABLE t1,t2;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
set use_stat_tables=@tmp_use_stat_tables;
--echo #
--echo # Bug mdev-4349: impossible range for non-indexed column
--echo #
set optimizer_use_condition_selectivity=3;
create table t1 (a int);
insert into t1 values
(3), (7), (2), (5), (7), (1), (2), (2);
set optimizer_use_condition_selectivity=1;
explain extended
select * from t1 where a < 1 and a > 7;
select * from t1 where a < 1 and a > 7;
set optimizer_use_condition_selectivity=3;
explain extended
select * from t1 where a < 1 and a > 7;
select * from t1 where a < 1 and a > 7;
drop table t1;
create table t1 (a int);
insert into t1 values (1);
create table t2 (b int);
insert into t2 values (2),(3);
explain extended
select * from t1 where a in ( select b from t2 ) AND ( a > 3 );
select * from t1 where a in ( select b from t2 ) AND ( a > 3 );
drop table t1,t2;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
--echo #
--echo # Bug mdev-4350: erroneous negative selectivity
--echo #
create table t1 (a int);
insert into t1 values (1), (1);
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 select * from t1;
insert into t1 values (0);
select count(*) from t1;
set use_stat_tables='preferably';
set histogram_size=127;
set histogram_type='SINGLE_PREC_HB';
analyze table t1;
flush table t1;
set optimizer_use_condition_selectivity=4;
explain extended select * from t1 where a=0;
drop table t1;
set histogram_size=@save_histogram_size;
set histogram_type=@save_histogram_type;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
--echo #
--echo # Bug mdev-4367: 2-way join with an empty table
--echo # when optimizer_use_condition_selectivity=3
--echo #
set optimizer_use_condition_selectivity=3;
CREATE TABLE t1 (a varchar(1)) ENGINE=MyISAM;
INSERT INTO t1 VALUES ('j'),('k');
CREATE TABLE t2 (b varchar(1)) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('x'),('y');
CREATE TABLE t3 (c varchar(1), KEY(c)) ENGINE=MyISAM;
SELECT * FROM t1 STRAIGHT_JOIN (t2 JOIN t3 ON c = b AND b > 'z');
DROP TABLE t1,t2,t3;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
--echo #
--echo # Bug mdev-4366: impossible condition on an indexed column discovered after
--echo # substitution of constant tables
--echo # with optimizer_use_condition_selectivity=3
--echo #
CREATE TABLE t1 (pk int PRIMARY KEY, a int);
INSERT INTO t1 VALUES
(1,4), (2,6), (3,3), (4,5);
CREATE TABLE t2 (b int);
INSERT INTO t2 VALUES (1), (7);
set optimizer_use_condition_selectivity=1;
EXPLAIN EXTENDED
SELECT 1 FROM t1, t2 WHERE pk = 6 AND a = 2 AND b = 10;
SELECT 1 FROM t1, t2 WHERE pk = 6 AND a = 2 AND b = 10;
set optimizer_use_condition_selectivity=3;
EXPLAIN EXTENDED
SELECT 1 FROM t1, t2 WHERE pk = 6 AND a = 2 AND b = 10;
SELECT 1 FROM t1, t2 WHERE pk = 6 AND a = 2 AND b = 10;
DROP TABLE t1,t2;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
--echo #
--echo # Bug mdev-4370: Histograms have bean created, but the query is run after
--echo # FLUSH TABLES with optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables=PREFERABLY;
set histogram_size=10;
set histogram_type='SINGLE_PREC_HB';
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (9), (1);
ANALYZE TABLE t1;
FLUSH TABLES;
set optimizer_use_condition_selectivity=3;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a > 3;
SELECT * FROM t1 WHERE a > 3;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1;
set histogram_size=@save_histogram_size;
set histogram_type=@save_histogram_type;
set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-4371: Join with condition supported by index on an empty table
--echo # with optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables=PREFERABLY;
CREATE TABLE t1 (a int, b int, INDEX(a));
CREATE TABLE t2 (c int);
INSERT INTO t2 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
ANALYZE TABLE t1, t2;
FLUSH TABLES;
set optimizer_use_condition_selectivity=3;
set @save_optimizer_switch=@@optimizer_switch;
set optimizer_switch='index_condition_pushdown=off';
EXPLAIN EXTENDED
SELECT * FROM t1, t2 WHERE a > 9;
SELECT * FROM t1, t2 WHERE a > 9;
set optimizer_switch=@save_optimizer_switch;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1,t2;
set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-4373: condition on a short varchar column
--echo # with optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables=PREFERABLY;
CREATE TABLE t1 (a varchar(1));
INSERT INTO t1 VALUES ('x'), ('y');
ANALYZE TABLE t1;
FLUSH TABLES;
set optimizer_use_condition_selectivity=3;
SELECT * FROM t1 WHERE a <= 'w';
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1;
set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-4372: exists subquery in WHERE
--echo # with optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables = PREFERABLY;
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES
(1),(7),(4),(7),(0),(2),(9),(4),(0),(9),(1),(3),(8),(8);
CREATE TABLE t2 (b int);
INSERT INTO t2 VALUES (4),(5),(2),(5),(1),(1),(2);
ANALYZE TABLE t1, t2;
FLUSH TABLES;
set optimizer_use_condition_selectivity=3;
EXPLAIN EXTENDED
SELECT * FROM t1, t2 WHERE EXISTS ( SELECT 1 FROM t1, t2 ) AND a != b OR a <= 4;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1,t2;
set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-4363: selectivity of the condition a IS NULL OR IS NOT NULL
--echo # with optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables = PREFERABLY;
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES
(1),(7),(4),(7),(NULL),(2),(NULL),(4),(NULL),(NULL),(1),(3),(8),(8);
ANALYZE TABLE t1;
FLUSH TABLE t1;
set optimizer_use_condition_selectivity=3;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a IS NULL;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a IS NOT NULL;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a IS NULL OR a IS NOT NULL;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a IS NULL OR a < 5;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1;
set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-4378: 2-way join with a materialized IN subquery in WHERE
--echo # when optimizer_use_condition_selectivity=4
--echo #
set use_stat_tables=PREFERABLY;
set histogram_size=50;
set histogram_type=SINGLE_PREC_HB;
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (8),(9),(6);
CREATE TABLE t2 (b INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (8),(1),(8),(9),(24),(6),(1),(6),(2),(4);
CREATE TABLE t3 (ln VARCHAR(16)) ENGINE=MyISAM;
INSERT INTO t3 VALUES
('smith'),('black'),('white'),('jones'),
('brown'),('taylor'),('anderson'),('taylor');
ANALYZE TABLE t1, t2, t3;
FLUSH TABLES;
set optimizer_use_condition_selectivity=4;
SELECT * FROM t1, t2 WHERE 'garcia' IN ( SELECT MIN( ln ) FROM t3 WHERE ln = 'sun' );
set histogram_size=@save_histogram_size;
set histogram_type=@save_histogram_type;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1,t2,t3;
set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-4380: 2-way join with a materialized IN subquery in WHERE
--echo # when optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables=PREFERABLY;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (5),(9);
CREATE TABLE t2 (b VARCHAR(8));
INSERT INTO t2 VALUES ('red'),('blue');
CREATE TABLE t3 (c VARCHAR(8), d VARCHAR(8));
INSERT INTO t3 VALUES ('white','black'),('cyan','yellow');
ANALYZE TABLE t1, t2, t3;
FLUSH TABLES;
set optimizer_use_condition_selectivity=3;
SELECT * FROM t1, t2 WHERE ( 'orange', 'green' ) IN (
SELECT MAX(c), MAX(d) FROM t3, t2 WHERE c >= d AND b = c
);
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1,t2,t3;
set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-4389: join with degenerated range condition in WHERE
--echo # when optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables=PREFERABLY;
CREATE TABLE t1 (f1 VARCHAR(1));
INSERT t1 VALUES ('p'),('q');
CREATE TABLE t2 (f2 VARCHAR(1));
INSERT INTO t2 VALUES
('o'),('v'),('f'),('f'),('e'),('l'),('j'),('p'),('r'),('j'),
('j'),('u'),('i'),('r'),('x'),('a'),('x'),('s');
ANALYZE TABLE t1, t2;
FLUSH TABLES;
SET optimizer_use_condition_selectivity=3;
SELECT * FROM t1, t2 AS t2a, t2 AS t2b WHERE f1 <= 'a' AND t2a.f2 = f1;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
DROP TABLE t1,t2;
set use_stat_tables=@save_use_stat_tables;
set use_stat_tables=@save_use_stat_tables;

12
mysql-test/t/selectivity_innodb.test

@ -0,0 +1,12 @@
--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;

123
mysql-test/t/statistics.test

@ -165,6 +165,37 @@ SELECT
WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL)
AS 'ARITY 3';
DELETE FROM mysql.column_stats;
set histogram_size=4;
ANALYZE TABLE t1;
SELECT db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
DELETE FROM mysql.column_stats;
set histogram_size=8;
set histogram_type='DOUBLE_PREC_HB';
ANALYZE TABLE t1;
SELECT db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
DELETE FROM mysql.column_stats;
set histogram_size= 0;
set histogram_type=default;
ANALYZE TABLE t1;
CREATE TABLE t3 (
a int NOT NULL PRIMARY KEY,
b varchar(32),
@ -559,6 +590,96 @@ DELETE FROM mysql.table_stats;
DELETE FROM mysql.column_stats;
DELETE FROM mysql.index_stats;
--echo #
--echo # Bug mdev-4357: empty string as a value of the HIST_SIZE column
--echo # from mysql.column_stats
--echo #
create table t1 (a int);
insert into t1 values (1),(2),(3);
set histogram_size=10;
analyze table t1 persistent for all;
select db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
set histogram_size=default;
drop table t1;
--echo #
--echo # Bug mdev-4359: wrong setting of the HIST_SIZE column
--echo # (see also mdev-4357) from mysql.column_stats
--echo #
create table t1 ( a int);
insert into t1 values (1),(2),(3),(4),(5);
set histogram_size=10;
set histogram_type='double_prec_hb';
show variables like 'histogram%';
analyze table t1 persistent for all;
select db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
set histogram_size=default;
set histogram_type=default;
drop table t1;
--echo #
--echo # Bug mdev-4369: histogram for a column with many distinct values
--echo #
CREATE TABLE t1 (id int);
CREATE TABLE t2 (id int);
INSERT INTO t1 (id) VALUES (1), (1), (1),(1);
INSERT INTO t1 (id) SELECT id FROM t1;
INSERT INTO t1 SELECT id+1 FROM t1;
INSERT INTO t1 SELECT id+2 FROM t1;
INSERT INTO t1 SELECT id+4 FROM t1;
INSERT INTO t1 SELECT id+8 FROM t1;
INSERT INTO t1 SELECT id+16 FROM t1;
INSERT INTO t1 SELECT id+32 FROM t1;
INSERT INTO t1 SELECT id+64 FROM t1;
INSERT INTO t1 SELECT id+128 FROM t1;
INSERT INTO t1 SELECT id+256 FROM t1;
INSERT INTO t1 SELECT id+512 FROM t1;
INSERT INTO t2 SELECT id FROM t1 ORDER BY id*rand();
SELECT COUNT(*) FROM t2;
SELECT COUNT(DISTINCT id) FROM t2;
set @@tmp_table_size=1024*16;
set @@max_heap_table_size=1024*16;
set histogram_size=63;
analyze table t2 persistent for all;
select db_name, table_name, column_name,
min_value, max_value,
nulls_ratio, avg_frequency,
hist_size, hist_type, HEX(histogram)
FROM mysql.column_stats;
set histogram_size=default;
drop table t1, t2;
set use_stat_tables=@save_use_stat_tables;

2
scripts/mysql_system_tables.sql

@ -114,6 +114,6 @@ set @had_proxies_priv_table= @@warning_count != 0;
CREATE TABLE IF NOT EXISTS table_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, cardinality bigint(21) unsigned DEFAULT NULL, PRIMARY KEY (db_name,table_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Tables';
CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varchar(255) DEFAULT NULL, max_value varchar(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, PRIMARY KEY (db_name,table_name,column_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns';
CREATE TABLE IF NOT EXISTS column_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, column_name varchar(64) NOT NULL, min_value varchar(255) DEFAULT NULL, max_value varchar(255) DEFAULT NULL, nulls_ratio decimal(12,4) DEFAULT NULL, avg_length decimal(12,4) DEFAULT NULL, avg_frequency decimal(12,4) DEFAULT NULL, hist_size tinyint unsigned, hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB'), histogram varbinary(255), PRIMARY KEY (db_name,table_name,column_name) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns';
CREATE TABLE IF NOT EXISTS index_stats (db_name varchar(64) NOT NULL, table_name varchar(64) NOT NULL, index_name varchar(64) NOT NULL, prefix_arity int(11) unsigned NOT NULL, avg_frequency decimal(12,4) DEFAULT NULL, PRIMARY KEY (db_name,table_name,index_name,prefix_arity) ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Indexes';

136
sql/field.cc

@ -1273,6 +1273,37 @@ out_of_range:
return 1;
}
/**
@brief
Determine the relative position of the field value in a numeric interval
@details
The function returns a double number between 0.0 and 1.0 as the relative
position of the value of the this field in the numeric interval of [min,max].
If the value is not in the interval the the function returns 0.0 when
the value is less than min, and, 1.0 when the value is greater than max.
@param min value of the left end of the interval
@param max value of the right end of the interval
@return
relative position of the field value in the numeric interval [min,max]
*/
double Field_num::pos_in_interval(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
truncation.
@ -1344,6 +1375,8 @@ Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
comment.length=0;
field_index= 0;
is_stat_field= FALSE;
cond_selectivity= 1.0;
next_equal_field= NULL;
}
@ -6167,6 +6200,79 @@ int Field_str::store(double nr)
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);
}
/**
@brief
Determine the relative position of the field value in a string interval
@details
The function returns a double number between 0.0 and 1.0 as the relative
position of the value of the this field in the string interval of [min,max].
If the value is not in the interval the the function returns 0.0 when
the value is less than min, and, 1.0 when the value is greater than max.
@note
To calculate the relative position of the string value v in the interval
[min, max] the function first converts the beginning of these three
strings v, min, max into the strings that are used for byte comparison.
For each string not more sizeof(ulonglong) first bytes are taken
from the result of conversion. Then these bytes are interpreted as the
big-endian representation of an ulonglong integer. The values of these
integer numbers obtained for the strings v, min, max are used to calculate
the position of v in [min,max] in the same way is it's done for numeric
fields (see Field_num::pos_in_interval).
@todo
Improve the procedure for the case when min and max have the same
beginning
@param min value of the left end of the interval
@param max value of the right end of the interval
@return
relative position of the field value in the string interval [min,max]
*/
double Field_str::pos_in_interval(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(),
data_length());
my_strnxfrm(charset(), minp_prefix, sizeof(minp),
min->ptr + length_size(),
min->data_length());
my_strnxfrm(charset(), maxp_prefix, sizeof(maxp),
max->ptr + length_size(),
max->data_length());
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)
{
@ -8378,6 +8484,36 @@ my_decimal *Field_bit::val_decimal(my_decimal *deciaml_value)
}
/**
@brief
Determine the relative position of the field value in a bit interval
@details
The function returns a double number between 0.0 and 1.0 as the relative
position of the value of the this field in the bit interval of [min,max].
If the value is not in the interval the the function returns 0.0 when
the value is less than min, and, 1.0 when the value is greater than max.
@param min value of the left end of the interval
@param max value of the right end of the interval
@return
relative position of the field value in the bit interval [min,max]
*/
double Field_bit::pos_in_interval(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);
}
/*
Compare two bit fields using pointers within the record.
SYNOPSIS

37
sql/field.h

@ -220,7 +220,23 @@ public:
*/
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
@ -456,6 +472,10 @@ public:
}
return update_fl;
}
virtual void store_field_value(uchar *val, uint len)
{
memcpy(ptr, val, len);
}
virtual uint decimals() const { return 0; }
/*
Caller beware: sql_type can change str.Ptr, so check
@ -703,6 +723,12 @@ public:
virtual bool hash_join_is_possible() { return TRUE; }
virtual bool eq_cmp_as_binary() { return TRUE; }
/* Position of the field value within the interval of [min, max] */
virtual double pos_in_interval(Field *min, Field *max)
{
return (double) 0.5;
}
friend int cre_myisam(char * name, register TABLE *form, uint options,
ulonglong auto_increment_value);
friend class Copy_field;
@ -821,6 +847,7 @@ public:
bool get_int(CHARSET_INFO *cs, const char *from, uint len,
longlong *rnd, ulonglong unsigned_max,
longlong signed_min, longlong signed_max);
double pos_in_interval(Field *min, Field *max);
};
@ -866,6 +893,8 @@ public:
virtual bool str_needs_quotes() { return TRUE; }
uint is_equal(Create_field *new_field);
bool eq_cmp_as_binary() { return test(flags & BINARY_FLAG); }
virtual uint length_size() { return 0; }
double pos_in_interval(Field *min, Field *max);
};
/* base class for Field_string, Field_varstring and Field_blob */
@ -1894,6 +1923,7 @@ public:
uint new_null_bit);
uint is_equal(Create_field *new_field);
void hash(ulong *nr, ulong *nr2);
uint length_size() { return length_bytes; }
private:
int do_save_field_metadata(uchar *first_byte);
};
@ -2275,6 +2305,11 @@ public:
}
return update_fl;
}
void store_field_value(uchar *val, uint len)
{
store(*((longlong *)val), TRUE);
}
double pos_in_interval(Field *min, Field *max);
void get_image(uchar *buff, uint length, CHARSET_INFO *cs)
{ get_key_image(buff, length, itRAW); }
void set_image(const uchar *buff,uint length, CHARSET_INFO *cs)

20
sql/item_cmpfunc.cc

@ -5568,7 +5568,8 @@ Item *Item_bool_rowready_func2::negated_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;
with_const= with_const_item;
@ -5592,7 +5593,8 @@ Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item)
*/
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;
List_iterator_fast<Item> li(item_equal->equal_items);
@ -5918,6 +5920,9 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
DBUG_ASSERT(fixed == 0);
Item_equal_fields_iterator it(*this);
Item *item;
Field *first_equal_field;
Field *last_equal_field;
Field *prev_equal_field= NULL;
not_null_tables_cache= used_tables_cache= 0;
const_item_cache= 0;
while ((item= it++))
@ -5931,7 +5936,18 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
maybe_null= 1;
if (!item->get_item_equal())
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();
fixed= 1;
return FALSE;

4
sql/item_cmpfunc.h

@ -1737,6 +1737,8 @@ class Item_equal: public Item_bool_func
*/
Item_field *context_field;
bool link_equal_fields;
public:
COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
@ -1774,6 +1776,8 @@ public:
CHARSET_INFO *compare_collation();
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_iterator<List_iterator_fast,Item>;
friend class Item_equal_iterator<List_iterator,Item>;
friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,

322
sql/opt_range.cc

@ -117,6 +117,7 @@
#include "records.h" // init_read_record, end_read_record
#include <m_ctype.h>
#include "sql_select.h"
#include "sql_statistics.h"
#include "filesort.h" // filesort_free_buffers
#ifndef EXTRA_DEBUG
@ -3217,6 +3218,327 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_RETURN(records ? test(quick) : -1);
}
/****************************************************************************
* Condition selectivity module
****************************************************************************/
/*
Build descriptors of pseudo-indexes over columns to perform range analysis
SYNOPSIS
create_key_parts_for_pseudo_indexes()
param IN/OUT data structure for the descriptors to be built
used_fields bitmap of columns for which the descriptors are to be built
DESCRIPTION
For each column marked in the bitmap used_fields the function builds
a descriptor of a single-component pseudo-index over this column that
can be used for the range analysis of the predicates over this columns.
The descriptors are created in the memory of param->mem_root.
RETURN
FALSE in the case of success
TRUE otherwise
*/
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;
key_part->flag= 0;
param->key[keys]= key_part;
keys++;
key_part++;
}
}
param->keys= keys;
param->key_parts_end= key_part;
return FALSE;
}
/*
Estimate the number of rows in all ranges built for a column
by the range optimizer
SYNOPSIS
records_in_column_ranges()
param the data structure to access descriptors of pseudo indexes
built over columns used in the condition of the processed query
idx the index of the descriptor of interest in param
tree the tree representing ranges built for the interesting column
DESCRIPTION
This function retrieves the ranges represented by the SEL_ARG 'tree' and
for each of them r it calls the function get_column_range_cardinality()
that estimates the number of expected rows in r. It is assumed that param
is the data structure containing the descriptors of pseudo-indexes that
has been built to perform range analysis of the range conditions imposed
on the columns used in the processed query, while idx is the index of the
descriptor created in 'param' exactly for the column for which 'tree'
has been built by the range optimizer.
RETURN
the number of rows in the retrieved ranges
*/
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,
range.range_flag);
if (HA_POS_ERROR == rows)
{
total_rows= HA_POS_ERROR;
break;
}
total_rows += rows;
}
return total_rows;
}
/*
Calculate the selectivity of the condition imposed on the rows of a table
SYNOPSIS
calculate_cond_selectivity_for_table()
thd the context handle
table the table of interest
cond conditions imposed on the rows of the table
DESCRIPTION
This function calculates the selectivity of range conditions cond imposed
on the rows of 'table' in the processed query.
The calculated selectivity is assigned to the field table->cond_selectivity.
NOTE
Currently the selectivities of range conditions over different columns are
considered independent.
RETURN
FALSE on success
TRUE otherwise
*/
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 (table_records == 0)
DBUG_RETURN(FALSE);
if (thd->variables.optimizer_use_condition_selectivity > 2 &&
!bitmap_is_clear_all(used_fields))
{
/*
Calculate the selectivity of the range conditions not supported
by any index
*/
PARAM param;
MEM_ROOT alloc;
SEL_TREE *tree;
SEL_ARG **key, **end;
double rows;
uint idx= 0;
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))
goto free_alloc;
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;
tree= get_mm_tree(&param, cond);
if (!tree)
goto free_alloc;
table->reginfo.impossible_range= 0;
if (tree->type == SEL_TREE::IMPOSSIBLE)
{
rows= 0;
table->reginfo.impossible_range= 1;
goto free_alloc;
}
else if (tree->type == SEL_TREE::MAYBE)
{
rows= table_records;
goto free_alloc;
}
for (key= tree->keys, end= key + param.keys; key != end; key++, idx++)
{
if (*key)
{
if ((*key)->type == SEL_ARG::IMPOSSIBLE)
{
rows= 0;
table->reginfo.impossible_range= 1;
goto free_alloc;
}
else
{
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;
}
free_alloc:
thd->mem_root= param.old_root;
free_root(&alloc, MYF(0));
}
/* 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)
{
table->cond_selectivity*= quick_cond_selectivity;
if (i != used_key_parts)
{
double f1= key_info->actual_rec_per_key(i-1);
double f2= key_info->actual_rec_per_key(i);
table->cond_selectivity*= f1 / f2;
}
}
}
}
}
DBUG_RETURN(FALSE);
}
/****************************************************************************
* Condition selectivity code ends
****************************************************************************/
/****************************************************************************
* Partition pruning module
****************************************************************************/

2
sql/opt_range.h

@ -1042,6 +1042,8 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds,
bool allow_null_cond, int *error);
bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond);
#ifdef WITH_PARTITION_STORAGE_ENGINE
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
void store_key_image_to_rec(Field *field, uchar *ptr, uint len);

6
sql/opt_range_mrr.cc

@ -268,8 +268,10 @@ walk_up_n_right:
range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts);
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->param->table->key_info[seq->real_keyno].flags & HA_NOSAME) &&
(seq->real_keyno == MAX_KEY ||
((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 &&
!memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length))
range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);

2
sql/opt_subselect.cc

@ -3908,7 +3908,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd)
&tmpname, (uint) strlen(path)+1,
&group_buff, (!using_unique_constraint ?
uniq_tuple_length_arg : 0),
&bitmaps, bitmap_buffer_size(1)*3,
&bitmaps, bitmap_buffer_size(1)*5,
NullS))
{
if (temp_pool_slot != MY_BIT_NONE)

1
sql/opt_subselect.h

@ -283,6 +283,7 @@ public:
{
pos->records_read= best_loose_scan_records;
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_parts= best_max_loose_keypart + 1;
pos->use_join_buffer= FALSE;

4
sql/sql_class.h

@ -504,7 +504,10 @@ typedef struct system_variables
ulong net_write_timeout;
ulong optimizer_prune_level;
ulong optimizer_search_depth;
ulong optimizer_use_condition_selectivity;
ulong use_stat_tables;
ulong histogram_size;
ulong histogram_type;
ulong preload_buff_size;
ulong profiling_history_size;
ulong read_buff_size;
@ -4017,6 +4020,7 @@ class Unique :public Sql_alloc
uint size;
uint full_size;
uint min_dupl_count; /* always 0 for unions, > 0 for intersections */
bool with_counters;
bool merge(TABLE *table, uchar *buff, bool without_last_merge);

1
sql/sql_priv.h

@ -228,6 +228,7 @@ template <class T> bool valid_buffer_range(T jump,
#define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 26)
#define OPTIMIZER_SWITCH_EXTENDED_KEYS (1ULL << 27)
#define OPTIMIZER_SWITCH_EXISTS_TO_IN (1ULL << 28)
#define OPTIMIZER_SWITCH_USE_CONDITION_SELECTIVITY (1ULL << 29)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \

376
sql/sql_select.cc

@ -89,12 +89,14 @@ void best_access_path(JOIN *join, JOIN_TAB *s,
POSITION *pos, POSITION *loose_scan_pos);
static void optimize_straight_join(JOIN *join, table_map join_tables);
static bool greedy_search(JOIN *join, table_map remaining_tables,
uint depth, uint prune_level);
uint depth, uint prune_level,
uint use_cond_selectivity);
static bool best_extension_by_limited_search(JOIN *join,
table_map remaining_tables,
uint idx, double record_count,
double read_time, uint depth,
uint prune_level);
uint prune_level,
uint use_cond_selectivity);
static uint determine_search_depth(JOIN* join);
C_MODE_START
static int join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2);
@ -134,7 +136,8 @@ static COND *build_equal_items(JOIN *join, COND *cond,
COND_EQUAL *inherited,
List<TABLE_LIST> *join_list,
bool ignore_on_conds,
COND_EQUAL **cond_equal_ref);
COND_EQUAL **cond_equal_ref,
bool link_equal_fields= FALSE);
static COND* substitute_for_best_equal_field(JOIN_TAB *context_tab,
COND *cond,
COND_EQUAL *cond_equal,
@ -150,8 +153,9 @@ static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list,
static COND *optimize_cond(JOIN *join, COND *conds,
List<TABLE_LIST> *join_list,
bool ignore_on_conds,
Item::cond_result *cond_value,
COND_EQUAL **cond_equal);
Item::cond_result *cond_value,
COND_EQUAL **cond_equal,
int flags= 0);
bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool create_internal_tmp_table_from_heap2(THD *, TABLE *,
ENGINE_COLUMNDEF *, ENGINE_COLUMNDEF **,
@ -279,6 +283,8 @@ enum enum_exec_or_opt {WALK_OPTIMIZATION_TABS , WALK_EXECUTION_TABS};
JOIN_TAB *first_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind);
JOIN_TAB *next_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind,
JOIN_TAB *tab);
static double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
table_map rem_tables);
#ifndef DBUG_OFF
@ -1158,7 +1164,7 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S
DBUG_RETURN(1);
conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal);
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
if (thd->is_error())
{
@ -3355,6 +3361,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
table->pos_in_table_list= tables;
error= tables->fetch_number_of_rows();
set_statistics_for_table(join->thd, table);
bitmap_clear_all(&table->cond_set);
#ifdef WITH_PARTITION_STORAGE_ENGINE
const bool no_partitions_used= table->no_partitions_used;
@ -3786,6 +3793,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
all select distinct fields participate in one index.
*/
add_group_and_distinct_keys(join, s);
s->table->cond_selectivity= 1.0;
/*
Perform range analysis if there are keys it could use (1).
@ -3794,7 +3803,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
Don't do range analysis for materialized subqueries (4).
Don't do range analysis for materialized derived tables (5)
*/
if (!s->const_keys.is_clear_all() && // (1)
if ((!s->const_keys.is_clear_all() ||
!bitmap_is_clear_all(&s->table->cond_set)) && // (1)
(!s->table->pos_in_table_list->embedding || // (2)
(s->table->pos_in_table_list->embedding && // (3)
s->table->pos_in_table_list->embedding->sj_on_expr)) && // (3)
@ -3802,20 +3812,37 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
!(s->table->pos_in_table_list->derived && // (5)
s->table->pos_in_table_list->is_materialized_derived())) // (5)
{
ha_rows records;
SQL_SELECT *select;
select= make_select(s->table, found_const_table_map,
found_const_table_map,
*s->on_expr_ref ? *s->on_expr_ref : conds,
1, &error);
if (!select)
goto error;
records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit);
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
if (records == 0 && s->table->reginfo.impossible_range)
bool impossible_range= FALSE;
ha_rows records= HA_POS_ERROR;
SQL_SELECT *select= 0;
if (!s->const_keys.is_clear_all())
{
select= make_select(s->table, found_const_table_map,
found_const_table_map,
*s->on_expr_ref ? *s->on_expr_ref : conds,
1, &error);
if (!select)
goto error;
records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit);
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
}
if (!impossible_range)
{
if (join->thd->variables.optimizer_use_condition_selectivity > 1)
calculate_cond_selectivity_for_table(join->thd, s->table,
*s->on_expr_ref ?
*s->on_expr_ref : conds);
if (s->table->reginfo.impossible_range)
{
impossible_range= TRUE;
records= 0;
}
}
if (impossible_range)
{
/*
Impossible WHERE or ON expression
@ -3840,8 +3867,10 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
s->found_records=records;
s->read_time= s->quick ? s->quick->read_time : 0.0;
}
delete select;
if (select)
delete select;
}
}
if (pull_out_semijoin_tables(join))
@ -4198,11 +4227,12 @@ add_key_field(JOIN *join,
else if (!(field->flags & PART_KEY_FLAG))
{
// Don't remove column IS NULL on a LEFT JOIN table
if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
!field->table->maybe_null || field->null_ptr)
return; // Not a key. Skip it
optimize= KEY_OPTIMIZE_EXISTS;
DBUG_ASSERT(num_values == 1);
if (eq_func && (*value)->type() == Item::NULL_ITEM &&
field->table->maybe_null && !field->null_ptr)
{
optimize= KEY_OPTIMIZE_EXISTS;
DBUG_ASSERT(num_values == 1);
}
}
if (optimize != KEY_OPTIMIZE_EXISTS)
{
@ -4251,7 +4281,11 @@ add_key_field(JOIN *join,
break;
}
if (is_const)
{
stat[0].const_keys.merge(possible_keys);
if (possible_keys.is_clear_all())
bitmap_set_bit(&field->table->cond_set, field->field_index);
}
else if (!eq_func)
{
/*
@ -5322,6 +5356,7 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
join->positions[idx].table= table;
join->positions[idx].key=key;
join->positions[idx].records_read=1.0; /* This is a const table */
join->positions[idx].cond_selectivity= 1.0;
join->positions[idx].ref_depend_map= 0;
// join->positions[idx].loosescan_key= MAX_KEY; /* Not a LooseScan */
@ -6140,6 +6175,8 @@ choose_plan(JOIN *join, table_map join_tables)
{
uint search_depth= join->thd->variables.optimizer_search_depth;
uint prune_level= join->thd->variables.optimizer_prune_level;
uint use_cond_selectivity=
join->thd->variables.optimizer_use_condition_selectivity;
bool straight_join= test(join->select_options & SELECT_STRAIGHT_JOIN);
DBUG_ENTER("choose_plan");
@ -6204,7 +6241,8 @@ choose_plan(JOIN *join, table_map join_tables)
if (search_depth == 0)
/* Automatically determine a reasonable value for 'search_depth' */
search_depth= determine_search_depth(join);
if (greedy_search(join, join_tables, search_depth, prune_level))
if (greedy_search(join, join_tables, search_depth, prune_level,
use_cond_selectivity))
DBUG_RETURN(TRUE);
}
}
@ -6478,6 +6516,8 @@ optimize_straight_join(JOIN *join, table_map join_tables)
bool disable_jbuf= join->thd->variables.join_cache_level == 0;
double record_count= 1.0;
double read_time= 0.0;
uint use_cond_selectivity=
join->thd->variables.optimizer_use_condition_selectivity;
POSITION loose_scan_pos;
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
@ -6494,6 +6534,11 @@ optimize_straight_join(JOIN *join, table_map join_tables)
&loose_scan_pos);
join_tables&= ~(s->table->map);
double pushdown_cond_selectivity= 1.0;
if (use_cond_selectivity > 1)
pushdown_cond_selectivity= table_cond_selectivity(join, idx, s,
join_tables);
join->positions[idx].cond_selectivity= pushdown_cond_selectivity;
++idx;
}
@ -6581,6 +6626,8 @@ optimize_straight_join(JOIN *join, table_map join_tables)
@param search_depth controlls the exhaustiveness of the search
@param prune_level the pruning heuristics that should be applied during
search
@param use_cond_selectivity specifies how the selectivity of the conditions
pushed to a table should be taken into account
@retval
FALSE ok
@ -6592,7 +6639,8 @@ static bool
greedy_search(JOIN *join,
table_map remaining_tables,
uint search_depth,
uint prune_level)
uint prune_level,
uint use_cond_selectivity)
{
double record_count= 1.0;
double read_time= 0.0;
@ -6617,7 +6665,8 @@ greedy_search(JOIN *join,
/* Find the extension of the current QEP with the lowest cost */
join->best_read= DBL_MAX;
if (best_extension_by_limited_search(join, remaining_tables, idx, record_count,
read_time, search_depth, prune_level))
read_time, search_depth, prune_level,
use_cond_selectivity))
DBUG_RETURN(TRUE);
/*
'best_read < DBL_MAX' means that optimizer managed to find
@ -6856,6 +6905,210 @@ double JOIN::get_examined_rows()
}
static
double table_multi_eq_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
table_map rem_tables, uint keyparts,
uint16 *ref_keyuse_steps)
{
double sel= 1.0;
COND_EQUAL *cond_equal= join->cond_equal;
if (!cond_equal || !cond_equal->current_level.elements)
return sel;
if (!s->keyuse)
return sel;
Item_equal *item_equal;
List_iterator_fast<Item_equal> it(cond_equal->current_level);
TABLE *table= s->table;
table_map table_bit= table->map;
POSITION *pos= &join->positions[idx];
while ((item_equal= it++))
{
/*
Check whether we need to take into account the selectivity of
multiple equality item_equal. If this is the case multiply
the current value of sel by this selectivity
*/
table_map used_tables= item_equal->used_tables();
if (!(used_tables & table_bit))
continue;
if (item_equal->get_const())
continue;
Field *fld;
bool adjust_sel= FALSE;
Item_equal_fields_iterator fi(*item_equal);
while((fi++) && !adjust_sel)
{
Field *fld= fi.get_curr_field();
if (fld->table->map != table_bit)
continue;
if (pos->key == 0)
adjust_sel= TRUE;
else
{
uint i;
KEYUSE *keyuse= pos->key;
uint key= keyuse->key;
for (i= 0; i < keyparts; i++)
{
uint fldno;
if (is_hash_join_key_no(key))
fldno= keyuse->keypart;
else
fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
if (fld->field_index == fldno)
break;
}
if (i == keyparts)
{
/*
Field fld is included in multiple equality item_equal
and is not a part of the ref key.
The selectivity of the multiple equality must be taken
into account unless one of the ref arguments is
equal to fld.
*/
adjust_sel= TRUE;
for (uint j= 0; j < keyparts && adjust_sel; j++)
{
if (j > 0)
keyuse+= ref_keyuse_steps[j-1];
Item *ref_item= keyuse->val;
if (ref_item->real_item()->type() == Item::FIELD_ITEM)
{
Item_field *field_item= (Item_field *) (ref_item->real_item());
if (item_equal->contains(field_item->field))
adjust_sel= FALSE;
}
}
}
}
}
if (adjust_sel)
{
/*
If ref == 0 and there are no fields in the multiple equality
item_equal that belong to the tables joined prior to s
then the selectivity of multiple equality will be set to 1.0.
*/
double eq_fld_sel= 1.0;
fi.rewind();
while ((fi++))
{
double curr_eq_fld_sel;
fld= fi.get_curr_field();
if (!fld->table->map & ~(table_bit | rem_tables))
continue;
curr_eq_fld_sel= get_column_avg_frequency(fld) /
fld->table->stat_records();
if (curr_eq_fld_sel < 1.0)
set_if_bigger(eq_fld_sel, curr_eq_fld_sel);
}
sel*= eq_fld_sel;
}
}
return sel;
}
static
double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
table_map rem_tables)
{
uint16 ref_keyuse_steps[MAX_REF_PARTS - 1];
Field *field;
TABLE *table= s->table;
MY_BITMAP *read_set= table->read_set;
double sel= s->table->cond_selectivity;
double table_records= table->stat_records();
POSITION *pos= &join->positions[idx];
uint keyparts= 0;
uint found_part_ref_or_null= 0;
/* Discount the selectivity of the access method used to join table s */
if (s->quick && s->quick->index != MAX_KEY)
{
if (pos->key == 0 && table_records > 0)
{
sel*= table->quick_rows[s->quick->index]/table_records;
}
}
else if (pos->key != 0)
{
/* A ref/ access or hash join is used to join table */
KEYUSE *keyuse= pos->key;
KEYUSE *prev_ref_keyuse= keyuse;
uint key= keyuse->key;
do
{
if (!(keyuse->used_tables & (rem_tables | table->map)))
{
if (are_tables_local(s, keyuse->val->used_tables()))
{
if (is_hash_join_key_no(key))
{
if (keyparts == keyuse->keypart)
keyparts++;
}
else
{
if (keyparts == keyuse->keypart &&
!(~(keyuse->val->used_tables()) & pos->ref_depend_map) &&
!(found_part_ref_or_null & keyuse->optimize))
{
keyparts++;
found_part_ref_or_null|= keyuse->optimize & ~KEY_OPTIMIZE_EQ;
}
}
if (keyparts > keyuse->keypart)
{
uint fldno;
if (is_hash_join_key_no(key))
fldno= keyuse->keypart;
else
fldno= table->key_info[key].key_part[keyparts-1].fieldnr - 1;
if (keyuse->val->const_item())
sel*= table->field[fldno]->cond_selectivity;
if (keyparts > 1)
{
ref_keyuse_steps[keyparts-2]= keyuse - prev_ref_keyuse;
prev_ref_keyuse= keyuse;
}
}
}
}
keyuse++;
} while (keyuse->table == table && keyuse->key == key);
}
for (Field **f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
{
if (!bitmap_is_set(read_set, field->field_index) ||
!field->next_equal_field)
continue;
for (Field *next_field= field->next_equal_field;
next_field != field;
next_field= next_field->next_equal_field)
{
if (!(next_field->table->map & rem_tables) && next_field->table != table)
{
sel/= field->cond_selectivity;
break;
}
}
}
sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables,
keyparts, ref_keyuse_steps);
return sel;
}
/**
Find a good, possibly optimal, query execution plan (QEP) by a possibly
exhaustive search.
@ -6966,6 +7219,8 @@ double JOIN::get_examined_rows()
@param prune_level pruning heuristics that should be applied during
optimization
(values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS)
@param use_cond_selectivity specifies how the selectivity of the conditions
pushed to a table should be taken into account
@retval
FALSE ok
@ -6980,7 +7235,8 @@ best_extension_by_limited_search(JOIN *join,
double record_count,
double read_time,
uint search_depth,
uint prune_level)
uint prune_level,
uint use_cond_selectivity)
{
DBUG_ENTER("best_extension_by_limited_search");
@ -7083,16 +7339,25 @@ best_extension_by_limited_search(JOIN *join,
}
}
double pushdown_cond_selectivity= 1.0;
if (use_cond_selectivity > 1)
pushdown_cond_selectivity= table_cond_selectivity(join, idx, s,
remaining_tables &
~real_table_bit);
join->positions[idx].cond_selectivity= pushdown_cond_selectivity;
double partial_join_cardinality= current_record_count *
pushdown_cond_selectivity;
if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) & allowed_tables )
{ /* Recursively expand the current partial plan */
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
if (best_extension_by_limited_search(join,
remaining_tables & ~real_table_bit,
idx + 1,
current_record_count,
partial_join_cardinality,
current_read_time,
search_depth - 1,
prune_level))
prune_level,
use_cond_selectivity))
DBUG_RETURN(TRUE);
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
}
@ -7110,7 +7375,7 @@ best_extension_by_limited_search(JOIN *join,
{
memcpy((uchar*) join->best_positions, (uchar*) join->positions,
sizeof(POSITION) * (idx + 1));
join->record_count= current_record_count;
join->record_count= partial_join_cardinality;
join->best_read= current_read_time - 0.001;
}
DBUG_EXECUTE("opt", print_plan(join, idx+1,
@ -7755,6 +8020,7 @@ get_best_combination(JOIN *join)
*/
SJ_MATERIALIZATION_INFO *sjm= cur_pos->table->emb_sj_nest->sj_mat_info;
j->records= j->records_read= (ha_rows)(sjm->is_sj_scan? sjm->rows : 1);
j->cond_selectivity= 1.0;
JOIN_TAB *jt;
JOIN_TAB_RANGE *jt_range;
if (!(jt= (JOIN_TAB*)join->thd->alloc(sizeof(JOIN_TAB)*sjm->tables)) ||
@ -7818,6 +8084,7 @@ get_best_combination(JOIN *join)
to access join->best_positions[].
*/
j->records_read= (ha_rows)join->best_positions[tablenr].records_read;
j->cond_selectivity= join->best_positions[tablenr].cond_selectivity;
join->map2table[j->table->tablenr]= j;
/* If we've reached the end of sjm nest, switch back to main sequence */
@ -11796,7 +12063,8 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
*/
static COND *build_equal_items_for_cond(THD *thd, COND *cond,
COND_EQUAL *inherited)
COND_EQUAL *inherited,
bool link_item_fields)
{
Item_equal *item_equal;
COND_EQUAL cond_equal;
@ -11843,6 +12111,7 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
List_iterator_fast<Item_equal> it(cond_equal.current_level);
while ((item_equal= it++))
{
item_equal->set_link_equal_fields(link_item_fields);
item_equal->fix_fields(thd, NULL);
item_equal->update_used_tables();
set_if_bigger(thd->lex->current_select->max_equal_elems,
@ -11862,7 +12131,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
while ((item= li++))
{
Item *new_item;
if ((new_item= build_equal_items_for_cond(thd, item, inherited)) != item)
if ((new_item= build_equal_items_for_cond(thd, item, inherited, FALSE))
!= item)
{
/* This replacement happens only for standalone equalities */
/*
@ -12025,14 +12295,15 @@ static COND *build_equal_items(JOIN *join, COND *cond,
COND_EQUAL *inherited,
List<TABLE_LIST> *join_list,
bool ignore_on_conds,
COND_EQUAL **cond_equal_ref)
COND_EQUAL **cond_equal_ref,
bool link_equal_fields)
{
THD *thd= join->thd;
COND_EQUAL *cond_equal= 0;
if (cond)
{
cond= build_equal_items_for_cond(thd, cond, inherited);
cond= build_equal_items_for_cond(thd, cond, inherited, link_equal_fields);
cond->update_used_tables();
if (cond->type() == Item::COND_ITEM &&
((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
@ -13548,9 +13819,10 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
static COND *
optimize_cond(JOIN *join, COND *conds,
optimize_cond(JOIN *join, COND *conds,
List<TABLE_LIST> *join_list, bool ignore_on_conds,
Item::cond_result *cond_value, COND_EQUAL **cond_equal)
Item::cond_result *cond_value, COND_EQUAL **cond_equal,
int flags)
{
THD *thd= join->thd;
DBUG_ENTER("optimize_cond");
@ -13573,9 +13845,10 @@ optimize_cond(JOIN *join, COND *conds,
multiple equality contains a constant.
*/
DBUG_EXECUTE("where", print_where(conds, "original", QT_ORDINARY););
conds= build_equal_items(join, conds, NULL, join_list, ignore_on_conds,
cond_equal);
DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY););
conds= build_equal_items(join, conds, NULL, join_list,
ignore_on_conds, cond_equal,
test(flags & OPT_LINK_EQUAL_FIELDS));
DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY););
/* change field = field to field = const for each found field = const */
propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
@ -14068,6 +14341,8 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
((Field_double *) new_field)->not_fixed= TRUE;
new_field->vcol_info= 0;
new_field->stored_in_db= TRUE;
new_field->cond_selectivity= 1.0;
new_field->next_equal_field= NULL;
}
return new_field;
}
@ -14412,6 +14687,9 @@ void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
bitmap_init(&table->eq_join_set,
(my_bitmap_map*) (bitmaps+ 3*bitmap_buffer_size(field_count)),
field_count, FALSE);
bitmap_init(&table->cond_set,
(my_bitmap_map*) (bitmaps+ 4*bitmap_buffer_size(field_count)),
field_count, FALSE);
/* write_set and all_set are copies of read_set */
table->def_write_set= table->def_read_set;
table->s->all_set= table->def_read_set;
@ -14575,7 +14853,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
&tmpname, (uint) strlen(path)+1,
&group_buff, (group && ! using_unique_constraint ?
param->group_length : 0),
&bitmaps, bitmap_buffer_size(field_count)*4,
&bitmaps, bitmap_buffer_size(field_count)*5,
NullS))
{
if (temp_pool_slot != MY_BIT_NONE)
@ -15330,7 +15608,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
&share, sizeof(*share),
&field, (field_count + 1) * sizeof(Field*),
&blob_field, (field_count+1) *sizeof(uint),
&bitmaps, bitmap_buffer_size(field_count)*4,
&bitmaps, bitmap_buffer_size(field_count)*5,
NullS))
return 0;
@ -22221,7 +22499,13 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
{
float f= 0.0;
if (examined_rows)
f= (float) (100.0 * tab->records_read / examined_rows);
{
double pushdown_cond_selectivity= tab->cond_selectivity;
if (pushdown_cond_selectivity == 1.0)
f= (float) (100.0 * tab->records_read / examined_rows);
else
f= (float) (100.0 * pushdown_cond_selectivity);
}
set_if_smaller(f, 100.0);
item_list.push_back(new Item_float(f, 2));
}

8
sql/sql_select.h

@ -292,6 +292,9 @@ typedef struct st_join_table {
/* psergey-todo: make the below have type double, like POSITION::records_read? */
ha_rows records_read;
/* The selectivity of the conditions that can be pushed to the table */
double cond_selectivity;
/* Startup cost for execution */
double startup_cost;
@ -772,6 +775,9 @@ typedef struct st_position :public Sql_alloc
*/
double records_read;
/* The selectivity of the pushed down conditions */
double cond_selectivity;
/*
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
@ -1820,6 +1826,8 @@ void eliminate_tables(JOIN *join);
/* Index Condition Pushdown entry point function */
void push_index_cond(JOIN_TAB *tab, uint keyno);
#define OPT_LINK_EQUAL_FIELDS 1
/****************************************************************************
Temporary table support for SQL Runtime
***************************************************************************/

596
sql/sql_statistics.cc

@ -26,6 +26,7 @@
#include "sql_base.h"
#include "key.h"
#include "sql_statistics.h"
#include "opt_range.h"
#include "my_atomic.h"
/*
@ -249,12 +250,13 @@ public:
and column_name with column_name taken out of the only parameter f of the
Field* type passed to this method. After this get_stat_values looks
for a row by the set key value. If the row is found the values of statistical
data columns min_value, max_value, nulls_ratio, avg_length, avg_frequency
are read into internal structures. Values of nulls_ratio, avg_length,
avg_frequency are read into the corresponding fields of the read_stat
structure from the Field object f, while values from min_value and max_value
are copied into the min_value and max_value record buffers attached to the
TABLE structure for table t.
data columns min_value, max_value, nulls_ratio, avg_length, avg_frequency,
hist_size, hist_type, histogram are read into internal structures. Values
of nulls_ratio, avg_length, avg_frequency, hist_size, hist_type, histogram
are read into the corresponding fields of the read_stat structure from
the Field object f, while values from min_value and max_value are copied
into the min_value and max_value record buffers attached to the TABLE
structure for table t.
If the value of a statistical column in the found row is null, then the
corresponding flag in the f->read_stat.column_stat_nulls bitmap is set off.
Otherwise the flag is set on. If no row is found for the column the all flags
@ -867,11 +869,12 @@ public:
@details
This implementation of a purely virtual method sets the value of the
columns 'min_value', 'max_value', 'nulls_ratio', 'avg_length' and
'avg_frequency' of the stistical table columns_stat according to the
contents of the bitmap write_stat.column_stat_nulls and the values
of the fields min_value, max_value, nulls_ratio, avg_length and
avg_frequency of the structure write_stat from the Field structure
columns 'min_value', 'max_value', 'nulls_ratio', 'avg_length',
'avg_frequency', 'hist_size', 'hist_type' and 'histogram' of the
stistical table columns_stat according to the contents of the bitmap
write_stat.column_stat_nulls and the values of the fields min_value,
max_value, nulls_ratio, avg_length, avg_frequency, hist_size, hist_type
and histogram of the structure write_stat from the Field structure
for the field 'table_field'.
The value of the k-th column in the table columns_stat is set to NULL
if the k-th bit in the bitmap 'column_stat_nulls' is set to 1.
@ -888,7 +891,7 @@ public:
char buff[MAX_FIELD_WIDTH];
String val(buff, sizeof(buff), &my_charset_utf8_bin);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_AVG_FREQUENCY; i++)
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++)
{
Field *stat_field= stat_table->field[i];
if (table_field->collected_stats->is_null(i))
@ -923,7 +926,21 @@ public:
break;
case COLUMN_STAT_AVG_FREQUENCY:
stat_field->store(table_field->collected_stats->get_avg_frequency());
break;
break;
case COLUMN_STAT_HIST_SIZE:
stat_field->store(table_field->collected_stats->histogram.get_size());
break;
case COLUMN_STAT_HIST_TYPE:
stat_field->store(table_field->collected_stats->histogram.get_type() +
1);
break;
case COLUMN_STAT_HISTOGRAM:
const char * col_histogram=
(const char *) (table_field->collected_stats->histogram.get_values());
stat_field->store(col_histogram,
table_field->collected_stats->histogram.get_size(),
&my_charset_bin);
break;
}
}
}
@ -936,14 +953,15 @@ public:
@details
This implementation of a purely virtual method first looks for a record
the statistical table column_stats by its primary key set the record
in the statistical table column_stats by its primary key set in the record
buffer with the help of Column_stat::set_key_fields. Then, if the row is
found, the function reads the values of the columns 'min_value',
'max_value', 'nulls_ratio', 'avg_length' and 'avg_frequency' of the
table column_stat and sets accordingly the value of the bitmap
read_stat.column_stat_nulls' and the values of the fields min_value,
max_value, nulls_ratio, avg_length and avg_frequency of the structure
read_stat from the Field structure for the field 'table_field'.
'max_value', 'nulls_ratio', 'avg_length', 'avg_frequency', 'hist_size' and
'hist_type" of the table column_stat and sets accordingly the value of
the bitmap read_stat.column_stat_nulls' and the values of the fields
min_value, max_value, nulls_ratio, avg_length, avg_frequency, hist_size and
hist_type of the structure read_stat from the Field structure for the field
'table_field'.
*/
void get_stat_values()
@ -960,7 +978,7 @@ public:
char buff[MAX_FIELD_WIDTH];
String val(buff, sizeof(buff), &my_charset_utf8_bin);
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_AVG_FREQUENCY; i++)
for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++)
{
Field *stat_field= stat_table->field[i];
@ -992,6 +1010,14 @@ public:
break;
case COLUMN_STAT_AVG_FREQUENCY:
table_field->read_stats->set_avg_frequency(stat_field->val_real());
break;
case COLUMN_STAT_HIST_SIZE:
table_field->read_stats->histogram.set_size(stat_field->val_int());
break;
case COLUMN_STAT_HIST_TYPE:
Histogram_type hist_type= (Histogram_type) (stat_field->val_int() -
1);
table_field->read_stats->histogram.set_type(hist_type);
break;
}
}
@ -999,6 +1025,37 @@ public:
}
}
/**
@brief
Read histogram from of column_stats
@details
This method first looks for a record in the statistical table column_stats
by its primary key set the record buffer with the help of
Column_stat::set_key_fields. Then, if the row is found, the function reads
the value of the column 'histogram' of the table column_stat and sets
accordingly the corresponding bit in the bitmap read_stat.column_stat_nulls.
The method assumes that the value of histogram size and the pointer to
the histogram location has been already set in the fields size and values
of read_stats->histogram.
*/
void get_histogram_value()
{
if (find_stat())
{
char buff[MAX_FIELD_WIDTH];
String val(buff, sizeof(buff), &my_charset_utf8_bin);
uint fldno= COLUMN_STAT_HISTOGRAM;
Field *stat_field= stat_table->field[fldno];
table_field->read_stats->set_not_null(fldno);
stat_field->val_str(&val);
memcpy(table_field->read_stats->histogram.get_values(),
val.ptr(), table_field->read_stats->histogram.get_size());
}
}
};
@ -1200,6 +1257,76 @@ public:
};
/*
Histogram_builder is a helper class that is used to build histograms
for columns
*/
class Histogram_builder
{
Field *column; /* table field for which the histogram is built */
uint col_length; /* size of this field */
ha_rows records; /* number of records the histogram is built for */
Field *min_value; /* pointer to the minimal value for the field */
Field *max_value; /* pointer to the maximal value for the field */
Histogram *histogram; /* the histogram location */
uint hist_width; /* the number of points in the histogram */
double bucket_capacity; /* number of rows in a bucket of the histogram */
uint curr_bucket; /* number of the current bucket to be built */
ulonglong count; /* number of values retrieved */
ulonglong count_distinct; /* number of distinct values retrieved */
public:
Histogram_builder(Field *col, uint col_len, ha_rows rows)
: column(col), col_length(col_len), records(rows)
{
Column_statistics *col_stats= col->collected_stats;
min_value= col_stats->min_value;
max_value= col_stats->max_value;
histogram= &col_stats->histogram;
hist_width= histogram->get_width();
bucket_capacity= (double) records / (hist_width + 1);
curr_bucket= 0;
count= 0;
count_distinct= 0;
}
ulonglong get_count_distinct() { return count_distinct; }
int next(void *elem, element_count elem_cnt)
{
count_distinct++;
count+= elem_cnt;
if (curr_bucket == hist_width)
return 0;
if (count > bucket_capacity * (curr_bucket + 1))
{
column->store_field_value((uchar *) elem, col_length);
histogram->set_value(curr_bucket,
column->pos_in_interval(min_value, max_value));
curr_bucket++;
while (curr_bucket != hist_width &&
count > bucket_capacity * (curr_bucket + 1))
{
histogram->set_prev_value(curr_bucket);
curr_bucket++;
}
}
return 0;
}
};
C_MODE_START
int histogram_build_walk(void *elem, element_count elem_cnt, void *arg)
{
Histogram_builder *hist_builder= (Histogram_builder *) arg;
return hist_builder->next(elem, elem_cnt);
}
C_MODE_END
/*
The class Count_distinct_field is a helper class used to calculate
@ -1220,6 +1347,8 @@ protected:
uint tree_key_length; /* The length of the keys for the elements of 'tree */
public:
Count_distinct_field() {}
/**
@param
@ -1238,28 +1367,11 @@ public:
Count_distinct_field(Field *field, uint max_heap_table_size)
{
qsort_cmp2 compare_key;
void* cmp_arg;
enum enum_field_types f_type= field->type();
table_field= field;
tree_key_length= field->pack_length();
if ((f_type == MYSQL_TYPE_VARCHAR) ||
(!field->binary() && (f_type == MYSQL_TYPE_STRING ||
f_type == MYSQL_TYPE_VAR_STRING)))
{
compare_key= (qsort_cmp2) simple_str_key_cmp;
cmp_arg= (void*) field;
}
else
{
cmp_arg= (void*) &tree_key_length;
compare_key= (qsort_cmp2) simple_raw_key_cmp;
}
tree= new Unique(compare_key, cmp_arg,
tree_key_length, max_heap_table_size);
tree= new Unique((qsort_cmp2) simple_str_key_cmp, (void*) field,
tree_key_length, max_heap_table_size, 1);
}
virtual ~Count_distinct_field()
@ -1299,9 +1411,48 @@ public:
tree->walk(table_field->table, count_distinct_walk, (void*) &count);
return count;
}
/*
@brief
Build the histogram for the elements accumulated in the container of 'tree'
*/
ulonglong get_value_with_histogram(ha_rows rows)
{
Histogram_builder hist_builder(table_field, tree_key_length, rows);
tree->walk(table_field->table, histogram_build_walk, (void *) &hist_builder);
return hist_builder.get_count_distinct();
}
/*
@brief
Get the size of the histogram in bytes built for table_field
*/
uint get_hist_size()
{
return table_field->collected_stats->histogram.get_size();
}
/*
@brief
Get the pointer to the histogram built for table_field
*/
uchar *get_histogram()
{
return table_field->collected_stats->histogram.get_values();
}
};
static
int simple_ulonglong_key_cmp(void* arg, uchar* key1, uchar* key2)
{
ulonglong *val1= (ulonglong *) key1;
ulonglong *val2= (ulonglong *) key2;
return *val1 > *val2 ? 1 : *val1 == *val2 ? 0 : -1;
}
/*
The class Count_distinct_field_bit is derived from the class
Count_distinct_field to be used only for fields of the MYSQL_TYPE_BIT type.
@ -1311,8 +1462,17 @@ public:
class Count_distinct_field_bit: public Count_distinct_field
{
public:
Count_distinct_field_bit(Field *field, uint max_heap_table_size)
:Count_distinct_field(field, max_heap_table_size) {}
{
table_field= field;
tree_key_length= sizeof(ulonglong);
tree= new Unique((qsort_cmp2) simple_ulonglong_key_cmp,
(void*) &tree_key_length,
tree_key_length, max_heap_table_size, 1);
}
bool add()
{
longlong val= table_field->val_int();
@ -1671,13 +1831,27 @@ int alloc_statistics_for_table(THD* thd, TABLE *table)
ulong *idx_avg_frequency= (ulong*) alloc_root(&table->mem_root,
sizeof(ulong) * key_parts);
if (!table_stats || !column_stats || !index_stats || !idx_avg_frequency)
uint columns= 0;
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
if (bitmap_is_set(table->read_set, (*field_ptr)->field_index))
columns++;
}
uint hist_size= thd->variables.histogram_size;
Histogram_type hist_type= (Histogram_type) (thd->variables.histogram_type);
uchar *histogram= NULL;
if (hist_size > 0)
histogram= (uchar *) alloc_root(&table->mem_root, hist_size * columns);
if (!table_stats || !column_stats || !index_stats || !idx_avg_frequency ||
(hist_size && !histogram))
DBUG_RETURN(1);
table->collected_stats= table_stats;
table_stats->column_stats= column_stats;
table_stats->index_stats= index_stats;
table_stats->idx_avg_frequency= idx_avg_frequency;
table_stats->histograms= histogram;
memset(column_stats, 0, sizeof(Column_statistics) * (fields+1));
@ -1686,6 +1860,13 @@ int alloc_statistics_for_table(THD* thd, TABLE *table)
(*field_ptr)->collected_stats= column_stats;
(*field_ptr)->collected_stats->max_value= NULL;
(*field_ptr)->collected_stats->min_value= NULL;
if (bitmap_is_set(table->read_set, (*field_ptr)->field_index))
{
column_stats->histogram.set_size(hist_size);
column_stats->histogram.set_type(hist_type);
column_stats->histogram.set_values(histogram);
histogram+= hist_size;
}
}
memset(idx_avg_frequency, 0, sizeof(ulong) * key_parts);
@ -1790,7 +1971,6 @@ inline bool statistics_for_command_is_needed(THD *thd)
@note
Currently the function always is called with the parameter is_safe set
to FALSE.
*/
int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share,
@ -1902,11 +2082,82 @@ int alloc_statistics_for_table_share(THD* thd, TABLE_SHARE *table_share,
if (!is_safe)
mysql_mutex_unlock(&table_share->LOCK_ha_data);
DBUG_RETURN(0);
}
/**
@brief
Allocate memory for the histogram used by a table share
@param
thd Thread handler
@param
table_share Table share for which the memory for histogram data is allocated
@param
is_safe TRUE <-> at any time only one thread can perform the function
@note
The function allocates the memory for the histogram built for a table in the
table's share memory with the intention to read the data there from the
system persistent statistical table mysql.column_stats,
The memory is allocated in the table_share's mem_root.
If the parameter is_safe is TRUE then it is guaranteed that at any given time
only one thread is executed the code of the function.
@retval
0 If the memory for all statistical data has been successfully allocated
@retval
1 Otherwise
@note
Currently the function always is called with the parameter is_safe set
to FALSE.
*/
static
int alloc_histograms_for_table_share(THD* thd, TABLE_SHARE *table_share,
bool is_safe)
{
TABLE_STATISTICS_CB *stats_cb= &table_share->stats_cb;
DBUG_ENTER("alloc_histograms_for_table_share");
if (!is_safe)
mysql_mutex_lock(&table_share->LOCK_ha_data);
if (stats_cb->histograms_can_be_read)
{
if (!is_safe)
mysql_mutex_unlock(&table_share->LOCK_ha_data);
DBUG_RETURN(0);
}
Table_statistics *table_stats= stats_cb->table_stats;
ulong total_hist_size= table_stats->total_hist_size;
if (total_hist_size && !table_stats->histograms)
{
uchar *histograms= (uchar *) alloc_root(&stats_cb->mem_root,
total_hist_size);
if (!histograms)
{
if (!is_safe)
mysql_mutex_unlock(&table_share->LOCK_ha_data);
DBUG_RETURN(1);
}
memset(histograms, 0, total_hist_size);
table_stats->histograms= histograms;
stats_cb->histograms_can_be_read= TRUE;
}
if (!is_safe)
mysql_mutex_unlock(&table_share->LOCK_ha_data);
DBUG_RETURN(0);
}
/**
@brief
Initialize the aggregation fields to collect statistics on a column
@ -2005,14 +2256,29 @@ void Column_statistics_collected::finish(ha_rows rows)
set_not_null(COLUMN_STAT_AVG_LENGTH);
}
if (count_distinct)
{
ulonglong distincts= count_distinct->get_value();
{
ulonglong distincts;
uint hist_size= count_distinct->get_hist_size();
if (hist_size == 0)
distincts= count_distinct->get_value();
else
distincts= count_distinct->get_value_with_histogram(rows - nulls);
if (distincts)
{
val= (double) (rows - nulls) / distincts;
set_avg_frequency(val);
set_not_null(COLUMN_STAT_AVG_FREQUENCY);
}
else
hist_size= 0;
histogram.set_size(hist_size);
set_not_null(COLUMN_STAT_HIST_SIZE);
if (hist_size && distincts)
{
set_not_null(COLUMN_STAT_HIST_TYPE);
histogram.set_values(count_distinct->get_histogram());
set_not_null(COLUMN_STAT_HISTOGRAM);
}
delete count_distinct;
count_distinct= NULL;
}
@ -2233,16 +2499,19 @@ int collect_statistics_for_table(THD *thd, TABLE *table)
table->collected_stats->cardinality= rows;
}
bitmap_clear_all(table->write_set);
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
table_field= *field_ptr;
if (!bitmap_is_set(table->read_set, table_field->field_index))
continue;
bitmap_set_bit(table->write_set, table_field->field_index);
if (!rc)
table_field->collected_stats->finish(rows);
else
table_field->collected_stats->cleanup();
}
bitmap_clear_all(table->write_set);
if (!rc)
{
@ -2420,6 +2689,7 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
Field **field_ptr;
KEY *key_info, *key_info_end;
TABLE_SHARE *table_share= table->s;
Table_statistics *read_stats= table_share->stats_cb.table_stats;
DBUG_ENTER("read_statistics_for_table");
@ -2431,16 +2701,18 @@ int read_statistics_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
/* Read statistics from the statistical table column_stats */
stat_table= stat_tables[COLUMN_STAT].table;
ulong total_hist_size= 0;
Column_stat column_stat(stat_table, table);
for (field_ptr= table_share->field; *field_ptr; field_ptr++)
{
table_field= *field_ptr;
column_stat.set_key_fields(table_field);
column_stat.get_stat_values();
total_hist_size+= table_field->read_stats->histogram.get_size();
}
read_stats->total_hist_size= total_hist_size;
/* Read statistics from the statistical table index_stats */
Table_statistics *read_stats= table_share->stats_cb.table_stats;
stat_table= stat_tables[INDEX_STAT].table;
Index_stat index_stat(stat_table, table);
for (key_info= table_share->key_info,
@ -2558,10 +2830,14 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
TABLE_SHARE *table_share= tl->table->s;
if (table_share &&
table_share->stats_cb.stats_can_be_read &&
!table_share->stats_cb.stats_is_read)
(!table_share->stats_cb.stats_is_read ||
(!table_share->stats_cb.histograms_are_read &&
thd->variables.optimizer_use_condition_selectivity > 3)))
return TRUE;
if (table_share->stats_cb.stats_is_read)
tl->table->stats_is_read= TRUE;
if (table_share->stats_cb.histograms_are_read)
tl->table->histograms_are_read= TRUE;
}
}
@ -2569,6 +2845,73 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
}
/**
@brief
Read histogram for a table from the persistent statistical tables
@param
thd The thread handle
@param
table The table to read histograms for
@param
stat_tables The array of TABLE_LIST objects for statistical tables
@details
For the statistical table columns_stats the function looks for the rows
from this table that contain statistical data on 'table'. If such rows
are found the histograms from them are read into the memory allocated
for histograms of 'table'. Later at the query processing these histogram
are supposed to be used by the optimizer.
The parameter stat_tables should point to an array of TABLE_LIST
objects for all statistical tables linked into a list. All statistical
tables are supposed to be opened.
The function is called by read_statistics_for_tables_if_needed().
@retval
0 If data has been successfully read for the table
@retval
1 Otherwise
@note
Objects of the helper Column_stat are employed read histogram
from the statistical table column_stats now.
*/
static
int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables)
{
TABLE_SHARE *table_share= table->s;
DBUG_ENTER("read_histograms_for_table");
if (!table_share->stats_cb.histograms_can_be_read)
{
(void) alloc_histograms_for_table_share(thd, table_share, FALSE);
}
if (table_share->stats_cb.histograms_can_be_read &&
!table_share->stats_cb.histograms_are_read)
{
Field **field_ptr;
uchar *histogram= table_share->stats_cb.table_stats->histograms;
TABLE *stat_table= stat_tables[COLUMN_STAT].table;
Column_stat column_stat(stat_table, table);
for (field_ptr= table_share->field; *field_ptr; field_ptr++)
{
Field *table_field= *field_ptr;
uint hist_size= table_field->read_stats->histogram.get_size();
if (hist_size)
{
column_stat.set_key_fields(table_field);
table_field->read_stats->histogram.set_values(histogram);
column_stat.get_histogram_value();
histogram+= hist_size;
}
}
}
DBUG_RETURN(0);
}
/**
@brief
Read statistics for tables from a table list if it is needed
@ -2596,7 +2939,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
TABLE_LIST stat_tables[STATISTICS_TABLES];
Open_tables_backup open_tables_backup;
DBUG_ENTER("read_statistics_for_table_if_needed");
DBUG_ENTER("read_statistics_for_tables_if_needed");
DEBUG_SYNC(thd, "statistics_read_start");
@ -2623,6 +2966,14 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
}
if (table_share->stats_cb.stats_is_read)
tl->table->stats_is_read= TRUE;
if (thd->variables.optimizer_use_condition_selectivity > 3 &&
table_share && !table_share->stats_cb.histograms_are_read)
{
(void) read_histograms_for_table(thd, tl->table, stat_tables);
table_share->stats_cb.histograms_are_read= TRUE;
}
if (table_share->stats_cb.stats_is_read)
tl->table->histograms_are_read= TRUE;
}
}
@ -3054,3 +3405,152 @@ void set_statistics_for_table(THD *thd, TABLE *table)
key_info->read_stats->get_avg_frequency(0) > 0.5);
}
}
/**
@brief
Get the average frequency for a column
@param
field The column whose average frequency is required
@retval
The required average frequency
*/
double get_column_avg_frequency(Field * field)
{
double res;
TABLE *table= field->table;
/*
Statistics is shared by table instances and is accessed through
the table share. If table->s->field is not set for 'table', then
no column statistics is available for the table .
*/
if (!table->s->field)
{
res= table->stat_records();
return res;
}
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;
}
/**
@brief
Estimate the number of rows in a column range using data from stat tables
@param
field The column whose range cardinality is to be estimated
@param
min_endp The left end of the range whose cardinality is required
@param
max_endp The right end of the range whose cardinality is required
@param
range_flag The range flags
@details
The function gets an estimate of the number of rows in a column range
using the statistical data from the table column_stats.
@retval
The required estimate of the rows in the column range
*/
double get_column_range_cardinality(Field *field,
key_range *min_endp,
key_range *max_endp,
uint range_flag)
{
double res;
TABLE *table= field->table;
Column_statistics *col_stats= table->field[field->field_index]->read_stats;
double tab_records= table->stat_records();
if (!col_stats)
return tab_records;
double col_nulls= tab_records * col_stats->get_nulls_ratio();
double col_non_nulls= tab_records - col_nulls;
bool nulls_incl= field->null_ptr && min_endp && min_endp->key[0] &&
!(range_flag & NEAR_MIN);
if (col_non_nulls < 1)
res= 0;
else if (min_endp && max_endp && min_endp->length == max_endp->length &&
!memcmp(min_endp->key, max_endp->key, min_endp->length))
{
if (nulls_incl)
{
/* This is null single point range */
res= col_nulls;
}
else
{
double avg_frequency= col_stats->get_avg_frequency();
res= avg_frequency;
if (avg_frequency > 1.0 + 0.000001 &&
col_stats->min_value && col_stats->max_value)
{
Histogram *hist= &col_stats->histogram;
if (hist->is_available())
{
double pos= field->pos_in_interval(col_stats->min_value,
col_stats->max_value);
res= col_non_nulls *
hist->point_selectivity(pos,
avg_frequency / col_non_nulls);
}
}
}
}
else
{
if (col_stats->min_value && col_stats->max_value)
{
double sel, min_mp_pos, max_mp_pos;
if (min_endp && !min_endp->key[0])
{
store_key_image_to_rec(field, (uchar *) min_endp->key,
min_endp->length);
min_mp_pos= field->pos_in_interval(col_stats->min_value,
col_stats->max_value);
}
else
min_mp_pos= 0.0;
if (max_endp)
{
store_key_image_to_rec(field, (uchar *) max_endp->key,
max_endp->length);
max_mp_pos= field->pos_in_interval(col_stats->min_value,
col_stats->max_value);
}
else
max_mp_pos= 1.0;
Histogram *hist= &col_stats->histogram;
if (!hist->is_available())
sel= (max_mp_pos - min_mp_pos);
else
sel= hist->range_selectivity(min_mp_pos, max_mp_pos);
res= col_non_nulls * sel;
set_if_bigger(res, col_stats->get_avg_frequency());
}
else
res= col_non_nulls;
if (nulls_incl)
res+= col_nulls;
}
return res;
}

194
sql/sql_statistics.h

@ -16,15 +16,6 @@
#ifndef SQL_STATISTICS_H
#define SQL_STATISTICS_H
/*
These enumeration types comprise the dictionary of three
statistical tables table_stat, column_stat and index_stat
as they defined in ../scripts/mysql_system_tables.sql.
It would be nice if the declarations of these types were
generated automatically by the table definitions.
*/
typedef
enum enum_use_stat_tables_mode
{
@ -33,6 +24,13 @@ enum enum_use_stat_tables_mode
PEFERABLY,
} Use_stat_tables_mode;
typedef
enum enum_histogram_type
{
SINGLE_PREC_HB,
DOUBLE_PREC_HB
} Histogram_type;
enum enum_stat_tables
{
TABLE_STAT,
@ -40,6 +38,16 @@ enum enum_stat_tables
INDEX_STAT,
};
/*
These enumeration types comprise the dictionary of three
statistical tables table_stat, column_stat and index_stat
as they defined in ../scripts/mysql_system_tables.sql.
It would be nice if the declarations of these types were
generated automatically by the table definitions.
*/
enum enum_table_stat_col
{
TABLE_STAT_DB_NAME,
@ -56,7 +64,10 @@ enum enum_column_stat_col
COLUMN_STAT_MAX_VALUE,
COLUMN_STAT_NULLS_RATIO,
COLUMN_STAT_AVG_LENGTH,
COLUMN_STAT_AVG_FREQUENCY
COLUMN_STAT_AVG_FREQUENCY,
COLUMN_STAT_HIST_SIZE,
COLUMN_STAT_HIST_TYPE,
COLUMN_STAT_HISTOGRAM
};
enum enum_index_stat_col
@ -90,6 +101,160 @@ int rename_column_in_stat_tables(THD *thd, TABLE *tab, Field *col,
const char *new_name);
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,
uint range_flag);
class Histogram
{
private:
Histogram_type type;
uint8 size;
uchar *values;
uint prec_factor()
{
switch (type) {
case SINGLE_PREC_HB:
return ((uint) (1 << 8) - 1);
case DOUBLE_PREC_HB:
return ((uint) (1 << 16) - 1);
}
return 1;
}
public:
uint get_width()
{
switch (type) {
case SINGLE_PREC_HB:
return size;
case DOUBLE_PREC_HB:
return size / 2;
}
return 0;
}
private:
uint get_value(uint i)
{
switch (type) {
case SINGLE_PREC_HB:
return (uint) (((uint8 *) values)[i]);
case DOUBLE_PREC_HB:
return (uint) (((uint16 *) values)[i]);
}
return 0;
}
uint find_bucket(double pos, bool first)
{
uint val= (uint) (pos * prec_factor());
int lp= 0;
int rp= get_width() - 1;
int d= get_width() / 2;
uint i= lp + d;
for ( ; d; d= (rp - lp) / 2, i= lp + d)
{
if (val == get_value(i))
break;
if (val < get_value(i))
rp= i;
else if (val > get_value(i + 1))
lp= i + 1;
else
break;
}
if (val == get_value(i))
{
if (first)
{
while(i && val == get_value(i - 1))
i--;
}
else
{
while(i + 1 < get_width() && val == get_value(i + 1))
i++;
}
}
return i;
}
public:
uint get_size() { return (uint) size; }
Histogram_type get_type() { return type; }
uchar *get_values() { return (uchar *) values; }
void set_size (ulonglong sz) { size= (uint8) sz; }
void set_type (Histogram_type t) { type= t; }
void set_values (uchar *vals) { values= (uchar *) vals; }
bool is_available() { return get_size() > 0 && get_values(); }
void set_value(uint i, double val)
{
switch (type) {
case SINGLE_PREC_HB:
((uint8 *) values)[i]= (uint8) (val * prec_factor());
return;
case DOUBLE_PREC_HB:
((uint16 *) values)[i]= (uint16) (val * prec_factor());
return;
}
}
void set_prev_value(uint i)
{
switch (type) {
case SINGLE_PREC_HB:
((uint8 *) values)[i]= ((uint8 *) values)[i-1];
return;
case DOUBLE_PREC_HB:
((uint16 *) values)[i]= ((uint16 *) values)[i-1];
return;
}
}
double range_selectivity(double min_pos, double max_pos)
{
double sel;
double bucket_sel= 1.0/(get_width() + 1);
uint min= find_bucket(min_pos, TRUE);
uint max= find_bucket(max_pos, FALSE);
sel= bucket_sel * (max - min + 1);
return sel;
}
double point_selectivity(double pos, double avg_sel)
{
double sel;
double bucket_sel= 1.0/(get_width() + 1);
uint min= find_bucket(pos, TRUE);
uint max= min;
while (max + 1 < get_width() && get_value(max + 1) == get_value(max))
max++;
double inv_prec_factor= (double) 1.0 / prec_factor();
double width= (max + 1 == get_width() ?
1.0 : get_value(max) * inv_prec_factor) -
(min == 0 ?
0.0 : get_value(min-1) * inv_prec_factor);
sel= avg_sel * (bucket_sel * (max + 1 - min)) / width;
return sel;
}
};
class Columns_statistics;
class Index_statistics;
@ -105,8 +270,9 @@ public:
uchar *min_max_record_buffers; /* Record buffers for min/max values */
Column_statistics *column_stats; /* Array of statistical data for columns */
Index_statistics *index_stats; /* Array of statistical data for indexes */
ulong *idx_avg_frequency; /* Array of records per key for index prefixes */
ulong *idx_avg_frequency; /* Array of records per key for index prefixes */
ulong total_hist_size; /* Total size of all histograms */
uchar *histograms; /* Sequence of histograms */
};
@ -161,10 +327,12 @@ private:
public:
Histogram histogram;
void set_all_nulls()
{
column_stat_nulls=
((1 << (COLUMN_STAT_AVG_FREQUENCY-COLUMN_STAT_COLUMN_NAME))-1) <<
((1 << (COLUMN_STAT_HISTOGRAM-COLUMN_STAT_COLUMN_NAME))-1) <<
(COLUMN_STAT_COLUMN_NAME+1);
}

37
sql/sys_vars.cc

@ -1533,6 +1533,25 @@ static Sys_var_ulong Sys_optimizer_prune_level(
SESSION_VAR(optimizer_prune_level), CMD_LINE(REQUIRED_ARG),
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 "
"the cardinality of a 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 "
"the cardinality of a partial join in any case, "
"3 - additionally always use selectivity of range conditions that are "
"not backed by any index to calculate the cardinality of a partial join, "
"4 - use histograms to calculate selectivity of range conditions that "
"are not backed by any index to calculate the cardinality of "
"a partial join.",
SESSION_VAR(optimizer_use_condition_selectivity), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1, 4), DEFAULT(1), BLOCK_SIZE(1));
/** Warns about deprecated value 63 */
static bool fix_optimizer_search_depth(sys_var *self, THD *thd,
enum_var_type type)
@ -3876,6 +3895,24 @@ static Sys_var_enum Sys_optimizer_use_stat_tables(
SESSION_VAR(use_stat_tables), CMD_LINE(REQUIRED_ARG),
use_stat_tables_modes, DEFAULT(0));
static Sys_var_ulong Sys_histogram_size(
"histogram_size",
"Number of bytes used for a histogram. "
"If set to 0, no histograms are created by ANALYZE.",
SESSION_VAR(histogram_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, 255), DEFAULT(0), BLOCK_SIZE(1));
const char *histogram_types[] =
{"SINGLE_PREC_HB", "DOUBLE_PREC_HB", 0};
static Sys_var_enum Sys_histogram_type(
"histogram_type",
"Specifies type of the histograms created by ANALYZE. "
"Possible values are: "
"SINGLE_PREC_HB - single precision height-balanced, "
"DOUBLE_PREC_HB - double precision height-balanced.",
SESSION_VAR(histogram_type), CMD_LINE(REQUIRED_ARG),
histogram_types, DEFAULT(0));
static Sys_var_mybool Sys_no_thread_alarm(
"debug_no_thread_alarm",
"Disable system thread alarm calls. Disabling it may be useful "

14
sql/table.cc

@ -425,6 +425,8 @@ void TABLE_SHARE::destroy()
free_root(&stats_cb.mem_root, MYF(0));
stats_cb.stats_can_be_read= FALSE;
stats_cb.stats_is_read= FALSE;
stats_cb.histograms_can_be_read= FALSE;
stats_cb.histograms_are_read= FALSE;
if (tmp_table == NO_TMP_TABLE)
mysql_mutex_unlock(&LOCK_ha_data);
@ -2749,7 +2751,7 @@ partititon_err:
/* Allocate bitmaps */
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;
bitmap_init(&outparam->def_read_set,
(my_bitmap_map*) bitmaps, share->fields, FALSE);
@ -2761,8 +2763,12 @@ partititon_err:
(my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields, FALSE);
bitmap_init(&outparam->eq_join_set,
(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->cond_selectivity= 1.0;
/* The table struct is now initialized; Open the table */
if (db_stat)
{
@ -3884,6 +3890,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
file->ha_start_of_new_statement();
reginfo.impossible_range= 0;
created= TRUE;
cond_selectivity= 1.0;
/* Catch wrong handling of the auto_increment_field_not_null. */
DBUG_ASSERT(!auto_increment_field_not_null);
@ -3892,6 +3899,11 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
pos_in_table_list= tl;
clear_column_bitmaps();
for (Field **f_ptr= field ; *f_ptr ; f_ptr++)
{
(*f_ptr)->next_equal_field= NULL;
(*f_ptr)->cond_selectivity= 1.0;
}
DBUG_ASSERT(key_read == 0);

8
sql/table.h

@ -586,7 +586,9 @@ struct TABLE_STATISTICS_CB
Table_statistics *table_stats; /* Structure to access the statistical data */
bool stats_can_be_read; /* Memory for statistical data is allocated */
bool stats_is_read; /* Statistical data for table has been read
from statistical tables */
from statistical tables */
bool histograms_can_be_read;
bool histograms_are_read;
};
@ -1107,6 +1109,7 @@ public:
my_bitmap_map *bitmap_init_value;
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 cond_set; /* used to mark fields from sargable conditions*/
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
@ -1159,6 +1162,8 @@ public:
*/
ha_rows quick_condition_rows;
double cond_selectivity;
table_map map; /* ID bit of table (1,2,4,8,16...) */
uint lock_position; /* Position in MYSQL_LOCK.table */
@ -1278,6 +1283,7 @@ public:
#endif
uint max_keys; /* Size of allocated key_info array. */
bool stats_is_read; /* Persistent statistics is read for the table */
bool histograms_are_read;
MDL_ticket *mdl_ticket;
void init(THD *thd, TABLE_LIST *tl);

40
sql/uniques.cc

@ -86,6 +86,7 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
full_size= size;
if (min_dupl_count_arg)
full_size+= sizeof(element_count);
with_counters= test(min_dupl_count_arg);
my_b_clear(&file);
init_tree(&tree, (ulong) (max_in_memory_size / 16), 0, size, comp_func,
NULL, comp_func_fixed_arg, MYF(MY_THREAD_SPECIFIC));
@ -428,6 +429,22 @@ static int buffpek_compare(void *arg, uchar *key_ptr1, uchar *key_ptr2)
C_MODE_END
inline
element_count get_counter_from_merged_element(void *ptr, uint ofs)
{
element_count cnt;
memcpy((uchar *) &cnt, (uchar *) ptr + ofs, sizeof(element_count));
return cnt;
}
inline
void put_counter_into_merged_element(void *ptr, uint ofs, element_count cnt)
{
memcpy((uchar *) ptr + ofs, (uchar *) &cnt, sizeof(element_count));
}
/*
DESCRIPTION
@ -457,6 +474,8 @@ C_MODE_END
file file with all trees dumped. Trees in the file
must contain sorted unique values. Cache must be
initialized in read mode.
with counters take into account counters for equal merged
elements
RETURN VALUE
0 ok
<> 0 error
@ -466,7 +485,7 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
uint key_length, BUFFPEK *begin, BUFFPEK *end,
tree_walk_action walk_action, void *walk_action_arg,
qsort_cmp2 compare, void *compare_arg,
IO_CACHE *file)
IO_CACHE *file, bool with_counters)
{
BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg };
QUEUE queue;
@ -485,6 +504,8 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
uint bytes_read; /* to hold return value of read_to_buffer */
BUFFPEK *top;
int res= 1;
uint cnt_ofs= key_length - (with_counters ? sizeof(element_count) : 0);
element_count cnt;
/*
Invariant: queue must contain top element from each tree, until a tree
is not completely walked through.
@ -543,9 +564,17 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
/* new top has been obtained; if old top is unique, apply the action */
if (compare(compare_arg, old_key, top->key))
{
if (walk_action(old_key, 1, walk_action_arg))
cnt= with_counters ?
get_counter_from_merged_element(old_key, cnt_ofs) : 1;
if (walk_action(old_key, cnt, walk_action_arg))
goto end;
}
else if (with_counters)
{
cnt= get_counter_from_merged_element(top->key, cnt_ofs);
cnt+= get_counter_from_merged_element(old_key, cnt_ofs);
put_counter_into_merged_element(top->key, cnt_ofs, cnt);
}
}
/*
Applying walk_action to the tail of the last tree: this is safe because
@ -556,7 +585,10 @@ static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
{
do
{
if (walk_action(top->key, 1, walk_action_arg))
cnt= with_counters ?
get_counter_from_merged_element(top->key, cnt_ofs) : 1;
if (walk_action(top->key, cnt, walk_action_arg))
goto end;
top->key+= key_length;
}
@ -620,7 +652,7 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg)
(BUFFPEK *) file_ptrs.buffer,
(BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
action, walk_action_arg,
tree.compare, tree.custom_arg, &file);
tree.compare, tree.custom_arg, &file, with_counters);
}
my_free(merge_buffer);
return res;

Loading…
Cancel
Save