diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2022-01-19 18:35:27 +0300 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2022-01-19 18:35:27 +0300 |
commit | da78030ec87e30d2218a0de182ffb87fc541da97 (patch) | |
tree | 7f7ce9bb818d56679eaf034b52f05738b8d83da1 | |
parent | e222e44d1bfc995870430bb90d8ac97e91f66cb4 (diff) | |
parent | ce4956f3229a8b2c26a4913fdbc190b5c822cb8e (diff) | |
download | mariadb-git-preview-10.8-MDEV-26519-json-histograms.tar.gz |
Merge MDEV-26519: JSON_HB histograms into 10.8preview-10.8-MDEV-26519-json-histograms
51 files changed, 11232 insertions, 439 deletions
diff --git a/include/json_lib.h b/include/json_lib.h index 6d802860cff..853c4a6f7fa 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -373,6 +373,9 @@ int json_find_paths_first(json_engine_t *je, json_find_paths_t *state, int json_find_paths_next(json_engine_t *je, json_find_paths_t *state); +#define JSON_ERROR_OUT_OF_SPACE (-1) +#define JSON_ERROR_ILLEGAL_SYMBOL (-2) + /* Converst JSON string constant into ordinary string constant which can involve unpacking json escapes and changing character set. @@ -385,10 +388,13 @@ int json_unescape(CHARSET_INFO *json_cs, uchar *res, uchar *res_end); /* - Converst ordinary string constant into JSON string constant. - which can involve appropriate escaping and changing character set. - Returns negative integer in the case of an error, - the length of the result otherwise. + Convert a string constant into JSON string constant. + This can involve appropriate escaping and changing the character set. + Returns the length of the result on success, + on error returns a negative error code. + Some error codes: + JSON_ERROR_OUT_OF_SPACE Not enough space in the provided buffer + JSON_ERROR_ILLEGAL_SYMBOL Source symbol cannot be represented in JSON */ int json_escape(CHARSET_INFO *str_cs, const uchar *str, const uchar *str_end, CHARSET_INFO *json_cs, uchar *json, uchar *json_end); diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index afa1edff421..cacaaae9a6d 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -138,6 +138,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/opt_trace.cc ../sql/xa.cc ../sql/json_table.cc + ../sql/opt_histogram_json.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index 4788fbb7ff6..49fb03ecc57 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -118,6 +118,7 @@ binlog-direct-non-transactional-updates default-storage-engine=myisam use_stat_tables=preferably +histogram_type=json_hb loose-ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem loose-ssl-cert=@ENV.MYSQL_TEST_DIR/std_data/server-cert.pem diff --git a/mysql-test/include/histogram_replaces.inc b/mysql-test/include/histogram_replaces.inc new file mode 100644 index 00000000000..4cea1b05709 --- /dev/null +++ b/mysql-test/include/histogram_replaces.inc @@ -0,0 +1 @@ +--source include/json_hb_histogram.inc diff --git a/mysql-test/include/json_hb_histogram.inc b/mysql-test/include/json_hb_histogram.inc new file mode 100644 index 00000000000..0820fb5fccb --- /dev/null +++ b/mysql-test/include/json_hb_histogram.inc @@ -0,0 +1,3 @@ +# Remove non-deterministic parts of JSON_HB histogram + +--replace_regex /("(collected_at|collected_by)": )"[^"]*"/\1"REPLACED"/ diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 3b7de95118b..88c82e25b7f 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -18387,7 +18387,7 @@ explain extended select t2.a,t2.b,t2.c,t.c as t_c,t.max,t.min from t2, t3, (select c, max(b) max, min(b) min from t4 group by c) t where t2.b < 40 and t2.a=t3.a and t3.c=t.c; id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 90 63.28 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 90 60.00 Using where 1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 1 100.00 Using where 1 PRIMARY <derived2> ref key0 key0 128 test.t3.c 10 100.00 2 DERIVED t4 ALL idx_c NULL NULL NULL 160 100.00 Using temporary; Using filesort @@ -18406,7 +18406,7 @@ EXPLAIN "table_name": "t2", "access_type": "ALL", "rows": 90, - "filtered": 63.28125, + "filtered": 60, "attached_condition": "t2.b < 40 and t2.a is not null" } }, @@ -18910,7 +18910,7 @@ explain extended select * from t2, t3, (select c, b, sum(b) over (partition by c) from t4 ) t where t2.b < 40 and t2.a=t3.a and t3.c=t.c; id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 90 63.28 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 90 60.00 Using where 1 PRIMARY t3 ref idx_a idx_a 5 test.t2.a 1 100.00 Using where 1 PRIMARY <derived2> ref key0 key0 128 test.t3.c 10 100.00 2 DERIVED t4 ALL idx_c NULL NULL NULL 160 100.00 Using temporary @@ -18929,7 +18929,7 @@ EXPLAIN "table_name": "t2", "access_type": "ALL", "rows": 90, - "filtered": 63.28125, + "filtered": 60, "attached_condition": "t2.b < 40 and t2.a is not null" } }, diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result index c7164fcc74c..3195ec79c2d 100644 --- a/mysql-test/main/group_min_max.result +++ b/mysql-test/main/group_min_max.result @@ -2080,19 +2080,19 @@ id select_type table type possible_keys key key_len ref rows Extra explain extended select a1,a2,min(b),max(b) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 276 99.22 Using where; Using index +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 276 98.44 Using where; Using index Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,min(`test`.`t1`.`b`) AS `min(b)`,max(`test`.`t1`.`b`) AS `max(b)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2` explain extended select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 512 40.43 Using where; Using temporary; Using filesort +1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 512 26.95 Using where; Using temporary; Using filesort Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,min(`test`.`t1`.`c`) AS `min(c)`,max(`test`.`t1`.`c`) AS `max(c)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b` explain extended select a1,a2,b,c from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 512 40.43 Using where; Using temporary; Using filesort +1 SIMPLE t1 ALL idx_t1_0,idx_t1_1,idx_t1_2 NULL NULL NULL 512 26.95 Using where; Using temporary; Using filesort Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`,`test`.`t1`.`c` explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1; @@ -2100,7 +2100,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL idx_t2_1 163 NULL 548 Using where; Using index explain extended select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 276 99.22 Using where; Using index +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 276 98.44 Using where; Using index Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b` explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1; diff --git a/mysql-test/main/join_cache.result b/mysql-test/main/join_cache.result index 36e045dc2bd..359739fecf8 100644 --- a/mysql-test/main/join_cache.result +++ b/mysql-test/main/join_cache.result @@ -6220,7 +6220,7 @@ EXPLAIN "key_length": "10", "used_key_parts": ["kp1", "kp2"], "rows": 836, - "filtered": 76.43428802, + "filtered": 76, "index_condition": "b.kp2 <= 10", "attached_condition": "b.kp2 <= 10 and b.col1 + 1 < 33333" }, diff --git a/mysql-test/main/join_outer.result b/mysql-test/main/join_outer.result index fcffeb6d161..522b668e07b 100644 --- a/mysql-test/main/join_outer.result +++ b/mysql-test/main/join_outer.result @@ -2795,7 +2795,7 @@ test.t3 analyze status OK explain extended select * from t1 left join t3 on t1.a=t3.b and t3.a<5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 -1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 1.96 Using where +1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 0.50 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t1` left join `test`.`t3` on(`test`.`t3`.`b` = `test`.`t1`.`a` and `test`.`t3`.`a` < 5) where 1 # t3.filtered must less than 100%, too: @@ -2803,7 +2803,7 @@ explain extended select * from t1 left join (t3 join t2) on t1.a=t3.b and t3.a<5 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 -1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 1.96 Using where +1 SIMPLE t3 ALL NULL NULL NULL NULL 1000 0.50 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t2`.`a` AS `a` from `test`.`t1` left join (`test`.`t3` join `test`.`t2`) on(`test`.`t3`.`b` = `test`.`t1`.`a` and `test`.`t3`.`a` < 5) where 1 drop table t1,t2,t3; diff --git a/mysql-test/main/join_outer_jcl6.result b/mysql-test/main/join_outer_jcl6.result index 721989c3368..b579cfc6ac0 100644 --- a/mysql-test/main/join_outer_jcl6.result +++ b/mysql-test/main/join_outer_jcl6.result @@ -2802,7 +2802,7 @@ test.t3 analyze status OK explain extended select * from t1 left join t3 on t1.a=t3.b and t3.a<5; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 -1 SIMPLE t3 hash_ALL NULL #hash#$hj 5 test.t1.a 1000 1.96 Using where; Using join buffer (flat, BNLH join) +1 SIMPLE t3 hash_ALL NULL #hash#$hj 5 test.t1.a 1000 0.50 Using where; Using join buffer (flat, BNLH join) Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b` from `test`.`t1` left join `test`.`t3` on(`test`.`t3`.`b` = `test`.`t1`.`a` and `test`.`t3`.`a` < 5 and `test`.`t1`.`a` is not null) where 1 # t3.filtered must less than 100%, too: @@ -2810,7 +2810,7 @@ explain extended select * from t1 left join (t3 join t2) on t1.a=t3.b and t3.a<5 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10 100.00 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join) -1 SIMPLE t3 hash_ALL NULL #hash#$hj 5 test.t1.a 1000 1.96 Using where; Using join buffer (incremental, BNLH join) +1 SIMPLE t3 hash_ALL NULL #hash#$hj 5 test.t1.a 1000 0.50 Using where; Using join buffer (incremental, BNLH join) Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t2`.`a` AS `a` from `test`.`t1` left join (`test`.`t3` join `test`.`t2`) on(`test`.`t3`.`b` = `test`.`t1`.`a` and `test`.`t3`.`a` < 5 and `test`.`t1`.`a` is not null) where 1 drop table t1,t2,t3; diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index a8aa461c863..d2799d6e009 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -368,7 +368,8 @@ The following specify which files/extra groups are read (specified before remain 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. + height-balanced, JSON_HB - height-balanced, stored as + JSON. --host-cache-size=# How many host names should be cached to avoid resolving. (Automatically configured unless set explicitly) --idle-readonly-transaction-timeout=# diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index 255aad4450b..0d16f47dc8f 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -2091,12 +2091,12 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 { { "column_name": "a", "ranges": ["1 <= a <= 1"], - "selectivity_from_histogram": 0.1796875 + "selectivity_from_histogram": 0.181 }, { "column_name": "b", "ranges": ["2 <= b <= 2"], - "selectivity_from_histogram": 0.015625 + "selectivity_from_histogram": 0.021 } ], "cond_selectivity": 0.021 @@ -8083,20 +8083,20 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) { "access_type": "scan", - "resulting_rows": 5.9375, - "cost": 2.829589844, + "resulting_rows": 5, + "cost": 3.017089844, "chosen": true } ], "chosen_access_method": { "type": "scan", - "records": 5.9375, - "cost": 2.829589844, + "records": 5, + "cost": 3.017089844, "uses_join_buffering": false } }, - "rows_for_plan": 5.9375, + "rows_for_plan": 5, "cost_for_plan": 4.017089844, "rest_of_plan": [ @@ -8114,22 +8114,22 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) { "access_type": "scan", - "resulting_rows": 804.6875, - "cost": 256.8548584, + "resulting_rows": 800, + "cost": 220.9863281, "chosen": true } ], "chosen_access_method": { "type": "scan", - "records": 804.6875, - "cost": 256.8548584, + "records": 800, + "cost": 220.9863281, "uses_join_buffering": false } }, - "rows_for_plan": 4777.832031, - "cost_for_plan": 1216.438354, - "estimated_join_cardinality": 4777.832031 + "rows_for_plan": 4000, + "cost_for_plan": 1025.003418, + "estimated_join_cardinality": 4000 } ] }, @@ -8146,20 +8146,20 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) { "access_type": "scan", - "resulting_rows": 804.6875, - "cost": 43.25976562, + "resulting_rows": 800, + "cost": 44.19726562, "chosen": true } ], "chosen_access_method": { "type": "scan", - "records": 804.6875, - "cost": 43.25976562, + "records": 800, + "cost": 44.19726562, "uses_join_buffering": false } }, - "rows_for_plan": 804.6875, + "rows_for_plan": 800, "cost_for_plan": 204.1972656, "pruned_by_heuristic": true } @@ -8230,8 +8230,8 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) { "access_type": "scan", - "resulting_rows": 804.6875, - "cost": 43.25976562, + "resulting_rows": 800, + "cost": 44.19726562, "chosen": false } ], @@ -8245,8 +8245,8 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) }, "rows_for_plan": 10, "cost_for_plan": 26.02294779, - "selectivity": 0.8046875, - "estimated_join_cardinality": 8.046875 + "selectivity": 0.8, + "estimated_join_cardinality": 8 } ] }, @@ -8263,20 +8263,20 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.considered_execution_plans')) { "access_type": "scan", - "resulting_rows": 804.6875, - "cost": 43.25976562, + "resulting_rows": 800, + "cost": 44.19726562, "chosen": true } ], "chosen_access_method": { "type": "scan", - "records": 804.6875, - "cost": 43.25976562, + "records": 800, + "cost": 44.19726562, "uses_join_buffering": false } }, - "rows_for_plan": 804.6875, + "rows_for_plan": 800, "cost_for_plan": 204.1972656, "pruned_by_cost": true } @@ -8564,7 +8564,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN EXTENDED SELECT * from t1 WHERE a between 1 and 5 and b <= 5; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 100 0.22 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 0.25 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` between 1 and 5 and `test`.`t1`.`b` <= 5 select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; @@ -8579,7 +8579,7 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) [ "1 <= a <= 5" ], - "selectivity_from_histogram": 0.046875 + "selectivity_from_histogram": 0.05 }, { @@ -8588,13 +8588,13 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) [ "NULL < b <= 5" ], - "selectivity_from_histogram": 0.046875 + "selectivity_from_histogram": 0.05 } ] ] EXPLAIN EXTENDED SELECT * from t1 WHERE a != 5; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 99.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` <> 5 select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; @@ -8610,13 +8610,13 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) "NULL < a < 5", "5 < a" ], - "selectivity_from_histogram": 1 + "selectivity_from_histogram": 0.99 } ] ] EXPLAIN EXTENDED SELECT * from t1 WHERE b >= 10 and b < 25; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 100 15.62 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 15.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` >= 10 and `test`.`t1`.`b` < 25 select JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; @@ -8631,7 +8631,7 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.selectivity_for_columns')) [ "10 <= b < 25" ], - "selectivity_from_histogram": 0.15625 + "selectivity_from_histogram": 0.15 } ] ] diff --git a/mysql-test/main/partition.result b/mysql-test/main/partition.result index 58d0464b86f..a5d84072d11 100644 --- a/mysql-test/main/partition.result +++ b/mysql-test/main/partition.result @@ -2741,7 +2741,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p1,p2 ALL NULL NULL NULL NULL 400 Using where explain extended select * from t2 where b=5; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 19.61 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 0.10 Using where Warnings: Note 1003 select `test`.`t2`.`part_key` AS `part_key`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where `test`.`t2`.`b` = 5 explain partitions select * from t2 where b=5; @@ -2749,7 +2749,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2,p3,p4 ALL NULL NULL NULL NULL 1000 Using where explain extended select * from t2 partition(p0) where b=1; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 200 19.61 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 200 20.00 Using where Warnings: Note 1003 select `test`.`t2`.`part_key` AS `part_key`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` PARTITION (`p0`) where `test`.`t2`.`b` = 1 set @@use_stat_tables= @save_use_stat_tables; diff --git a/mysql-test/main/selectivity.result b/mysql-test/main/selectivity.result index 40ab309fffd..003b91a6a28 100644 --- a/mysql-test/main/selectivity.result +++ b/mysql-test/main/selectivity.result @@ -1245,8 +1245,8 @@ EXPLAIN EXTENDED SELECT * FROM language, country, continent WHERE country_group = lang_group AND lang_group IS NULL; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE country ALL NULL NULL NULL NULL 2 0.00 Using where -1 SIMPLE language ALL NULL NULL NULL NULL 6 0.00 Using where; Using join buffer (flat, BNL join) +1 SIMPLE country ALL NULL NULL NULL NULL 2 50.00 Using where +1 SIMPLE language ALL NULL NULL NULL NULL 6 16.67 Using where; Using join buffer (flat, BNL join) 1 SIMPLE continent ALL NULL NULL NULL NULL 6 100.00 Using join buffer (incremental, BNL join) Warnings: Note 1003 select `test`.`language`.`lang_group` AS `lang_group`,`test`.`language`.`lang` AS `lang`,`test`.`country`.`code` AS `code`,`test`.`country`.`country_group` AS `country_group`,`test`.`continent`.`cont_group` AS `cont_group`,`test`.`continent`.`cont` AS `cont` from `test`.`language` join `test`.`country` join `test`.`continent` where `test`.`language`.`lang_group` = `test`.`country`.`country_group` and `test`.`country`.`country_group` is null @@ -1372,14 +1372,14 @@ test.t2 analyze status Table is already up to date explain extended select * from t1 straight_join t2 where t1.a=t2.a and t1.a<10; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.96 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.00 Using where 1 SIMPLE t2 ref a a 5 test.t1.a 10 100.00 Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` straight_join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 10 explain extended select * from t1 straight_join t2 where t1.a=t2.a and t2.a<10; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.96 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.00 Using where 1 SIMPLE t2 ref a a 5 test.t1.a 10 100.00 Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` straight_join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 10 @@ -1649,12 +1649,12 @@ test.t1 analyze status Table is already up to date # Check what info the optimizer has about selectivities explain extended select * from t1 use index () where a in (17,51,5); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 3.90 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 2.90 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where `test`.`t1`.`a` in (17,51,5) explain extended select * from t1 use index () where b=2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 5.47 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 5.90 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where `test`.`t1`.`b` = 2 # Now, the equality is used for ref access, while the range condition @@ -1895,7 +1895,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN EXTENDED SELECT * from t1 where t1.a >= 81; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 3 66.41 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 66.67 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` >= 81 SELECT HEX(a), b from t1 where t1.a >= 81; @@ -1919,7 +1919,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 5 39.84 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 40.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 2 SET optimizer_use_condition_selectivity=3; diff --git a/mysql-test/main/selectivity_innodb.result b/mysql-test/main/selectivity_innodb.result index 5457db21436..8db83c6bcaf 100644 --- a/mysql-test/main/selectivity_innodb.result +++ b/mysql-test/main/selectivity_innodb.result @@ -1257,8 +1257,8 @@ EXPLAIN EXTENDED SELECT * FROM language, country, continent WHERE country_group = lang_group AND lang_group IS NULL; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE country ALL NULL NULL NULL NULL 2 0.00 Using where -1 SIMPLE language ALL NULL NULL NULL NULL 6 0.00 Using where; Using join buffer (flat, BNL join) +1 SIMPLE country ALL NULL NULL NULL NULL 2 50.00 Using where +1 SIMPLE language ALL NULL NULL NULL NULL 6 16.67 Using where; Using join buffer (flat, BNL join) 1 SIMPLE continent ALL NULL NULL NULL NULL 6 100.00 Using join buffer (incremental, BNL join) Warnings: Note 1003 select `test`.`language`.`lang_group` AS `lang_group`,`test`.`language`.`lang` AS `lang`,`test`.`country`.`code` AS `code`,`test`.`country`.`country_group` AS `country_group`,`test`.`continent`.`cont_group` AS `cont_group`,`test`.`continent`.`cont` AS `cont` from `test`.`language` join `test`.`country` join `test`.`continent` where `test`.`language`.`lang_group` = `test`.`country`.`country_group` and `test`.`country`.`country_group` is null @@ -1384,14 +1384,14 @@ test.t2 analyze status OK explain extended select * from t1 straight_join t2 where t1.a=t2.a and t1.a<10; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.96 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.00 Using where 1 SIMPLE t2 ref a a 5 test.t1.a 10 100.00 Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` straight_join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 10 explain extended select * from t1 straight_join t2 where t1.a=t2.a and t2.a<10; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.96 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1.00 Using where 1 SIMPLE t2 ref a a 5 test.t1.a 10 100.00 Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` straight_join `test`.`t2` where `test`.`t2`.`a` = `test`.`t1`.`a` and `test`.`t1`.`a` < 10 @@ -1661,12 +1661,12 @@ test.t1 analyze status OK # Check what info the optimizer has about selectivities explain extended select * from t1 use index () where a in (17,51,5); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 3.90 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 2.90 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where `test`.`t1`.`a` in (17,51,5) explain extended select * from t1 use index () where b=2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 5.47 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 5.90 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` USE INDEX () where `test`.`t1`.`b` = 2 # Now, the equality is used for ref access, while the range condition @@ -1907,7 +1907,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN EXTENDED SELECT * from t1 where t1.a >= 81; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 3 66.41 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 66.67 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` >= 81 SELECT HEX(a), b from t1 where t1.a >= 81; @@ -1931,7 +1931,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=2; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 5 39.84 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 40.00 Using where Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 2 SET optimizer_use_condition_selectivity=3; diff --git a/mysql-test/main/statistics.result b/mysql-test/main/statistics.result index 1ba087dd7a1..43b28f464e1 100644 --- a/mysql-test/main/statistics.result +++ b/mysql-test/main/statistics.result @@ -1,9 +1,12 @@ +set @SINGLE_PREC_TYPE='single_prec_hb'; +set @DOUBLE_PREC_TYPE='double_prec_hb'; +set @DEFAULT_HIST_TYPE='double_prec_hb'; drop table if exists t1,t2; set @save_use_stat_tables=@@use_stat_tables; set @save_histogram_size=@@global.histogram_size; set @@global.histogram_size=0,@@local.histogram_size=0; -set @save_hist_type=@@histogram_type; -set histogram_type='single_prec_hb'; +set @save_hist_type=@DEFAULT_HIST_TYPE; +set histogram_type=@SINGLE_PREC_TYPE; DELETE FROM mysql.table_stats; DELETE FROM mysql.column_stats; DELETE FROM mysql.index_stats; @@ -220,18 +223,19 @@ 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 001919FF -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 +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 0 49 0.0000 1.0000 4 SINGLE_PREC_HB 0.180,0.204,0.247,0.184,0.184 +test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 4 SINGLE_PREC_HB 0.000,0.247,0.502,0.251,0.000 +test t1 c aaaa dddddddd 0.1250 7.0000 4 SINGLE_PREC_HB 0.000,0.333,0.333,0.333,0.000 +test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 4 SINGLE_PREC_HB 0.000,0.098,0.000,0.902,0.000 +test t1 e 0.01 0.112 0.2250 6.2000 4 SINGLE_PREC_HB 0.000,0.020,0.373,0.490,0.118 +test t1 f 1 5 0.2000 6.4000 4 SINGLE_PREC_HB 0.247,0.251,0.251,0.000,0.251 DELETE FROM mysql.column_stats; set histogram_size=8; -set histogram_type='DOUBLE_PREC_HB'; +set histogram_type=@DOUBLE_PREC_TYPE; ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected @@ -239,18 +243,19 @@ 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 0000031A031AFFFF -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 +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 0 49 0.0000 1.0000 8 DOUBLE_PREC_HB 0.18367,0.20407,0.24489,0.18367,0.18369 +test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 8 DOUBLE_PREC_HB 0.00000,0.24999,0.50001,0.25000,0.00000 +test t1 c aaaa dddddddd 0.1250 7.0000 8 DOUBLE_PREC_HB 0.00000,0.33333,0.33333,0.33333,0.00000 +test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 8 DOUBLE_PREC_HB 0.00000,0.10161,0.00000,0.89839,0.00000 +test t1 e 0.01 0.112 0.2250 6.2000 8 DOUBLE_PREC_HB 0.00000,0.01961,0.37255,0.49020,0.11765 +test t1 f 1 5 0.2000 6.4000 8 DOUBLE_PREC_HB 0.24999,0.25000,0.25000,0.00000,0.25000 DELETE FROM mysql.column_stats; set histogram_size= 0; -set histogram_type='single_prec_hb'; +set histogram_type=@SINGLE_PREC_TYPE; ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected @@ -1476,13 +1481,13 @@ WORLD_INNODB COUNTRYLANGUAGE Percentage 1 2.7640 use world; set use_stat_tables='preferably'; set histogram_size=100; -set histogram_type='SINGLE_PREC_HB'; +set histogram_type=@SINGLE_PREC_TYPE; ANALYZE TABLE CountryLanguage; set histogram_size=254; -set histogram_type='DOUBLE_PREC_HB'; +set histogram_type=@DOUBLE_PREC_TYPE; ANALYZE TABLE City; FLUSH TABLES; -select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,hex(histogram),decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='COUNTRYLANGUAGE' and UPPER(column_name) = 'PERCENTAGE';; +select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='COUNTRYLANGUAGE' and UPPER(column_name) = 'PERCENTAGE';; UPPER(db_name) WORLD UPPER(table_name) COUNTRYLANGUAGE UPPER(column_name) PERCENTAGE @@ -1493,9 +1498,8 @@ avg_length 4.0000 avg_frequency 2.7640 hist_size 100 hist_type SINGLE_PREC_HB -hex(histogram) 0000000000000000000000000101010101010101010202020303030304040404050505050606070707080809090A0A0B0C0D0D0E0E0F10111213131415161718191B1C1E202224292A2E33373B4850575F6A76818C9AA7B9C4CFDADFE5EBF0F4F8FAFCFF decode_histogram(hist_type,histogram) 0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.004,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.004,0.000,0.000,0.004,0.000,0.000,0.000,0.004,0.000,0.000,0.000,0.004,0.000,0.000,0.000,0.004,0.000,0.004,0.000,0.000,0.004,0.000,0.004,0.000,0.004,0.000,0.004,0.004,0.004,0.000,0.004,0.000,0.004,0.004,0.004,0.004,0.004,0.000,0.004,0.004,0.004,0.004,0.004,0.004,0.008,0.004,0.008,0.008,0.008,0.008,0.020,0.004,0.016,0.020,0.016,0.016,0.051,0.031,0.027,0.031,0.043,0.047,0.043,0.043,0.055,0.051,0.071,0.043,0.043,0.043,0.020,0.024,0.024,0.020,0.016,0.016,0.008,0.008,0.012,0.000 -select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,hex(histogram),decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='CITY' and UPPER(column_name) = 'POPULATION';; +select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='CITY' and UPPER(column_name) = 'POPULATION';; UPPER(db_name) WORLD UPPER(table_name) CITY UPPER(column_name) POPULATION @@ -1506,9 +1510,8 @@ avg_length 4.0000 avg_frequency 1.0467 hist_size 254 hist_type DOUBLE_PREC_HB -hex(histogram) 1F00A1002B023002350238023F02430249024E02520258025D02630268026E02720276027B02800285028C02920297029D02A102A802AC02B402BC02C402CC02D302DA02E302EA02F102F802010305030C03120319031F03290333033D0343034F03590363036D037803840390039A03A603B303C303D103E003F203020412042404330440045304600472047F049104A204B804C804DE04F2040A0526053F0558056F058E05B305D905F4051306380667068406AB06DA06020731075C079407C507F8072E085E08A508DF0824096909CC092E0A760AD50A400BA90B150CAD0C310D240E130F0E103B11B9126B14F0166B192F1CB71FFF240630483FC567 decode_histogram(hist_type,histogram) 0.00047,0.00198,0.00601,0.00008,0.00008,0.00005,0.00011,0.00006,0.00009,0.00008,0.00006,0.00009,0.00008,0.00009,0.00008,0.00009,0.00006,0.00006,0.00008,0.00008,0.00008,0.00011,0.00009,0.00008,0.00009,0.00006,0.00011,0.00006,0.00012,0.00012,0.00012,0.00012,0.00011,0.00011,0.00014,0.00011,0.00011,0.00011,0.00014,0.00006,0.00011,0.00009,0.00011,0.00009,0.00015,0.00015,0.00015,0.00009,0.00018,0.00015,0.00015,0.00015,0.00017,0.00018,0.00018,0.00015,0.00018,0.00020,0.00024,0.00021,0.00023,0.00027,0.00024,0.00024,0.00027,0.00023,0.00020,0.00029,0.00020,0.00027,0.00020,0.00027,0.00026,0.00034,0.00024,0.00034,0.00031,0.00037,0.00043,0.00038,0.00038,0.00035,0.00047,0.00056,0.00058,0.00041,0.00047,0.00056,0.00072,0.00044,0.00060,0.00072,0.00061,0.00072,0.00066,0.00085,0.00075,0.00078,0.00082,0.00073,0.00108,0.00089,0.00105,0.00105,0.00151,0.00150,0.00110,0.00145,0.00163,0.00160,0.00165,0.00232,0.00201,0.00371,0.00365,0.00383,0.00459,0.00583,0.00662,0.00984,0.00969,0.01080,0.01379,0.02063,0.04308,0.05960,0.15816,0.59464 -set histogram_type='single_prec_hb'; +set histogram_type=@SINGLE_PREC_TYPE; set histogram_size=0; use test; DROP DATABASE world; @@ -1575,10 +1578,11 @@ 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 +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 1 3 0.0000 1.0000 10 SINGLE_PREC_HB 0.000,0.000,0.000,0.498,0.000,0.000,0.000,0.502,0.000,0.000,0.000 set histogram_size=default; drop table t1; # @@ -1588,7 +1592,7 @@ drop table t1; create table t1 ( a int); insert into t1 values (1),(2),(3),(4),(5); set histogram_size=10; -set histogram_type='double_prec_hb'; +set histogram_type=@DOUBLE_PREC_TYPE; show variables like 'histogram%'; Variable_name Value histogram_size 10 @@ -1600,12 +1604,13 @@ 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 +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 1 5 0.0000 1.0000 10 DOUBLE_PREC_HB 0.00000,0.24999,0.25000,0.25000,0.25000,0.00000 set histogram_size=0; -set histogram_type='single_prec_hb'; +set histogram_type=@SINGLE_PREC_TYPE; drop table t1; # # Bug mdev-4369: histogram for a column with many distinct values @@ -1641,10 +1646,10 @@ 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) +hist_size, hist_type, decode_histogram(hist_type,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 +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t2 id 1 1024 0.0000 8.0000 63 SINGLE_PREC_HB 0.012,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016,0.016 set histogram_size=0; drop table t1, t2; set use_stat_tables=@save_use_stat_tables; @@ -1662,9 +1667,9 @@ Level Code Message select db_name, table_name, column_name, HEX(min_value), HEX(max_value), nulls_ratio, avg_frequency, -hist_size, hist_type, HEX(histogram) +hist_size, hist_type, decode_histogram(hist_type,histogram) FROM mysql.column_stats; -db_name table_name column_name HEX(min_value) HEX(max_value) nulls_ratio avg_frequency hist_size hist_type HEX(histogram) +db_name table_name column_name HEX(min_value) HEX(max_value) nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) test t1 a D879626AF872675F73E662F8 D879626AF872675F73E662F8 0.0000 1.0000 0 NULL NULL drop table t1; # @@ -1760,12 +1765,12 @@ set use_stat_tables=@save_use_stat_tables; # # MDEV-10134 Add full support for DEFAULT # -CREATE TABLE t1 (a BLOB, b TEXT DEFAULT DECODE_HISTOGRAM('SINGLE_PREC_HB',a)); +CREATE TABLE t1 (a BLOB, b TEXT DEFAULT DECODE_HISTOGRAM(@SINGLE_PREC_TYPE,a)); SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` blob DEFAULT NULL, - `b` text DEFAULT decode_histogram('SINGLE_PREC_HB',`a`) + `b` text DEFAULT decode_histogram(@`SINGLE_PREC_TYPE`,`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 INSERT INTO t1 (a) VALUES (0x0000000000000000000000000101010101010101010202020303030304040404050505050606070707080809090A0A0B0C0D0D0E0E0F10111213131415161718191B1C1E202224292A2E33373B4850575F6A76818C9AA7B9C4CFDADFE5EBF0F4F8FAFCFF); SELECT b FROM t1; @@ -1878,6 +1883,7 @@ t1 id 1 17384 0.0000 4.0000 14.0000 0.15705,0.15711,0.21463,0.15705,0.15711,0.15 explain select * from t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 229376 +drop table t0; drop table t1; set analyze_sample_percentage=@save_analyze_sample_percentage; set histogram_size=@save_histogram_size; diff --git a/mysql-test/main/statistics.test b/mysql-test/main/statistics.test index 1f99aaa33e5..1d431237e82 100644 --- a/mysql-test/main/statistics.test +++ b/mysql-test/main/statistics.test @@ -1,3 +1,13 @@ +set @SINGLE_PREC_TYPE='single_prec_hb'; +set @DOUBLE_PREC_TYPE='double_prec_hb'; +set @DEFAULT_HIST_TYPE='double_prec_hb'; + +if ($histogram_type_override) { + eval set @SINGLE_PREC_TYPE=$histogram_type_override; + eval set @DOUBLE_PREC_TYPE=$histogram_type_override; + eval set @DEFAULT_HIST_TYPE=$histogram_type_override; +} + --source include/have_stat_tables.inc --source include/have_innodb.inc --disable_warnings @@ -7,8 +17,8 @@ drop table if exists t1,t2; set @save_use_stat_tables=@@use_stat_tables; set @save_histogram_size=@@global.histogram_size; set @@global.histogram_size=0,@@local.histogram_size=0; -set @save_hist_type=@@histogram_type; -set histogram_type='single_prec_hb'; +set @save_hist_type=@DEFAULT_HIST_TYPE; +set histogram_type=@SINGLE_PREC_TYPE; DELETE FROM mysql.table_stats; --sorted_result @@ -81,6 +91,7 @@ SELECT * FROM mysql.index_stats; SELECT COUNT(*) FROM t1; + SELECT * FROM mysql.column_stats WHERE db_name='test' AND table_name='t1' AND column_name='a'; SELECT MIN(t1.a), MAX(t1.a), @@ -177,30 +188,32 @@ DELETE FROM mysql.column_stats; set histogram_size=4; ANALYZE TABLE t1; ---sorted_result +--source include/histogram_replaces.inc 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; + hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; DELETE FROM mysql.column_stats; set histogram_size=8; -set histogram_type='DOUBLE_PREC_HB'; +set histogram_type=@DOUBLE_PREC_TYPE; ANALYZE TABLE t1; ---sorted_result +--source include/histogram_replaces.inc 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; + hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; DELETE FROM mysql.column_stats; set histogram_size= 0; -set histogram_type='single_prec_hb'; +set histogram_type=@SINGLE_PREC_TYPE; ANALYZE TABLE t1; @@ -650,18 +663,20 @@ use world; set use_stat_tables='preferably'; --disable_result_log set histogram_size=100; -set histogram_type='SINGLE_PREC_HB'; +set histogram_type=@SINGLE_PREC_TYPE; ANALYZE TABLE CountryLanguage; set histogram_size=254; -set histogram_type='DOUBLE_PREC_HB'; +set histogram_type=@DOUBLE_PREC_TYPE; ANALYZE TABLE City; FLUSH TABLES; --enable_result_log ---query_vertical select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,hex(histogram),decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='COUNTRYLANGUAGE' and UPPER(column_name) = 'PERCENTAGE'; ---query_vertical select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,hex(histogram),decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='CITY' and UPPER(column_name) = 'POPULATION'; +--source include/histogram_replaces.inc +--query_vertical select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='COUNTRYLANGUAGE' and UPPER(column_name) = 'PERCENTAGE'; +--source include/histogram_replaces.inc +--query_vertical select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='CITY' and UPPER(column_name) = 'POPULATION'; -set histogram_type='single_prec_hb'; +set histogram_type=@SINGLE_PREC_TYPE; set histogram_size=0; use test; @@ -705,11 +720,13 @@ set histogram_size=10; analyze table t1 persistent for all; +--source include/histogram_replaces.inc 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; + hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; set histogram_size=default; @@ -724,20 +741,22 @@ create table t1 ( a int); insert into t1 values (1),(2),(3),(4),(5); set histogram_size=10; -set histogram_type='double_prec_hb'; +set histogram_type=@DOUBLE_PREC_TYPE; show variables like 'histogram%'; analyze table t1 persistent for all; +--source include/histogram_replaces.inc 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; + hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; set histogram_size=0; -set histogram_type='single_prec_hb'; +set histogram_type=@SINGLE_PREC_TYPE; drop table t1; @@ -774,10 +793,11 @@ set histogram_size=63; analyze table t2 persistent for all; +--source include/histogram_replaces.inc select db_name, table_name, column_name, min_value, max_value, nulls_ratio, avg_frequency, - hist_size, hist_type, HEX(histogram) + hist_size, hist_type, decode_histogram(hist_type,histogram) FROM mysql.column_stats; set histogram_size=0; @@ -795,10 +815,11 @@ insert into t1 values(unhex('D879626AF872675F73E662F8')); analyze table t1 persistent for all; show warnings; +--source include/histogram_replaces.inc select db_name, table_name, column_name, HEX(min_value), HEX(max_value), nulls_ratio, avg_frequency, - hist_size, hist_type, HEX(histogram) + hist_size, hist_type, decode_histogram(hist_type,histogram) FROM mysql.column_stats; drop table t1; @@ -908,11 +929,14 @@ set use_stat_tables=@save_use_stat_tables; --echo # MDEV-10134 Add full support for DEFAULT --echo # -CREATE TABLE t1 (a BLOB, b TEXT DEFAULT DECODE_HISTOGRAM('SINGLE_PREC_HB',a)); +# disable for JSON histograms +if (!$histogram_type_override) { +CREATE TABLE t1 (a BLOB, b TEXT DEFAULT DECODE_HISTOGRAM(@SINGLE_PREC_TYPE,a)); SHOW CREATE TABLE t1; INSERT INTO t1 (a) VALUES (0x0000000000000000000000000101010101010101010202020303030304040404050505050606070707080809090A0A0B0C0D0D0E0E0F10111213131415161718191B1C1E202224292A2E33373B4850575F6A76818C9AA7B9C4CFDADFE5EBF0F4F8FAFCFF); SELECT b FROM t1; DROP TABLE t1; +} --echo # --echo # End of 10.2 tests @@ -959,6 +983,7 @@ INSERT INTO t1 SELECT id+9192 FROM t1; --echo # This query will should show a full table scan analysis. --echo # ANALYZE TABLE t1; +--source include/histogram_replaces.inc select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, DECODE_HISTOGRAM(hist_type, histogram) from mysql.column_stats; @@ -969,6 +994,7 @@ set analyze_sample_percentage=0.1; --echo # This query will show an innacurate avg_frequency value. --echo # ANALYZE TABLE t1; +--source include/histogram_replaces.inc select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, DECODE_HISTOGRAM(hist_type, histogram) from mysql.column_stats; @@ -978,6 +1004,7 @@ from mysql.column_stats; --echo # set analyze_sample_percentage=25; ANALYZE TABLE t1; +--source include/histogram_replaces.inc select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, DECODE_HISTOGRAM(hist_type, histogram) from mysql.column_stats; @@ -988,6 +1015,7 @@ set analyze_sample_percentage=0; --echo # Test self adjusting sampling level. --echo # ANALYZE TABLE t1; +--source include/histogram_replaces.inc select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, DECODE_HISTOGRAM(hist_type, histogram) from mysql.column_stats; @@ -999,12 +1027,13 @@ explain select * from t1; set analyze_sample_percentage=100; ANALYZE TABLE t1; +--source include/histogram_replaces.inc select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, DECODE_HISTOGRAM(hist_type, histogram) from mysql.column_stats; explain select * from t1; - +drop table t0; drop table t1; set analyze_sample_percentage=@save_analyze_sample_percentage; set histogram_size=@save_histogram_size; diff --git a/mysql-test/main/statistics_json.result b/mysql-test/main/statistics_json.result new file mode 100644 index 00000000000..a9740056777 --- /dev/null +++ b/mysql-test/main/statistics_json.result @@ -0,0 +1,8324 @@ +# +# Test that we can store JSON arrays in histogram field mysql.column_stats when histogram_type=JSON +# +set @SINGLE_PREC_TYPE='single_prec_hb'; +set @DOUBLE_PREC_TYPE='double_prec_hb'; +set @DEFAULT_HIST_TYPE='double_prec_hb'; +set @SINGLE_PREC_TYPE='JSON_HB'; +set @DOUBLE_PREC_TYPE='JSON_HB'; +set @DEFAULT_HIST_TYPE='JSON_HB'; +drop table if exists t1,t2; +set @save_use_stat_tables=@@use_stat_tables; +set @save_histogram_size=@@global.histogram_size; +set @@global.histogram_size=0,@@local.histogram_size=0; +set @save_hist_type=@DEFAULT_HIST_TYPE; +set histogram_type=@SINGLE_PREC_TYPE; +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; +set use_stat_tables='preferably'; +CREATE TABLE t1 ( +a int NOT NULL PRIMARY KEY, +b varchar(32), +c char(16), +d date, +e double, +f bit(3), +INDEX idx1 (b, e), +INDEX idx2 (c, d), +INDEX idx3 (d), +INDEX idx4 (e, b, d) +) ENGINE= MYISAM; +INSERT INTO t1 VALUES +(0, NULL, NULL, NULL, NULL, NULL), +(7, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'dddddddd', '1990-05-15', 0.1, b'100'), +(17, 'vvvvvvvvvvvvv', 'aaaa', '1989-03-12', 0.01, b'101'), +(1, 'vvvvvvvvvvvvv', NULL, '1989-03-12', 0.01, b'100'), +(12, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd', '1999-07-23', 0.112, b'001'), +(23, 'vvvvvvvvvvvvv', 'dddddddd', '1999-07-23', 0.1, b'100'), +(8, 'vvvvvvvvvvvvv', 'aaaa', '1999-07-23', 0.1, b'100'), +(22, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'aaaa', '1989-03-12', 0.112, b'001'), +(31, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'aaaa', '1999-07-23', 0.01, b'001'), +(10, NULL, 'aaaa', NULL, 0.01, b'010'), +(5, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd', '1999-07-23', 0.1, b'100'), +(15, 'vvvvvvvvvvvvv', 'ccccccccc', '1990-05-15', 0.1, b'010'), +(30, NULL, 'bbbbbb', NULL, NULL, b'100'), +(38, 'zzzzzzzzzzzzzzzzzz', 'bbbbbb', NULL, NULL, NULL), +(18, 'zzzzzzzzzzzzzzzzzz', 'ccccccccc', '1990-05-15', 0.01, b'010'), +(9, 'yyy', 'bbbbbb', '1998-08-28', 0.01, NULL), +(29, 'vvvvvvvvvvvvv', 'dddddddd', '1999-07-23', 0.012, b'010'), +(3, 'yyy', 'dddddddd', '1990-05-15', 0.112, b'010'), +(39, 'zzzzzzzzzzzzzzzzzz', 'bbbbbb', NULL, 0.01, b'100'), +(14, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'ccccccccc', '1990-05-15', 0.1, b'100'), +(40, 'zzzzzzzzzzzzzzzzzz', 'bbbbbb', '1989-03-12', NULL, NULL), +(44, NULL, 'aaaa', '1989-03-12', NULL, b'010'), +(19, 'vvvvvvvvvvvvv', 'ccccccccc', '1990-05-15', 0.012, b'011'), +(21, 'zzzzzzzzzzzzzzzzzz', 'dddddddd', '1989-03-12', 0.112, b'100'), +(45, NULL, NULL, '1989-03-12', NULL, b'011'), +(2, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'ccccccccc', '1990-05-15', 0.1, b'001'), +(35, 'yyy', 'aaaa', '1990-05-15', 0.05, b'011'), +(4, 'vvvvvvvvvvvvv', 'dddddddd', '1999-07-23', 0.01, b'101'), +(47, NULL, 'aaaa', '1990-05-15', 0.05, b'010'), +(42, NULL, 'ccccccccc', '1989-03-12', 0.01, b'010'), +(32, NULL, 'bbbbbb', '1990-05-15', 0.01, b'011'), +(49, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww' , 'aaaa', '1990-05-15', NULL, NULL), +(43, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww' , 'bbbbbb', '1990-05-15', NULL, b'100'), +(37, 'yyy', NULL, '1989-03-12', 0.05, b'011'), +(41, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'ccccccccc', '1990-05-15', 0.05, NULL), +(34, 'yyy', NULL, NULL, NULL, NULL), +(33, 'zzzzzzzzzzzzzzzzzz', 'dddddddd', '1989-03-12', 0.05, b'011'), +(24, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd', '1990-05-15', 0.01, b'101'), +(11, 'yyy', 'ccccccccc', '1999-07-23', 0.1, NULL), +(25, 'zzzzzzzzzzzzzzzzzz', 'bbb', '1989-03-12', 0.01, b'101'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +SELECT COUNT(*) FROM t1; +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 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)", +(SELECT COUNT(t1.a) FROM t1) / +(SELECT COUNT(DISTINCT t1.a) FROM t1) AS "AVG_FREQUENCY(t1.a)" +FROM t1; +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 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)", +(SELECT COUNT(t1.b) FROM t1) / +(SELECT COUNT(DISTINCT t1.b) FROM t1) AS "AVG_FREQUENCY(t1.b)" +FROM t1; +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 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)", +(SELECT COUNT(t1.c) FROM t1) / +(SELECT COUNT(DISTINCT t1.c) FROM t1) AS "AVG_FREQUENCY(t1.c)" +FROM t1; +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 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)", +(SELECT COUNT(t1.d) FROM t1) / +(SELECT COUNT(DISTINCT t1.d) FROM t1) AS "AVG_FREQUENCY(t1.d)" +FROM t1; +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 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)", +(SELECT COUNT(t1.e) FROM t1) / +(SELECT COUNT(DISTINCT t1.e) FROM t1) AS "AVG_FREQUENCY(t1.e)" +FROM t1; +MIN(t1.e) MAX(t1.e) NULLS_RATIO(t1.e) AVG_FREQUENCY(t1.e) +0.01 0.112 0.2250 6.2000 +SELECT * FROM mysql.index_stats +WHERE db_name='test' AND table_name='t1' AND index_name='idx1'; +db_name table_name index_name prefix_arity avg_frequency +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +SELECT +(SELECT COUNT(*) FROM t1 WHERE t1.b IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.b) FROM t1 WHERE t1.b IS NOT NULL) +AS 'ARITY 1', +(SELECT COUNT(*) FROM t1 WHERE t1.b IS NOT NULL AND t1.e IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.b, t1.e) FROM t1 +WHERE t1.b IS NOT NULL AND t1.e IS NOT NULL) +AS 'ARITY 2'; +ARITY 1 ARITY 2 +6.4000 1.6875 +SELECT * FROM mysql.index_stats +WHERE db_name='test' AND table_name='t1' AND index_name='idx2'; +db_name table_name index_name prefix_arity avg_frequency +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +SELECT +(SELECT COUNT(*) FROM t1 WHERE t1.c IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.c) FROM t1 WHERE t1.c IS NOT NULL) +AS 'ARITY 1', +(SELECT COUNT(*) FROM t1 WHERE t1.c IS NOT NULL AND t1.d IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.c, t1.d) FROM t1 +WHERE t1.c IS NOT NULL AND t1.d IS NOT NULL) +AS 'ARITY 2'; +ARITY 1 ARITY 2 +7.0000 2.3846 +SELECT * FROM mysql.index_stats +WHERE db_name='test' AND table_name='t1' AND index_name='idx3'; +db_name table_name index_name prefix_arity avg_frequency +test t1 idx3 1 8.5000 +SELECT +(SELECT COUNT(*) FROM t1 WHERE t1.d IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.d) FROM t1 WHERE t1.d IS NOT NULL) +AS 'ARITY 1'; +ARITY 1 +8.5000 +SELECT * FROM mysql.index_stats +WHERE db_name='test' AND table_name='t1' AND index_name='idx4'; +db_name table_name index_name prefix_arity avg_frequency +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +SELECT +(SELECT COUNT(*) FROM t1 WHERE t1.e IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.e) FROM t1 WHERE t1.e IS NOT NULL) +AS 'ARITY 1', +(SELECT COUNT(*) FROM t1 WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.e, t1.b) FROM t1 +WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL) +AS 'ARITY 2', +(SELECT COUNT(*) FROM t1 +WHERE t1.e IS NOT NULL AND t1.b IS NOT NULL AND t1.d IS NOT NULL) / +(SELECT COUNT(DISTINCT t1.e, t1.b, t1.d) FROM t1 +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 Engine-independent statistics collected +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, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 0 49 0.0000 1.0000 4 JSON_HB { + "target_histogram_size": 4, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0", + "size": 0.275, + "ndv": 11 + }, + { + "start": "12", + "size": 0.275, + "ndv": 11 + }, + { + "start": "29", + "size": 0.275, + "ndv": 11 + }, + { + "start": "41", + "end": "49", + "size": 0.175, + "ndv": 7 + } + ] +} +test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 4 JSON_HB { + "target_histogram_size": 4, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "vvvvvvvvvvvvv", + "size": 0.28125, + "ndv": 2 + }, + { + "start": "wwwwwwwwwwwwwwwwwwwwwwwwwwww", + "size": 0.28125, + "ndv": 2 + }, + { + "start": "xxxxxxxxxxxxxxxxxxxxxxxxxx", + "size": 0.28125, + "ndv": 3 + }, + { + "start": "zzzzzzzzzzzzzzzzzz", + "end": "zzzzzzzzzzzzzzzzzz", + "size": 0.15625, + "ndv": 1 + } + ] +} +test t1 c aaaa dddddddd 0.1250 7.0000 4 JSON_HB { + "target_histogram_size": 4, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "aaaa", + "size": 0.257142857, + "ndv": 1 + }, + { + "start": "bbb", + "size": 0.257142857, + "ndv": 3 + }, + { + "start": "ccccccccc", + "size": 0.257142857, + "ndv": 2 + }, + { + "start": "dddddddd", + "end": "dddddddd", + "size": 0.228571429, + "ndv": 1 + } + ] +} +test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 3 JSON_HB { + "target_histogram_size": 4, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1989-03-12", + "size": 0.323529412, + "ndv": 1 + }, + { + "start": "1990-05-15", + "size": 0.411764706, + "ndv": 1 + }, + { + "start": "1998-08-28", + "end": "1999-07-23", + "size": 0.264705882, + "ndv": 2 + } + ] +} +test t1 e 0.01 0.112 0.2250 6.2000 4 JSON_HB { + "target_histogram_size": 4, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0.01", + "size": 0.387096774, + "ndv": 1 + }, + { + "start": "0.012", + "size": 0.258064516, + "ndv": 3 + }, + { + "start": "0.1", + "size": 0.258064516, + "ndv": 2 + }, + { + "start": "0.112", + "end": "0.112", + "size": 0.096774194, + "ndv": 1 + } + ] +} +test t1 f 1 5 0.2000 6.4000 4 JSON_HB { + "target_histogram_size": 4, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start_hex": "01", + "size": 0.28125, + "ndv": 2 + }, + { + "start_hex": "02", + "size": 0.28125, + "ndv": 2 + }, + { + "start_hex": "04", + "size": 0.3125, + "ndv": 1 + }, + { + "start_hex": "05", + "end_hex": "05", + "size": 0.125, + "ndv": 1 + } + ] +} +DELETE FROM mysql.column_stats; +set histogram_size=8; +set histogram_type=@DOUBLE_PREC_TYPE; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +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, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 0 49 0.0000 1.0000 7 JSON_HB { + "target_histogram_size": 8, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0", + "size": 0.15, + "ndv": 6 + }, + { + "start": "7", + "size": 0.15, + "ndv": 6 + }, + { + "start": "14", + "size": 0.15, + "ndv": 6 + }, + { + "start": "22", + "size": 0.15, + "ndv": 6 + }, + { + "start": "31", + "size": 0.15, + "ndv": 6 + }, + { + "start": "38", + "size": 0.15, + "ndv": 6 + }, + { + "start": "44", + "end": "49", + "size": 0.1, + "ndv": 4 + } + ] +} +test t1 b vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 6.4000 5 JSON_HB { + "target_histogram_size": 8, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "vvvvvvvvvvvvv", + "size": 0.25, + "ndv": 1 + }, + { + "start": "wwwwwwwwwwwwwwwwwwwwwwwwwwww", + "size": 0.21875, + "ndv": 1 + }, + { + "start": "xxxxxxxxxxxxxxxxxxxxxxxxxx", + "size": 0.125, + "ndv": 1 + }, + { + "start": "yyy", + "size": 0.1875, + "ndv": 1 + }, + { + "start": "zzzzzzzzzzzzzzzzzz", + "end": "zzzzzzzzzzzzzzzzzz", + "size": 0.21875, + "ndv": 1 + } + ] +} +test t1 c aaaa dddddddd 0.1250 7.0000 5 JSON_HB { + "target_histogram_size": 8, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "aaaa", + "size": 0.257142857, + "ndv": 1 + }, + { + "start": "bbb", + "size": 0.142857143, + "ndv": 2 + }, + { + "start": "bbbbbb", + "size": 0.085714286, + "ndv": 1 + }, + { + "start": "ccccccccc", + "size": 0.228571429, + "ndv": 1 + }, + { + "start": "dddddddd", + "end": "dddddddd", + "size": 0.285714286, + "ndv": 1 + } + ] +} +test t1 d 1989-03-12 1999-07-23 0.1500 8.5000 4 JSON_HB { + "target_histogram_size": 8, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1989-03-12", + "size": 0.323529412, + "ndv": 1 + }, + { + "start": "1990-05-15", + "size": 0.411764706, + "ndv": 1 + }, + { + "start": "1998-08-28", + "size": 0.147058824, + "ndv": 2 + }, + { + "start": "1999-07-23", + "end": "1999-07-23", + "size": 0.117647059, + "ndv": 1 + } + ] +} +test t1 e 0.01 0.112 0.2250 6.2000 5 JSON_HB { + "target_histogram_size": 8, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0.01", + "size": 0.387096774, + "ndv": 1 + }, + { + "start": "0.012", + "size": 0.129032258, + "ndv": 2 + }, + { + "start": "0.05", + "size": 0.096774194, + "ndv": 1 + }, + { + "start": "0.1", + "size": 0.258064516, + "ndv": 1 + }, + { + "start": "0.112", + "end": "0.112", + "size": 0.129032258, + "ndv": 1 + } + ] +} +test t1 f 1 5 0.2000 6.4000 5 JSON_HB { + "target_histogram_size": 8, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start_hex": "01", + "size": 0.125, + "ndv": 1 + }, + { + "start_hex": "02", + "size": 0.25, + "ndv": 1 + }, + { + "start_hex": "03", + "size": 0.1875, + "ndv": 1 + }, + { + "start_hex": "04", + "size": 0.3125, + "ndv": 1 + }, + { + "start_hex": "05", + "end_hex": "05", + "size": 0.125, + "ndv": 1 + } + ] +} +DELETE FROM mysql.column_stats; +set histogram_size= 0; +set histogram_type=@SINGLE_PREC_TYPE; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +CREATE TABLE t3 ( +a int NOT NULL PRIMARY KEY, +b varchar(32), +c char(16), +INDEX idx (c) +) ENGINE=MYISAM; +INSERT INTO t3 VALUES +(0, NULL, NULL), +(7, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'dddddddd'), +(17, 'vvvvvvvvvvvvv', 'aaaa'), +(1, 'vvvvvvvvvvvvv', NULL), +(12, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd'), +(23, 'vvvvvvvvvvvvv', 'dddddddd'), +(8, 'vvvvvvvvvvvvv', 'aaaa'), +(22, 'xxxxxxxxxxxxxxxxxxxxxxxxxx', 'aaaa'), +(31, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'aaaa'), +(10, NULL, 'aaaa'), +(5, 'wwwwwwwwwwwwwwwwwwwwwwwwwwww', 'dddddddd'), +(15, 'vvvvvvvvvvvvv', 'ccccccccc'), +(30, NULL, 'bbbbbb'), +(38, 'zzzzzzzzzzzzzzzzzz', 'bbbbbb'), +(18, 'zzzzzzzzzzzzzzzzzz', 'ccccccccc'), +(9, 'yyy', 'bbbbbb'), +(29, 'vvvvvvvvvvvvv', 'dddddddd'); +ANALYZE TABLE t3; +Table Op Msg_type Msg_text +test.t3 analyze status Engine-independent statistics collected +test.t3 analyze status OK +SELECT * FROM mysql.table_stats; +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +test t3 PRIMARY 1 1.0000 +test t3 idx 1 3.7500 +ALTER TABLE t1 RENAME TO s1; +SELECT * FROM mysql.table_stats; +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 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 +test s1 idx1 1 6.4000 +test s1 idx1 2 1.6875 +test s1 idx2 1 7.0000 +test s1 idx2 2 2.3846 +test s1 idx3 1 8.5000 +test s1 idx4 1 6.2000 +test s1 idx4 2 1.6875 +test s1 idx4 3 1.1304 +test t3 PRIMARY 1 1.0000 +test t3 idx 1 3.7500 +RENAME TABLE s1 TO t1; +SELECT * FROM mysql.table_stats; +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +test t3 PRIMARY 1 1.0000 +test t3 idx 1 3.7500 +DROP TABLE t3; +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +CREATE TEMPORARY TABLE t0 ( +a int NOT NULL PRIMARY KEY, +b varchar(32) +); +INSERT INTO t0 SELECT a,b FROM t1; +ALTER TABLE t1 CHANGE COLUMN b x varchar(32), +CHANGE COLUMN e y double; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `x` varchar(32) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `y` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`x`,`y`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + 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 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 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL +test t1 x vvvvvvvvvvvvv zzzzzzzzzzzzzzzzzz 0.2000 17.1250 6.4000 0 NULL NULL +test t1 y 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL +ALTER TABLE t1 CHANGE COLUMN x b varchar(32), +CHANGE COLUMN y e double; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` varchar(32) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`b`,`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + 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 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 +s1 CREATE TABLE `s1` ( + `a` int(11) NOT NULL, + `x` varchar(32) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`x`,`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + KEY `idx4` (`e`,`x`,`d`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +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 hist_size hist_type histogram +test s1 a 0 49 0.0000 4.0000 1.0000 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 s1 x 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 s1 PRIMARY 1 1.0000 +test s1 idx1 1 6.4000 +test s1 idx1 2 1.6875 +test s1 idx2 1 7.0000 +test s1 idx2 2 2.3846 +test s1 idx3 1 8.5000 +test s1 idx4 1 6.2000 +test s1 idx4 2 1.6875 +test s1 idx4 3 1.1304 +ALTER TABLE s1 RENAME TO t1, CHANGE COLUMN x b varchar(32); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` varchar(32) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`b`,`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + KEY `idx4` (`e`,`b`,`d`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +ALTER TABLE t1 CHANGE COLUMN b x varchar(30); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `x` varchar(30) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`x`,`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + 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 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 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +ALTER TABLE t1 CHANGE COLUMN x b varchar(32); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` varchar(32) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`b`,`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + 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 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 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx4); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/save_column_stats' + FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' + FROM mysql.column_stats WHERE column_name='b'; +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/save_index_stats' + FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' + FROM mysql.index_stats WHERE index_name IN ('idx1', 'idx4'); +ALTER TABLE t1 CHANGE COLUMN b x varchar(30); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `x` varchar(30) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`x`,`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + 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 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 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +ALTER TABLE t1 CHANGE COLUMN x b varchar(32); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `b` varchar(32) DEFAULT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`b`,`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + 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 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 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/save_column_stats' + INTO TABLE mysql.column_stats +FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +ALTER TABLE t1 DROP COLUMN b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`e`), + KEY `idx2` (`c`,`d`), + KEY `idx3` (`d`), + 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 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 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +DROP INDEX idx2 ON t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx1` (`e`), + KEY `idx3` (`d`), + KEY `idx4` (`e`,`d`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT * FROM mysql.index_stats; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 idx3 1 8.5000 +DROP INDEX idx1 ON t1; +DROP INDEX idx4 ON t1; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx3` (`d`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t1 ADD COLUMN b varchar(32); +CREATE INDEX idx1 ON t1(b, e); +CREATE INDEX idx2 ON t1(c, d); +CREATE INDEX idx4 ON t1(e, b, d); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + `b` varchar(32) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx3` (`d`), + KEY `idx1` (`b`,`e`), + KEY `idx2` (`c`,`d`), + 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 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 +test t1 idx3 1 8.5000 +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +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 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 +test t1 idx1 1 NULL +test t1 idx1 2 NULL +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 NULL +test t1 idx4 3 NULL +UPDATE t1 SET b=(SELECT b FROM t0 WHERE t0.a= t1.a); +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +ALTER TABLE t1 DROP COLUMN b, +DROP INDEX idx1, DROP INDEX idx2, DROP INDEX idx4; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + PRIMARY KEY (`a`), + 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 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 +test t1 idx3 1 8.5000 +ALTER TABLE t1 ADD COLUMN b varchar(32); +ALTER TABLE t1 +ADD INDEX idx1 (b, e), ADD INDEX idx2 (c, d), ADD INDEX idx4 (e, b, d); +UPDATE t1 SET b=(SELECT b FROM t0 WHERE t0.a= t1.a); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) NOT NULL, + `c` char(16) DEFAULT NULL, + `d` date DEFAULT NULL, + `e` double DEFAULT NULL, + `f` bit(3) DEFAULT NULL, + `b` varchar(32) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx3` (`d`), + KEY `idx1` (`b`,`e`), + KEY `idx2` (`c`,`d`), + 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 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 +test t1 idx3 1 8.5000 +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(idx1, idx2, idx4); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS() INDEXES(); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +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 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); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +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 hist_size hist_type histogram +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 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL +SELECT * FROM mysql.index_stats; +db_name table_name index_name prefix_arity avg_frequency +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +DELETE FROM mysql.index_stats WHERE table_name='t1' AND index_name='primary'; +SELECT * FROM mysql.index_stats; +db_name table_name index_name prefix_arity avg_frequency +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS() INDEXES(primary); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +SELECT * FROM mysql.index_stats; +db_name table_name index_name prefix_arity avg_frequency +test t1 PRIMARY 1 1.0000 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS ALL INDEXES ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +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 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 +test t1 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t1 idx4 3 1.1304 +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 ENGINE=InnoDB; +INSERT INTO t2 SELECT * FROM t1; +set optimizer_switch='extended_keys=off'; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +SELECT * FROM mysql.table_stats; +db_name table_name cardinality +test t1 40 +test t2 40 +SELECT * FROM mysql.column_stats ORDER BY column_name, table_name; +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 +test t2 PRIMARY 1 1.0000 +test t1 idx1 1 6.4000 +test t2 idx1 1 6.4000 +test t1 idx1 2 1.6875 +test t2 idx1 2 1.6875 +test t1 idx2 1 7.0000 +test t2 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t2 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t2 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t2 idx4 1 6.2000 +test t1 idx4 2 1.6875 +test t2 idx4 2 1.6875 +test t1 idx4 3 1.1304 +test t2 idx4 3 1.1304 +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; +set optimizer_switch='extended_keys=on'; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +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 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 +test t2 idx1 1 6.4000 +test t2 idx1 2 1.6875 +test t2 idx1 3 1.0000 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 1.6875 +test t2 idx4 3 1.1304 +test t2 idx4 4 1.0000 +ALTER TABLE t2 DROP PRIMARY KEY, DROP INDEX idx1; +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 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx3 1 8.5000 +test t2 idx4 1 6.2000 +test t2 idx4 2 1.6875 +test t2 idx4 3 1.1304 +UPDATE t2 SET b=0 WHERE b IS NULL; +ALTER TABLE t2 ADD PRIMARY KEY (a,b); +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 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx3 1 8.5000 +test t2 idx4 1 6.2000 +test t2 idx4 2 1.6875 +test t2 idx4 3 1.1304 +ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +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 +test t2 PRIMARY 2 1.0000 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx2 4 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx3 3 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 1.7222 +test t2 idx4 3 1.1154 +test t2 idx4 4 1.0000 +ALTER TABLE t2 CHANGE COLUMN b b varchar(30); +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 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx3 1 8.5000 +ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +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 +test t2 PRIMARY 2 1.0000 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx2 4 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx3 3 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 1.7222 +test t2 idx4 3 1.1154 +test t2 idx4 4 1.0000 +ALTER TABLE t2 CHANGE COLUMN b b varchar(32); +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 +test t2 PRIMARY 2 1.0000 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx2 4 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx3 3 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 1.7222 +test t2 idx4 3 1.1154 +test t2 idx4 4 1.0000 +ANALYZE TABLE t2 PERSISTENT FOR COLUMNS ALL INDEXES ALL; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +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 +test t2 PRIMARY 2 1.0000 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx2 4 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx3 3 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 1.7222 +test t2 idx4 3 1.1154 +test t2 idx4 4 1.0000 +ALTER TABLE t2 DROP COLUMN b, DROP PRIMARY KEY, ADD PRIMARY KEY(a); +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 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx3 1 8.5000 +ANALYZE TABLE t2 PERSISTENT FOR COLUMNS() INDEXES ALL; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +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 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 2.2308 +test t2 idx4 3 1.0000 +set optimizer_switch='extended_keys=off'; +ALTER TABLE t1 +DROP INDEX idx1, +DROP INDEX idx4; +ALTER TABLE t1 +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 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 PRIMARY 1 1.0000 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 2.2308 +test t2 idx4 3 1.0000 +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +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 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 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 t1 PRIMARY 1 1.0000 +test t1 idx1 1 NULL +test t1 idx1 2 NULL +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 NULL +test t1 idx4 3 NULL +test t2 PRIMARY 1 1.0000 +test t2 idx2 1 7.0000 +test t2 idx2 2 2.3846 +test t2 idx2 3 1.0000 +test t2 idx3 1 8.5000 +test t2 idx3 2 1.0000 +test t2 idx4 1 6.2000 +test t2 idx4 2 2.2308 +test t2 idx4 3 1.0000 +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; +ANALYZE TABLE mysql.column_stats PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +mysql.column_stats analyze error Invalid argument +ANALYZE TABLE mysql.column_stats; +Table Op Msg_type Msg_text +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 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'; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status Table is already up to date +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 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 +test t1 idx1 1 NULL +test t1 idx1 2 NULL +test t1 idx2 1 7.0000 +test t1 idx2 2 2.3846 +test t1 idx3 1 8.5000 +test t1 idx4 1 6.2000 +test t1 idx4 2 NULL +test t1 idx4 3 NULL +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status Table is already up to date +ANALYZE TABLE t1 PERSISTENT FOR columns(a,b) INDEXES(); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status Table is already up to date +ANALYZE TABLE t1 PERSISTENT FOR columns(b) indexes(idx2); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status Table is already up to date +ANALYZE TABLE t1 PERSISTENT FOR columns() indexes(idx2); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; +DROP TABLE t1,t2; +set names utf8; +CREATE DATABASE world; +use world; +CREATE TABLE Country ( +Code char(3) NOT NULL default '', +Name char(52) NOT NULL default '', +SurfaceArea float(10,2) NOT NULL default '0.00', +Population int(11) NOT NULL default '0', +Capital int(11) default NULL, +PRIMARY KEY (Code), +UNIQUE INDEX (Name) +) CHARACTER SET utf8 COLLATE utf8_bin; +CREATE TABLE City ( +ID int(11) NOT NULL auto_increment, +Name char(35) NOT NULL default '', +Country char(3) NOT NULL default '', +Population int(11) NOT NULL default '0', +PRIMARY KEY (ID), +INDEX (Population), +INDEX (Country) +) CHARACTER SET utf8 COLLATE utf8_bin; +CREATE TABLE CountryLanguage ( +Country char(3) NOT NULL default '', +Language char(30) NOT NULL default '', +Percentage float(3,1) NOT NULL default '0.0', +PRIMARY KEY (Country, Language), +INDEX (Percentage) +) CHARACTER SET utf8 COLLATE utf8_bin; +set use_stat_tables='preferably'; +ANALYZE TABLE Country, City, CountryLanguage; +SELECT UPPER(db_name), UPPER(table_name), cardinality +FROM mysql.table_stats; +UPPER(db_name) UPPER(table_name) cardinality +WORLD CITY 4079 +WORLD COUNTRY 239 +WORLD COUNTRYLANGUAGE 984 +SELECT UPPER(db_name), UPPER(table_name), +column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency +FROM mysql.column_stats; +UPPER(db_name) UPPER(table_name) column_name min_value max_value nulls_ratio avg_length avg_frequency +WORLD CITY Country ABW ZWE 0.0000 3.0000 17.5819 +WORLD CITY ID 1 4079 0.0000 4.0000 1.0000 +WORLD CITY Name A Coruña (La Coruña) Ãœrgenc 0.0000 8.6416 1.0195 +WORLD CITY Population 42 10500000 0.0000 4.0000 1.0467 +WORLD COUNTRY Capital 1 4074 0.0293 4.0000 1.0000 +WORLD COUNTRY Code ABW ZWE 0.0000 3.0000 1.0000 +WORLD COUNTRY Name Afghanistan Zimbabwe 0.0000 10.1088 1.0000 +WORLD COUNTRY Population 0 1277558000 0.0000 4.0000 1.0575 +WORLD COUNTRY SurfaceArea 0.40 17075400.00 0.0000 4.0000 1.0042 +WORLD COUNTRYLANGUAGE Country ABW ZWE 0.0000 3.0000 4.2232 +WORLD COUNTRYLANGUAGE Language Abhyasi [South]Mande 0.0000 7.1778 2.1532 +WORLD COUNTRYLANGUAGE Percentage 0.0 99.9 0.0000 4.0000 2.7640 +SELECT UPPER(db_name), UPPER(table_name), +index_name, prefix_arity, avg_frequency +FROM mysql.index_stats; +UPPER(db_name) UPPER(table_name) index_name prefix_arity avg_frequency +WORLD CITY Country 1 17.5819 +WORLD CITY PRIMARY 1 1.0000 +WORLD CITY Population 1 1.0467 +WORLD COUNTRY Name 1 1.0000 +WORLD COUNTRY PRIMARY 1 1.0000 +WORLD COUNTRYLANGUAGE PRIMARY 1 4.2232 +WORLD COUNTRYLANGUAGE PRIMARY 2 1.0000 +WORLD COUNTRYLANGUAGE Percentage 1 2.7640 +use test; +set use_stat_tables='never'; +CREATE DATABASE world_innodb; +use world_innodb; +CREATE TABLE Country ( +Code char(3) NOT NULL default '', +Name char(52) NOT NULL default '', +SurfaceArea float(10,2) NOT NULL default '0.00', +Population int(11) NOT NULL default '0', +Capital int(11) default NULL, +PRIMARY KEY (Code), +UNIQUE INDEX (Name) +) CHARACTER SET utf8 COLLATE utf8_bin; +CREATE TABLE City ( +ID int(11) NOT NULL auto_increment, +Name char(35) NOT NULL default '', +Country char(3) NOT NULL default '', +Population int(11) NOT NULL default '0', +PRIMARY KEY (ID), +INDEX (Population), +INDEX (Country) +) CHARACTER SET utf8 COLLATE utf8_bin; +CREATE TABLE CountryLanguage ( +Country char(3) NOT NULL default '', +Language char(30) NOT NULL default '', +Percentage float(3,1) NOT NULL default '0.0', +PRIMARY KEY (Country, Language), +INDEX (Percentage) +) CHARACTER SET utf8 COLLATE utf8_bin; +ALTER TABLE Country ENGINE=InnoDB; +ALTER TABLE City ENGINE=InnoDB; +ALTER TABLE CountryLanguage ENGINE=InnoDB; +set use_stat_tables='preferably'; +ANALYZE TABLE Country, City, CountryLanguage; +SELECT UPPER(db_name), UPPER(table_name), cardinality +FROM mysql.table_stats; +UPPER(db_name) UPPER(table_name) cardinality +WORLD CITY 4079 +WORLD COUNTRY 239 +WORLD COUNTRYLANGUAGE 984 +WORLD_INNODB CITY 4079 +WORLD_INNODB COUNTRY 239 +WORLD_INNODB COUNTRYLANGUAGE 984 +SELECT UPPER(db_name), UPPER(table_name), +column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency +FROM mysql.column_stats; +UPPER(db_name) UPPER(table_name) column_name min_value max_value nulls_ratio avg_length avg_frequency +WORLD CITY Country ABW ZWE 0.0000 3.0000 17.5819 +WORLD CITY ID 1 4079 0.0000 4.0000 1.0000 +WORLD CITY Name A Coruña (La Coruña) Ãœrgenc 0.0000 8.6416 1.0195 +WORLD CITY Population 42 10500000 0.0000 4.0000 1.0467 +WORLD COUNTRY Capital 1 4074 0.0293 4.0000 1.0000 +WORLD COUNTRY Code ABW ZWE 0.0000 3.0000 1.0000 +WORLD COUNTRY Name Afghanistan Zimbabwe 0.0000 10.1088 1.0000 +WORLD COUNTRY Population 0 1277558000 0.0000 4.0000 1.0575 +WORLD COUNTRY SurfaceArea 0.40 17075400.00 0.0000 4.0000 1.0042 +WORLD COUNTRYLANGUAGE Country ABW ZWE 0.0000 3.0000 4.2232 +WORLD COUNTRYLANGUAGE Language Abhyasi [South]Mande 0.0000 7.1778 2.1532 +WORLD COUNTRYLANGUAGE Percentage 0.0 99.9 0.0000 4.0000 2.7640 +WORLD_INNODB CITY Country ABW ZWE 0.0000 3.0000 17.5819 +WORLD_INNODB CITY ID 1 4079 0.0000 4.0000 1.0000 +WORLD_INNODB CITY Name A Coruña (La Coruña) Ãœrgenc 0.0000 8.6416 1.0195 +WORLD_INNODB CITY Population 42 10500000 0.0000 4.0000 1.0467 +WORLD_INNODB COUNTRY Capital 1 4074 0.0293 4.0000 1.0000 +WORLD_INNODB COUNTRY Code ABW ZWE 0.0000 3.0000 1.0000 +WORLD_INNODB COUNTRY Name Afghanistan Zimbabwe 0.0000 10.1088 1.0000 +WORLD_INNODB COUNTRY Population 0 1277558000 0.0000 4.0000 1.0575 +WORLD_INNODB COUNTRY SurfaceArea 0.40 17075400.00 0.0000 4.0000 1.0042 +WORLD_INNODB COUNTRYLANGUAGE Country ABW ZWE 0.0000 3.0000 4.2232 +WORLD_INNODB COUNTRYLANGUAGE Language Abhyasi [South]Mande 0.0000 7.1778 2.1532 +WORLD_INNODB COUNTRYLANGUAGE Percentage 0.0 99.9 0.0000 4.0000 2.7640 +SELECT UPPER(db_name), UPPER(table_name), +index_name, prefix_arity, avg_frequency +FROM mysql.index_stats; +UPPER(db_name) UPPER(table_name) index_name prefix_arity avg_frequency +WORLD CITY Country 1 17.5819 +WORLD CITY PRIMARY 1 1.0000 +WORLD CITY Population 1 1.0467 +WORLD COUNTRY Name 1 1.0000 +WORLD COUNTRY PRIMARY 1 1.0000 +WORLD COUNTRYLANGUAGE PRIMARY 1 4.2232 +WORLD COUNTRYLANGUAGE PRIMARY 2 1.0000 +WORLD COUNTRYLANGUAGE Percentage 1 2.7640 +WORLD_INNODB CITY Country 1 17.5819 +WORLD_INNODB CITY PRIMARY 1 1.0000 +WORLD_INNODB CITY Population 1 1.0467 +WORLD_INNODB COUNTRY Name 1 1.0000 +WORLD_INNODB COUNTRY PRIMARY 1 1.0000 +WORLD_INNODB COUNTRYLANGUAGE PRIMARY 1 4.2232 +WORLD_INNODB COUNTRYLANGUAGE PRIMARY 2 1.0000 +WORLD_INNODB COUNTRYLANGUAGE Percentage 1 2.7640 +use world; +set use_stat_tables='preferably'; +set histogram_size=100; +set histogram_type=@SINGLE_PREC_TYPE; +ANALYZE TABLE CountryLanguage; +set histogram_size=254; +set histogram_type=@DOUBLE_PREC_TYPE; +ANALYZE TABLE City; +FLUSH TABLES; +select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='COUNTRYLANGUAGE' and UPPER(column_name) = 'PERCENTAGE';; +UPPER(db_name) WORLD +UPPER(table_name) COUNTRYLANGUAGE +UPPER(column_name) PERCENTAGE +min_value 0.0 +max_value 99.9 +nulls_ratio 0.0000 +avg_length 4.0000 +avg_frequency 2.7640 +hist_size 85 +hist_type JSON_HB +decode_histogram(hist_type,histogram) { + "target_histogram_size": 100, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0.0", + "size": 0.066056911, + "ndv": 1 + }, + { + "start": "0.1", + "size": 0.020325203, + "ndv": 1 + }, + { + "start": "0.2", + "size": 0.022357724, + "ndv": 1 + }, + { + "start": "0.3", + "size": 0.017276423, + "ndv": 1 + }, + { + "start": "0.4", + "size": 0.025406504, + "ndv": 1 + }, + { + "start": "0.5", + "size": 0.020325203, + "ndv": 1 + }, + { + "start": "0.6", + "size": 0.020325203, + "ndv": 1 + }, + { + "start": "0.7", + "size": 0.017276423, + "ndv": 1 + }, + { + "start": "0.8", + "size": 0.010162602, + "ndv": 1 + }, + { + "start": "0.9", + "size": 0.010162602, + "ndv": 1 + }, + { + "start": "1.0", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "1.1", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "1.3", + "size": 0.012195122, + "ndv": 1 + }, + { + "start": "1.4", + "size": 0.015243902, + "ndv": 1 + }, + { + "start": "1.5", + "size": 0.005081301, + "ndv": 1 + }, + { + "start": "1.6", + "size": 0.015243902, + "ndv": 1 + }, + { + "start": "1.7", + "size": 0.010162602, + "ndv": 1 + }, + { + "start": "1.8", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "1.9", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "2.0", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "2.2", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "2.3", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "2.4", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "2.5", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "2.7", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "2.8", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "3.0", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "3.2", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "3.3", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "3.5", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "3.7", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "3.8", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "4.1", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "4.4", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "4.8", + "size": 0.010162602, + "ndv": 2 + }, + { + "start": "4.9", + "size": 0.010162602, + "ndv": 5 + }, + { + "start": "5.3", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "5.5", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "5.7", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "6.0", + "size": 0.010162602, + "ndv": 5 + }, + { + "start": "6.4", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "6.7", + "size": 0.010162602, + "ndv": 5 + }, + { + "start": "7.2", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "7.4", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "7.7", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "8.0", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "8.5", + "size": 0.010162602, + "ndv": 3 + }, + { + "start": "8.7", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "9.1", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "9.5", + "size": 0.010162602, + "ndv": 4 + }, + { + "start": "10.1", + "size": 0.010162602, + "ndv": 6 + }, + { + "start": "10.8", + "size": 0.010162602, + "ndv": 6 + }, + { + "start": "11.4", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "12.1", + "size": 0.010162602, + "ndv": 6 + }, + { + "start": "12.8", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "13.8", + "size": 0.010162602, + "ndv": 6 + }, + { + "start": "14.6", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "16.1", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "17.1", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "19.0", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "20.3", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "22.7", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "23.8", + "size": 0.010162602, + "ndv": 9 + }, + { + "start": "29.7", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "32.1", + "size": 0.010162602, + "ndv": 9 + }, + { + "start": "34.8", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "39.9", + "size": 0.010162602, + "ndv": 9 + }, + { + "start": "44.6", + "size": 0.010162602, + "ndv": 10 + }, + { + "start": "49.1", + "size": 0.010162602, + "ndv": 9 + }, + { + "start": "52.0", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "58.4", + "size": 0.010162602, + "ndv": 10 + }, + { + "start": "64.7", + "size": 0.010162602, + "ndv": 9 + }, + { + "start": "69.9", + "size": 0.010162602, + "ndv": 10 + }, + { + "start": "76.7", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "80.0", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "85.0", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "87.0", + "size": 0.010162602, + "ndv": 9 + }, + { + "start": "89.5", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "92.0", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "93.6", + "size": 0.010162602, + "ndv": 8 + }, + { + "start": "95.7", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "96.9", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "98.0", + "size": 0.010162602, + "ndv": 7 + }, + { + "start": "99.0", + "size": 0.006097561, + "ndv": 4 + }, + { + "start": "99.9", + "end": "99.9", + "size": 0.015243902, + "ndv": 1 + } + ] +} +select UPPER(db_name),UPPER(table_name),UPPER(column_name),min_value,max_value,nulls_ratio,avg_length,avg_frequency,hist_size,hist_type,decode_histogram(hist_type,histogram) from mysql.column_stats where UPPER(db_name)='WORLD' and UPPER(table_name)='CITY' and UPPER(column_name) = 'POPULATION';; +UPPER(db_name) WORLD +UPPER(table_name) CITY +UPPER(column_name) POPULATION +min_value 42 +max_value 10500000 +nulls_ratio 0.0000 +avg_length 4.0000 +avg_frequency 1.0467 +hist_size 240 +hist_type JSON_HB +decode_histogram(hist_type,histogram) { + "target_histogram_size": 254, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "42", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "1636", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "5808", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "16243", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "29034", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "71000", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "89200", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "89447", + "size": 0.004167688, + "ndv": 10 + }, + { + "start": "90000", + "size": 0.004167688, + "ndv": 11 + }, + { + "start": "90500", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "90814", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "91100", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "91700", + "size": 0.004167688, + "ndv": 13 + }, + { + "start": "92044", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "92574", + "size": 0.004167688, + "ndv": 13 + }, + { + "start": "92988", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "93342", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "93900", + "size": 0.004167688, + "ndv": 13 + }, + { + "start": "94200", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "94700", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "95052", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "95521", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "96100", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "96626", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "96938", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "97300", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "97929", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "98293", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "98640", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "99300", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "99781", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "100118", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "100490", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "100924", + "size": 0.004167688, + "ndv": 12 + }, + { + "start": "101295", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "101660", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "102121", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "102379", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "102820", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "103300", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "103653", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "104400", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "105080", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "105530", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "106000", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "106400", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "106996", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "107329", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "107770", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "108254", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "108600", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "109225", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "109600", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "110034", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "110700", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "111454", + "size": 0.004167688, + "ndv": 12 + }, + { + "start": "112007", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "112673", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "113494", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "114065", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "114815", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "115483", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "116132", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "116695", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "117258", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "118080", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "118815", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "119391", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "119990", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "120700", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "121197", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "121842", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "122400", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "123273", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "123776", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "124072", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "124600", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "125236", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "125700", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "126282", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "126872", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "127350", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "127898", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "128651", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "129688", + "size": 0.004167688, + "ndv": 13 + }, + { + "start": "130215", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "131149", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "132127", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "132820", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "133443", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "133936", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "134835", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "136062", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "137000", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "137700", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "138418", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "139357", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "140169", + "size": 0.004167688, + "ndv": 13 + }, + { + "start": "141132", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "142170", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "142990", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "144126", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "145150", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "146105", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "147124", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "147939", + "size": 0.004167688, + "ndv": 14 + }, + { + "start": "148867", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "149900", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "151000", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "152194", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "153344", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "154980", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "155941", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "157358", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "158720", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "160359", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "161500", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "163100", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "164367", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "165583", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "167183", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "168953", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "170123", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "171363", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "172648", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "173878", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "174984", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "176576", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "178200", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "179258", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "180400", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "182148", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "183261", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "184500", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "185951", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "187557", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "189036", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "190255", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "192509", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "194100", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "195468", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "197000", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "199000", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "200901", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "202451", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "204900", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "206338", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "208054", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "211068", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "213271", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "215373", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "217499", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "219761", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "222030", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "224044", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "226573", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "229212", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "232811", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "235760", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "239124", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "241769", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "243825", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "246535", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "249200", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "253587", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "255617", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "259537", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "262947", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "265211", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "269393", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "272058", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "275990", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "278829", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "282197", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "286848", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "291000", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "294125", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "299118", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "301504", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "305699", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "311200", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "315083", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "319373", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "324662", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "328711", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "332800", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "337966", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "342200", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "348100", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "353400", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "358663", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "362470", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "366712", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "375000", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "381725", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "386236", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "395402", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "403151", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "411542", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "419000", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "425579", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "433180", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "441649", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "450180", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "459884", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "469533", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "476668", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "483155", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "495540", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "510000", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "520000", + "size": 0.004167688, + "ndv": 15 + }, + { + "start": "530965", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "554636", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "568855", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "587211", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "606932", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "624269", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "650100", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "669181", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "701827", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "728060", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "762000", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "794246", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "830000", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "879000", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "947483", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "1002239", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "1060257", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "1119117", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "1186926", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "1248700", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "1346176", + "size": 0.004167688, + "ndv": 16 + }, + { + "start": "1458483", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "1615369", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "1861265", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "2117500", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "2500000", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "2896016", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "4017733", + "size": 0.004167688, + "ndv": 17 + }, + { + "start": "6758845", + "end": "10500000", + "size": 0.00392253, + "ndv": 16 + } + ] +} +set histogram_type=@SINGLE_PREC_TYPE; +set histogram_size=0; +use test; +DROP DATABASE world; +SELECT UPPER(db_name), UPPER(table_name), cardinality +FROM mysql.table_stats; +UPPER(db_name) UPPER(table_name) cardinality +WORLD_INNODB CITY 4079 +WORLD_INNODB COUNTRY 239 +WORLD_INNODB COUNTRYLANGUAGE 984 +SELECT UPPER(db_name), UPPER(table_name), +column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency +FROM mysql.column_stats; +UPPER(db_name) UPPER(table_name) column_name min_value max_value nulls_ratio avg_length avg_frequency +WORLD_INNODB CITY Country ABW ZWE 0.0000 3.0000 17.5819 +WORLD_INNODB CITY ID 1 4079 0.0000 4.0000 1.0000 +WORLD_INNODB CITY Name A Coruña (La Coruña) Ãœrgenc 0.0000 8.6416 1.0195 +WORLD_INNODB CITY Population 42 10500000 0.0000 4.0000 1.0467 +WORLD_INNODB COUNTRY Capital 1 4074 0.0293 4.0000 1.0000 +WORLD_INNODB COUNTRY Code ABW ZWE 0.0000 3.0000 1.0000 +WORLD_INNODB COUNTRY Name Afghanistan Zimbabwe 0.0000 10.1088 1.0000 +WORLD_INNODB COUNTRY Population 0 1277558000 0.0000 4.0000 1.0575 +WORLD_INNODB COUNTRY SurfaceArea 0.40 17075400.00 0.0000 4.0000 1.0042 +WORLD_INNODB COUNTRYLANGUAGE Country ABW ZWE 0.0000 3.0000 4.2232 +WORLD_INNODB COUNTRYLANGUAGE Language Abhyasi [South]Mande 0.0000 7.1778 2.1532 +WORLD_INNODB COUNTRYLANGUAGE Percentage 0.0 99.9 0.0000 4.0000 2.7640 +SELECT UPPER(db_name), UPPER(table_name), +index_name, prefix_arity, avg_frequency +FROM mysql.index_stats; +UPPER(db_name) UPPER(table_name) index_name prefix_arity avg_frequency +WORLD_INNODB CITY Country 1 17.5819 +WORLD_INNODB CITY PRIMARY 1 1.0000 +WORLD_INNODB CITY Population 1 1.0467 +WORLD_INNODB COUNTRY Name 1 1.0000 +WORLD_INNODB COUNTRY PRIMARY 1 1.0000 +WORLD_INNODB COUNTRYLANGUAGE PRIMARY 1 4.2232 +WORLD_INNODB COUNTRYLANGUAGE PRIMARY 2 1.0000 +WORLD_INNODB COUNTRYLANGUAGE Percentage 1 2.7640 +DROP DATABASE world_innodb; +SELECT UPPER(db_name), UPPER(table_name), cardinality +FROM mysql.table_stats; +UPPER(db_name) UPPER(table_name) cardinality +SELECT UPPER(db_name), UPPER(table_name), +column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency +FROM mysql.column_stats; +UPPER(db_name) UPPER(table_name) column_name min_value max_value nulls_ratio avg_length avg_frequency +SELECT UPPER(db_name), UPPER(table_name), +index_name, prefix_arity, avg_frequency +FROM mysql.index_stats; +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 Engine-independent statistics collected +test.t1 analyze status OK +select db_name, table_name, column_name, +min_value, max_value, +nulls_ratio, avg_frequency, +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 1 3 0.0000 1.0000 3 JSON_HB { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.333333333, + "ndv": 1 + }, + { + "start": "2", + "size": 0.333333333, + "ndv": 1 + }, + { + "start": "3", + "end": "3", + "size": 0.333333333, + "ndv": 1 + } + ] +} +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_TYPE; +show variables like 'histogram%'; +Variable_name Value +histogram_size 10 +histogram_type JSON_HB +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select db_name, table_name, column_name, +min_value, max_value, +nulls_ratio, avg_frequency, +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats +ORDER BY db_name, table_name, column_name; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a 1 5 0.0000 1.0000 5 JSON_HB { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.2, + "ndv": 1 + }, + { + "start": "2", + "size": 0.2, + "ndv": 1 + }, + { + "start": "3", + "size": 0.2, + "ndv": 1 + }, + { + "start": "4", + "size": 0.2, + "ndv": 1 + }, + { + "start": "5", + "end": "5", + "size": 0.2, + "ndv": 1 + } + ] +} +set histogram_size=0; +set histogram_type=@SINGLE_PREC_TYPE; +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 Engine-independent statistics collected +test.t2 analyze status OK +select db_name, table_name, column_name, +min_value, max_value, +nulls_ratio, avg_frequency, +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t2 id 1 1024 0.0000 8.0000 63 JSON_HB { + "target_histogram_size": 63, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "17", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "33", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "50", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "66", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "82", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "99", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "115", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "132", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "148", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "164", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "181", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "197", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "213", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "230", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "246", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "263", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "279", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "295", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "312", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "328", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "344", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "361", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "377", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "394", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "410", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "426", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "443", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "459", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "475", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "492", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "508", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "525", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "541", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "557", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "574", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "590", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "606", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "623", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "639", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "656", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "672", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "688", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "705", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "721", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "737", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "754", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "770", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "787", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "803", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "819", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "836", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "852", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "868", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "885", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "901", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "918", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "934", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "950", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "967", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "983", + "size": 0.015991211, + "ndv": 17 + }, + { + "start": "999", + "size": 0.015991211, + "ndv": 18 + }, + { + "start": "1016", + "end": "1024", + "size": 0.008544922, + "ndv": 9 + } + ] +} +set histogram_size=0; +drop table t1, t2; +set use_stat_tables=@save_use_stat_tables; +# +# Bug MDEV-7383: min/max value for a column not utf8 compatible +# +create table t1 (a varchar(100)) engine=MyISAM; +insert into t1 values(unhex('D879626AF872675F73E662F8')); +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +show warnings; +Level Code Message +select db_name, table_name, column_name, +HEX(min_value), HEX(max_value), +nulls_ratio, avg_frequency, +hist_size, hist_type, decode_histogram(hist_type,histogram) +FROM mysql.column_stats; +db_name table_name column_name HEX(min_value) HEX(max_value) nulls_ratio avg_frequency hist_size hist_type decode_histogram(hist_type,histogram) +test t1 a D879626AF872675F73E662F8 D879626AF872675F73E662F8 0.0000 1.0000 0 NULL NULL +drop table t1; +# +# MDEB-9744: session optimizer_use_condition_selectivity=5 causing SQL Error (1918): +# Encountered illegal value '' when converting to DECIMAL +# +set @save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +set optimizer_use_condition_selectivity=3, use_stat_tables=preferably; +create table t1 (id int(10),cost decimal(9,2)) engine=innodb; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +create temporary table t2 (id int); +insert into t2 (id) select id from t1 where cost > 0; +select * from t2; +id +set use_stat_tables=@save_use_stat_tables; +set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +drop table t1,t2; +# +# MDEV-16507: statistics for temporary tables should not be used +# +SET +@save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +SET @@use_stat_tables = preferably ; +SET @@optimizer_use_condition_selectivity = 4; +CREATE TABLE t1 ( +TIMESTAMP TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +ON UPDATE CURRENT_TIMESTAMP +); +SET @had_t1_table= @@warning_count != 0; +CREATE TEMPORARY TABLE tmp_t1 LIKE t1; +INSERT INTO tmp_t1 VALUES (now()); +INSERT INTO t1 SELECT * FROM tmp_t1 WHERE @had_t1_table=0; +DROP TABLE t1; +SET +use_stat_tables=@save_use_stat_tables; +SET +optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +# End of 10.0 tests +# +# MDEV-9590: Always print "Engine-independent statistic" warnings and +# might be filtering columns unintentionally from engines +# +set use_stat_tables='NEVER'; +create table t1 (test blob); +show variables like 'use_stat_tables'; +Variable_name Value +use_stat_tables NEVER +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +drop table t1; +# +# MDEV-10435 crash with bad stat tables +# +set use_stat_tables='preferably'; +call mtr.add_suppression("Column count of mysql.table_stats is wrong. Expected 3, found 1. The table is probably corrupted"); +rename table mysql.table_stats to test.table_stats; +flush tables; +create table t1 (a int); +rename table t1 to t2, t3 to t4; +ERROR 42S02: Table 'test.t3' doesn't exist +drop table t1; +rename table test.table_stats to mysql.table_stats; +rename table mysql.table_stats to test.table_stats; +create table mysql.table_stats (a int); +flush tables; +create table t1 (a int); +rename table t1 to t2, t3 to t4; +ERROR 42S02: Table 'test.t3' doesn't exist +drop table t1, mysql.table_stats; +rename table test.table_stats to mysql.table_stats; +# +# MDEV-19334: bool is_eits_usable(Field*): Assertion `field->table->stats_is_read' failed. +# +create temporary table t1(a int); +insert into t1 values (1),(2),(3); +set use_stat_tables=preferably; +set @optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +set optimizer_use_condition_selectivity=4; +select * from t1 where a >= 2; +a +2 +3 +drop table t1; +set @@optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; +set use_stat_tables=@save_use_stat_tables; +# +# Start of 10.2 tests +# +# +# MDEV-10134 Add full support for DEFAULT +# +# +# End of 10.2 tests +# +set histogram_size=@save_histogram_size, histogram_type=@save_hist_type; +# +# Start of 10.4 tests +# +# +# Test analyze_sample_percentage system variable. +# +set @save_use_stat_tables=@@use_stat_tables; +set @save_analyze_sample_percentage=@@analyze_sample_percentage; +set session rand_seed1=42; +set session rand_seed2=62; +set use_stat_tables=PREFERABLY; +set histogram_size=10; +CREATE TABLE t1 (id int); +INSERT INTO t1 (id) VALUES (1), (1), (1), (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 t1 SELECT id+1024 FROM t1; +INSERT INTO t1 SELECT id+2048 FROM t1; +INSERT INTO t1 SELECT id+4096 FROM t1; +INSERT INTO t1 SELECT id+9192 FROM t1; +# +# This query will should show a full table scan analysis. +# +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, +DECODE_HISTOGRAM(hist_type, histogram) +from mysql.column_stats; +table_name column_name min_value max_value nulls_ratio avg_length avg_frequency DECODE_HISTOGRAM(hist_type, histogram) +t1 id 1 17384 0.0000 4.0000 14.0000 { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "1639", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "3277", + "size": 0.100001744, + "ndv": 1640 + }, + { + "start": "4916", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "6554", + "size": 0.100001744, + "ndv": 1640 + }, + { + "start": "9193", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "10831", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "12470", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "14108", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "15746", + "end": "17384", + "size": 0.099984305, + "ndv": 1639 + } + ] +} +set analyze_sample_percentage=0.1; +# +# This query will show an innacurate avg_frequency value. +# +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, +DECODE_HISTOGRAM(hist_type, histogram) +from mysql.column_stats; +table_name column_name min_value max_value nulls_ratio avg_length avg_frequency DECODE_HISTOGRAM(hist_type, histogram) +t1 id 111 17026 0.0000 4.0000 10.4739 { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "111", + "size": 0.103773585, + "ndv": 21 + }, + { + "start": "1074", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "2504", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "4395", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "6165", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "8082", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "10671", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "12738", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "14487", + "size": 0.103773585, + "ndv": 22 + }, + { + "start": "15785", + "end": "17026", + "size": 0.066037736, + "ndv": 14 + } + ] +} +# +# This query will show a better avg_frequency value. +# +set analyze_sample_percentage=25; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, +DECODE_HISTOGRAM(hist_type, histogram) +from mysql.column_stats; +table_name column_name min_value max_value nulls_ratio avg_length avg_frequency DECODE_HISTOGRAM(hist_type, histogram) +t1 id 1 17384 0.0000 4.0000 14.0401 { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.100015657, + "ndv": 1591 + }, + { + "start": "1624", + "size": 0.100015657, + "ndv": 1599 + }, + { + "start": "3252", + "size": 0.100015657, + "ndv": 1587 + }, + { + "start": "4868", + "size": 0.100015657, + "ndv": 1594 + }, + { + "start": "6483", + "size": 0.100015657, + "ndv": 1632 + }, + { + "start": "8153", + "size": 0.100015657, + "ndv": 1607 + }, + { + "start": "10791", + "size": 0.100015657, + "ndv": 1619 + }, + { + "start": "12435", + "size": 0.100015657, + "ndv": 1627 + }, + { + "start": "14080", + "size": 0.100015657, + "ndv": 1613 + }, + { + "start": "15727", + "end": "17384", + "size": 0.099859084, + "ndv": 1622 + } + ] +} +set analyze_sample_percentage=0; +# +# Test self adjusting sampling level. +# +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, +DECODE_HISTOGRAM(hist_type, histogram) +from mysql.column_stats; +table_name column_name min_value max_value nulls_ratio avg_length avg_frequency DECODE_HISTOGRAM(hist_type, histogram) +t1 id 1 17384 0.0000 4.0000 13.9812 { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.100007372, + "ndv": 1651 + }, + { + "start": "1651", + "size": 0.100007372, + "ndv": 1656 + }, + { + "start": "3306", + "size": 0.100007372, + "ndv": 1643 + }, + { + "start": "4949", + "size": 0.100007372, + "ndv": 1648 + }, + { + "start": "6597", + "size": 0.100007372, + "ndv": 1644 + }, + { + "start": "9240", + "size": 0.100007372, + "ndv": 1624 + }, + { + "start": "10864", + "size": 0.100007372, + "ndv": 1633 + }, + { + "start": "12496", + "size": 0.100007372, + "ndv": 1619 + }, + { + "start": "14114", + "size": 0.100007372, + "ndv": 1645 + }, + { + "start": "15758", + "end": "17384", + "size": 0.099933656, + "ndv": 1627 + } + ] +} +# +# Test record estimation is working properly. +# +select count(*) from t1; +count(*) +229376 +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 229060 +set analyze_sample_percentage=100; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +select table_name, column_name, min_value, max_value, nulls_ratio, avg_length, avg_frequency, +DECODE_HISTOGRAM(hist_type, histogram) +from mysql.column_stats; +table_name column_name min_value max_value nulls_ratio avg_length avg_frequency DECODE_HISTOGRAM(hist_type, histogram) +t1 id 1 17384 0.0000 4.0000 14.0000 { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "1639", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "3277", + "size": 0.100001744, + "ndv": 1640 + }, + { + "start": "4916", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "6554", + "size": 0.100001744, + "ndv": 1640 + }, + { + "start": "9193", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "10831", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "12470", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "14108", + "size": 0.100001744, + "ndv": 1639 + }, + { + "start": "15746", + "end": "17384", + "size": 0.099984305, + "ndv": 1639 + } + ] +} +explain select * from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 229376 +drop table t0; +drop table t1; +set analyze_sample_percentage=@save_analyze_sample_percentage; +set histogram_size=@save_histogram_size; +set use_stat_tables=@save_use_stat_tables; +set @@global.histogram_size=@save_histogram_size; +drop table if exists t1; +set @save_histogram_type=@@histogram_type; +set @save_histogram_size=@@histogram_size; +call mtr.add_suppression("Failed to parse histogram for table .*"); +create table ten(a int primary key); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +set histogram_size=100; +set histogram_type='double_prec_hb'; +create table t1_bin (a varchar(255)); +insert into t1_bin select concat('a-', a) from ten; +analyze table t1_bin persistent for all; +Table Op Msg_type Msg_text +test.t1_bin analyze status Engine-independent statistics collected +test.t1_bin analyze status OK +select hex(histogram) from mysql.column_stats where table_name='t1_bin'; +hex(histogram) +00000000000000000000711C711C711C711C711CE338E338E338E338E33855555555555555555555C671C671C671C671C671388E388E388E388E388EAAAAAAAAAAAAAAAAAAAA1BC71BC71BC71BC71BC78DE38DE38DE38DE38DE3FFFFFFFFFFFFFFFFFFFF +explain extended select * from t1_bin where a between 'a-3a' and 'zzzzzzzzz'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1_bin ALL NULL NULL NULL NULL 10 58.82 Using where +Warnings: +Note 1003 select `test`.`t1_bin`.`a` AS `a` from `test`.`t1_bin` where `test`.`t1_bin`.`a` between 'a-3a' and 'zzzzzzzzz' +analyze select * from t1_bin where a between 'a-3a' and 'zzzzzzzzz'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1_bin ALL NULL NULL NULL NULL 10 10.00 58.82 60.00 Using where +set histogram_type=json_hb; +create table t1_json (a varchar(255)); +insert into t1_json select concat('a-', a) from ten; +analyze table t1_json persistent for all; +Table Op Msg_type Msg_text +test.t1_json analyze status Engine-independent statistics collected +test.t1_json analyze status OK +select * from mysql.column_stats where table_name='t1_json'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1_json a a-0 a-9 0.0000 3.0000 1.0000 10 JSON_HB { + "target_histogram_size": 100, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "a-0", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-1", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-2", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-3", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-4", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-5", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-6", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-7", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-8", + "size": 0.1, + "ndv": 1 + }, + { + "start": "a-9", + "end": "a-9", + "size": 0.1, + "ndv": 1 + } + ] +} +explain extended select * from t1_json where a between 'a-3a' and 'zzzzzzzzz'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 60.00 Using where +Warnings: +Note 1003 select `test`.`t1_json`.`a` AS `a` from `test`.`t1_json` where `test`.`t1_json`.`a` between 'a-3a' and 'zzzzzzzzz' +analyze select * from t1_json where a between 'a-3a' and 'zzzzzzzzz'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 10.00 60.00 60.00 Using where +explain extended select * from t1_json where a < 'b-1a'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 100.00 Using where +Warnings: +Note 1003 select `test`.`t1_json`.`a` AS `a` from `test`.`t1_json` where `test`.`t1_json`.`a` < 'b-1a' +analyze select * from t1_json where a > 'zzzzzzzzz'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 10.00 0.00 0.00 Using where +drop table ten; +UPDATE mysql.column_stats +SET histogram='["not-what-you-expect"]' WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: Root JSON element must be a JSON object at offset 1. +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":"not-histogram"}' WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: histogram_hb must contain an array at offset 32. +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":["not-a-bucket"]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: Expected an object in the buckets array at offset 32. +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"no-expected-members":1}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: "start" element not present at offset 42. +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":{}}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: String or number expected at offset 27. +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":"aaa", "size":"not-an-integer"}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: "ndv" element not present at offset 57. +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":"aaa", "size":0.25}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: "ndv" element not present at offset 45. +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":"aaa", "size":0.25, "ndv":1}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1_json ALL NULL NULL NULL NULL 10 +Warnings: +Warning 4186 Failed to parse histogram for table test.t1_json: Histogram must have at least one bucket at offset 19. +create table t2 ( +city varchar(100) +); +set histogram_size=50; +insert into t2 select 'Moscow' from seq_1_to_99; +insert into t2 select 'Helsinki' from seq_1_to_2; +set histogram_type=json_hb; +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +explain extended select * from t2 where city = 'Moscow'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 101 98.02 Using where +Warnings: +Note 1003 select `test`.`t2`.`city` AS `city` from `test`.`t2` where `test`.`t2`.`city` = 'Moscow' +analyze select * from t2 where city = 'Moscow'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 101 101.00 98.02 98.02 Using where +explain extended select * from t2 where city = 'Helsinki'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 101 1.98 Using where +Warnings: +Note 1003 select `test`.`t2`.`city` AS `city` from `test`.`t2` where `test`.`t2`.`city` = 'Helsinki' +analyze select * from t2 where city = 'helsinki'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 101 101.00 1.98 1.98 Using where +explain extended select * from t2 where city < 'Lagos'; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 101 1.98 Using where +Warnings: +Note 1003 select `test`.`t2`.`city` AS `city` from `test`.`t2` where `test`.`t2`.`city` < 'Lagos' +drop table t1_bin; +drop table t1_json; +drop table t2; +DELETE FROM mysql.column_stats; +create schema world; +use world; +set histogram_type='JSON_HB'; +set histogram_size=50; +ANALYZE TABLE Country, City, CountryLanguage persistent for all; +SELECT column_name, min_value, max_value, hist_size, hist_type, histogram FROM mysql.column_stats; +column_name min_value max_value hist_size hist_type histogram +Code ABW ZWE 48 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "ABW", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "AND", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "ASM", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "AUT", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "BFA", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "BIH", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "BRA", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "BWA", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "CHL", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "COG", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "CRI", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "CZE", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "DOM", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "ESH", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "FJI", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "GAB", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "GIN", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "GRC", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "GUM", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "HRV", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "IOT", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "ISR", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "KAZ", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "KNA", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "LBR", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "LSO", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "MAR", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "MEX", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "MMR", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "MSR", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "MYT", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "NGA", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "NPL", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "PAN", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "PNG", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "PRY", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "ROM", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "SEN", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "SLB", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "SPM", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "SWE", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "TCD", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "TKM", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "TUR", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "UKR", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "VAT", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "VNM", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "YUG", + "end": "ZWE", + "size": 0.016736402, + "ndv": 4 + } + ] +} +Country ABW ZWE 39 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "ABW", + "size": 0.020102966, + "ndv": 11 + }, + { + "start": "ATG", + "size": 0.020102966, + "ndv": 14 + }, + { + "start": "BLR", + "size": 0.006619269, + "ndv": 4 + }, + { + "start": "BRA", + "size": 0.061289532, + "ndv": 1 + }, + { + "start": "BRB", + "size": 0.020102966, + "ndv": 9 + }, + { + "start": "CHL", + "size": 0.002206423, + "ndv": 1 + }, + { + "start": "CHN", + "size": 0.0889924, + "ndv": 1 + }, + { + "start": "CIV", + "size": 0.020102966, + "ndv": 10 + }, + { + "start": "CUB", + "size": 0.020102966, + "ndv": 6 + }, + { + "start": "DEU", + "size": 0.020102966, + "ndv": 8 + }, + { + "start": "EGY", + "size": 0.020102966, + "ndv": 4 + }, + { + "start": "ESP", + "size": 0.020102966, + "ndv": 11 + }, + { + "start": "GBR", + "size": 0.020102966, + "ndv": 3 + }, + { + "start": "GIB", + "size": 0.020102966, + "ndv": 19 + }, + { + "start": "IDN", + "size": 0.012503064, + "ndv": 1 + }, + { + "start": "IND", + "size": 0.083598921, + "ndv": 1 + }, + { + "start": "IRL", + "size": 0.020102966, + "ndv": 3 + }, + { + "start": "IRQ", + "size": 0.020102966, + "ndv": 6 + }, + { + "start": "JOR", + "size": 2.451581e-4, + "ndv": 1 + }, + { + "start": "JPN", + "size": 0.060799215, + "ndv": 1 + }, + { + "start": "KAZ", + "size": 0.020102966, + "ndv": 7 + }, + { + "start": "KOR", + "size": 0.020102966, + "ndv": 16 + }, + { + "start": "MDA", + "size": 0.002451581, + "ndv": 3 + }, + { + "start": "MEX", + "size": 0.042412356, + "ndv": 1 + }, + { + "start": "MHL", + "size": 0.020102966, + "ndv": 20 + }, + { + "start": "NGA", + "size": 0.020102966, + "ndv": 4 + }, + { + "start": "NLD", + "size": 0.020102966, + "ndv": 7 + }, + { + "start": "PAK", + "size": 0.007354744, + "ndv": 4 + }, + { + "start": "PHL", + "size": 0.033341505, + "ndv": 1 + }, + { + "start": "PLW", + "size": 0.020102966, + "ndv": 8 + }, + { + "start": "PSE", + "size": 0.008580534, + "ndv": 5 + }, + { + "start": "RUS", + "size": 0.046334886, + "ndv": 1 + }, + { + "start": "RWA", + "size": 0.020102966, + "ndv": 18 + }, + { + "start": "SWE", + "size": 0.020102966, + "ndv": 16 + }, + { + "start": "TUR", + "size": 0.020102966, + "ndv": 4 + }, + { + "start": "TZA", + "size": 0.015199804, + "ndv": 4 + }, + { + "start": "USA", + "size": 0.067173327, + "ndv": 1 + }, + { + "start": "UZB", + "size": 0.020102966, + "ndv": 7 + }, + { + "start": "VNM", + "end": "ZWE", + "size": 0.018632018, + "ndv": 9 + } + ] +} +Name Afghanistan Zimbabwe 48 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "Afghanistan", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Angola", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Armenia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Bahamas", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Belgium", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Bolivia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "British Indian Ocean Territory", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Cambodia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Central African Republic", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Cocos (Keeling) Islands", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Cook Islands", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Czech Republic", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Dominican Republic", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Equatorial Guinea", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Faroe Islands", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "French Polynesia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Germany", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Grenada", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Guinea-Bissau", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Honduras", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Indonesia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Italy", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Kenya", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Latvia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Liechtenstein", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Madagascar", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Malta", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Mayotte", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Mongolia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Namibia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "New Caledonia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Niue", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Oman", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Papua New Guinea", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Poland", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Russian Federation", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Saint Lucia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Sao Tome and Principe", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Singapore", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "South Africa", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Sudan", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Switzerland", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Thailand", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Tunisia", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Uganda", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "United States Minor Outlying Islands", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Vietnam", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "Yemen", + "end": "Zimbabwe", + "size": 0.016736402, + "ndv": 4 + } + ] +} +SurfaceArea 0.40 17075400.00 48 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0.40", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "16.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "49.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "96.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "181.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "242.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "314.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "373.00", + "size": 0.020920502, + "ndv": 4 + }, + { + "start": "455.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "618.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "726.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "1102.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "2510.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "4033.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "8875.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "11295.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "17364.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "21041.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "26338.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "28896.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "36125.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "45227.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "51197.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "65301.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "75517.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "88946.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "102173.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "111369.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "120538.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "147181.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "185180.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "236800.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "245857.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "283561.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "323250.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "342000.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "438317.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "475442.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "551500.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "622984.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "756626.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "883749.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "1098581.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "1246700.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "1648195.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "2166090.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "2780400.00", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "9572900.00", + "end": "17075400.00", + "size": 0.016736402, + "ndv": 4 + } + ] +} +Population 0 1277558000 48 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0", + "size": 0.029288703, + "ndv": 1 + }, + { + "start": "50", + "size": 0.020920502, + "ndv": 4 + }, + { + "start": "2000", + "size": 0.020920502, + "ndv": 4 + }, + { + "start": "7000", + "size": 0.020920502, + "ndv": 4 + }, + { + "start": "15000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "25000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "38000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "68000", + "size": 0.020920502, + "ndv": 4 + }, + { + "start": "78000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "103000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "154000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "214000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "279000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "380200", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "444000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "599000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "817000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "1213000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "1622000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "2124000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "2583000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "3101000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "3520000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "3850000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "4380000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "4699000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "5083000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "5496000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "6276000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "7430000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "8190900", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "9169000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "10097000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "10640000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "11234000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "12878000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "15942000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "18886000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "22244000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "23930000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "28351000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "33517000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "42321000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "57680000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "66591000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "82164700", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "146934000", + "size": 0.020920502, + "ndv": 5 + }, + { + "start": "1013662000", + "end": "1277558000", + "size": 0.008368201, + "ndv": 2 + } + ] +} +Capital 1 4074 47 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "54", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "65", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "144", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "179", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "194", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "537", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "553", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "586", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "652", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "764", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "905", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "919", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "928", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "939", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "1449", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "1530", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "1792", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "1864", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2256", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2317", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2413", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2437", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2447", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2460", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2484", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2511", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2695", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2726", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2754", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2821", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2885", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "2919", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3014", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3048", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3067", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3171", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3207", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3217", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3248", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3315", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3336", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3419", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3483", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3520", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "3580", + "size": 0.021551724, + "ndv": 5 + }, + { + "start": "4068", + "end": "4074", + "size": 0.00862069, + "ndv": 2 + } + ] +} +ID 1 4079 50 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "83", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "165", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "247", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "329", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "411", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "493", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "575", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "657", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "739", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "821", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "903", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "985", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1067", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1149", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1231", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1313", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1395", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1477", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1559", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1641", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1723", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1805", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1887", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "1969", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2051", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2133", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2215", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2297", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2379", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2461", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2543", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2625", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2707", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2789", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2871", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "2953", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3035", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3117", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3199", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3281", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3363", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3445", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3527", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3609", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3691", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3773", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3855", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "3937", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "4019", + "end": "4079", + "size": 0.014954646, + "ndv": 61 + } + ] +} +Name A Coruña (La Coruña) Ãœrgenc 50 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "A Coruña (La Coruña)", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "AlmerÃa", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Araras", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Bakersfield", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Bayamo", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Bilaspur", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Bridgeport", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Cambridge", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Chatsworth", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Cizah", + "size": 0.020102966, + "ndv": 78 + }, + { + "start": "Da Nang", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Djougou", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Emeishan", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Freiburg im Breisgau", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Giugliano in Campania", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "Györ", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "Herat", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Hyesan", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Itabira", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Jiangyou", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "Kamjanets-Podilskyi", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Khouribga", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Koudougou", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Lahore", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Linköping", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Machilipatnam (Masulipatam)", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Marikina", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Miami Beach", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Moscow", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Nanded (Nander)", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Nizni Tagil", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Okazaki", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Pak Kret", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Petah Tiqwa", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Porto-Novo", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Qomsheh", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Rimini", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Salamanca", + "size": 0.020102966, + "ndv": 70 + }, + { + "start": "Sanaa", + "size": 0.020102966, + "ndv": 78 + }, + { + "start": "Secunderabad", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "Silay", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Subotica", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Tagum", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Tema", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Tongling", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Udine", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "Verona", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "Wichita Falls", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "Yibin", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "Zixing", + "end": "Ãœrgenc", + "size": 0.014954646, + "ndv": 61 + } + ] +} +Population 42 10500000 50 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "42", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "56601", + "size": 0.020102966, + "ndv": 64 + }, + { + "start": "90674", + "size": 0.020102966, + "ndv": 70 + }, + { + "start": "92700", + "size": 0.020102966, + "ndv": 76 + }, + { + "start": "94800", + "size": 0.020102966, + "ndv": 74 + }, + { + "start": "96984", + "size": 0.020102966, + "ndv": 75 + }, + { + "start": "99296", + "size": 0.020102966, + "ndv": 73 + }, + { + "start": "101144", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "103211", + "size": 0.020102966, + "ndv": 73 + }, + { + "start": "105700", + "size": 0.020102966, + "ndv": 77 + }, + { + "start": "107800", + "size": 0.020102966, + "ndv": 76 + }, + { + "start": "110048", + "size": 0.020102966, + "ndv": 76 + }, + { + "start": "113336", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "116485", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "119675", + "size": 0.020102966, + "ndv": 77 + }, + { + "start": "122700", + "size": 0.020102966, + "ndv": 77 + }, + { + "start": "125300", + "size": 0.020102966, + "ndv": 77 + }, + { + "start": "127898", + "size": 0.020102966, + "ndv": 77 + }, + { + "start": "131831", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "135621", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "139712", + "size": 0.020102966, + "ndv": 75 + }, + { + "start": "144282", + "size": 0.020102966, + "ndv": 77 + }, + { + "start": "149000", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "154976", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "161191", + "size": 0.020102966, + "ndv": 78 + }, + { + "start": "167795", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "174381", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "180650", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "187691", + "size": 0.020102966, + "ndv": 76 + }, + { + "start": "195400", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "203500", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "214901", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "224897", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "239810", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "253587", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "268013", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "285114", + "size": 0.020102966, + "ndv": 77 + }, + { + "start": "303346", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "325790", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "348845", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "374945", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "410000", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "445555", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "487148", + "size": 0.020102966, + "ndv": 79 + }, + { + "start": "559249", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "651154", + "size": 0.020102966, + "ndv": 82 + }, + { + "start": "791926", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "1040000", + "size": 0.020102966, + "ndv": 80 + }, + { + "start": "1398800", + "size": 0.020102966, + "ndv": 81 + }, + { + "start": "2641312", + "end": "10500000", + "size": 0.014954646, + "ndv": 61 + } + ] +} +Country ABW ZWE 50 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "ABW", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "ALB", + "size": 0.020325203, + "ndv": 8 + }, + { + "start": "ATG", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "AZE", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "BFA", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "BLR", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "BRN", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "CAN", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "CHN", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "CMR", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "COK", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "CXR", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "DJI", + "size": 0.020325203, + "ndv": 8 + }, + { + "start": "ERI", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "ETH", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "FSM", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "GHA", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "GNB", + "size": 0.020325203, + "ndv": 8 + }, + { + "start": "GUM", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "HUN", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "IND", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "IRQ", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "JOR", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "KEN", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "KWT", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "LCA", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "LVA", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "MDA", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "MLI", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "MNP", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "MRT", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "MYS", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "NFK", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "NLD", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "OMN", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "PHL", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "PRI", + "size": 0.020325203, + "ndv": 8 + }, + { + "start": "REU", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "RWA", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "SGP", + "size": 0.020325203, + "ndv": 8 + }, + { + "start": "SPM", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "SWZ", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "TGO", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "TON", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "TZA", + "size": 0.020325203, + "ndv": 2 + }, + { + "start": "UGA", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "USA", + "size": 0.020325203, + "ndv": 8 + }, + { + "start": "VNM", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "YUG", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "ZWE", + "end": "ZWE", + "size": 0.004065041, + "ndv": 1 + } + ] +} +Language Abhyasi [South]Mande 48 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "Abhyasi", + "size": 0.020325203, + "ndv": 12 + }, + { + "start": "Ami", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "Arabic", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "Armenian", + "size": 0.020325203, + "ndv": 11 + }, + { + "start": "Balochi", + "size": 0.020325203, + "ndv": 13 + }, + { + "start": "Belorussian", + "size": 0.020325203, + "ndv": 13 + }, + { + "start": "Bullom-sherbro", + "size": 0.020325203, + "ndv": 15 + }, + { + "start": "Chechen", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "Chinese", + "size": 0.020325203, + "ndv": 12 + }, + { + "start": "Creole English", + "size": 0.020325203, + "ndv": 2 + }, + { + "start": "Creole French", + "size": 0.020325203, + "ndv": 13 + }, + { + "start": "Dorbet", + "size": 0.012195122, + "ndv": 8 + }, + { + "start": "English", + "size": 0.06097561, + "ndv": 1 + }, + { + "start": "Eskimo Languages", + "size": 0.020325203, + "ndv": 9 + }, + { + "start": "French", + "size": 0.020325203, + "ndv": 2 + }, + { + "start": "Friuli", + "size": 0.020325203, + "ndv": 9 + }, + { + "start": "Ganda", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "German", + "size": 0.020325203, + "ndv": 11 + }, + { + "start": "GuaymÃ", + "size": 0.020325203, + "ndv": 15 + }, + { + "start": "Hehet", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "Hungarian", + "size": 0.020325203, + "ndv": 10 + }, + { + "start": "Italian", + "size": 0.020325203, + "ndv": 10 + }, + { + "start": "Kanuri", + "size": 0.020325203, + "ndv": 10 + }, + { + "start": "Khoekhoe", + "size": 0.020325203, + "ndv": 11 + }, + { + "start": "Kotokoli", + "size": 0.020325203, + "ndv": 14 + }, + { + "start": "Lithuanian", + "size": 0.020325203, + "ndv": 16 + }, + { + "start": "Macedonian", + "size": 0.020325203, + "ndv": 13 + }, + { + "start": "Malenasian Languages", + "size": 0.020325203, + "ndv": 12 + }, + { + "start": "Maranao", + "size": 0.020325203, + "ndv": 18 + }, + { + "start": "Miao", + "size": 0.020325203, + "ndv": 17 + }, + { + "start": "Muong", + "size": 0.020325203, + "ndv": 15 + }, + { + "start": "Norwegian", + "size": 0.020325203, + "ndv": 18 + }, + { + "start": "Paiwan", + "size": 0.020325203, + "ndv": 13 + }, + { + "start": "Polish", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "Portuguese", + "size": 0.020325203, + "ndv": 9 + }, + { + "start": "Romanian", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "Russian", + "size": 0.020325203, + "ndv": 10 + }, + { + "start": "Saraiki", + "size": 0.020325203, + "ndv": 10 + }, + { + "start": "Sidamo", + "size": 0.020325203, + "ndv": 12 + }, + { + "start": "Soninke", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "Spanish", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "Sunda", + "size": 0.020325203, + "ndv": 11 + }, + { + "start": "Tamil", + "size": 0.020325203, + "ndv": 11 + }, + { + "start": "Tigre", + "size": 0.020325203, + "ndv": 15 + }, + { + "start": "Turkish", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "Ukrainian", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "Uzbek", + "size": 0.020325203, + "ndv": 13 + }, + { + "start": "Yap", + "end": "[South]Mande", + "size": 0.012195122, + "ndv": 9 + } + ] +} +Percentage 0.0 99.9 47 JSON_HB { + "target_histogram_size": 50, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0.0", + "size": 0.066056911, + "ndv": 1 + }, + { + "start": "0.1", + "size": 0.020325203, + "ndv": 1 + }, + { + "start": "0.2", + "size": 0.022357724, + "ndv": 1 + }, + { + "start": "0.3", + "size": 0.017276423, + "ndv": 1 + }, + { + "start": "0.4", + "size": 0.025406504, + "ndv": 1 + }, + { + "start": "0.5", + "size": 0.020325203, + "ndv": 1 + }, + { + "start": "0.6", + "size": 0.020325203, + "ndv": 1 + }, + { + "start": "0.7", + "size": 0.020325203, + "ndv": 2 + }, + { + "start": "0.8", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "1.0", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "1.3", + "size": 0.020325203, + "ndv": 2 + }, + { + "start": "1.4", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "1.6", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "1.8", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "2.1", + "size": 0.020325203, + "ndv": 3 + }, + { + "start": "2.3", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "2.6", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "2.9", + "size": 0.020325203, + "ndv": 4 + }, + { + "start": "3.2", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "3.6", + "size": 0.020325203, + "ndv": 5 + }, + { + "start": "4.1", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "4.6", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "5.1", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "5.7", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "6.2", + "size": 0.020325203, + "ndv": 8 + }, + { + "start": "6.9", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "7.6", + "size": 0.020325203, + "ndv": 6 + }, + { + "start": "8.2", + "size": 0.020325203, + "ndv": 7 + }, + { + "start": "8.9", + "size": 0.020325203, + "ndv": 9 + }, + { + "start": "9.7", + "size": 0.020325203, + "ndv": 11 + }, + { + "start": "11.0", + "size": 0.020325203, + "ndv": 15 + }, + { + "start": "12.4", + "size": 0.020325203, + "ndv": 14 + }, + { + "start": "14.1", + "size": 0.020325203, + "ndv": 13 + }, + { + "start": "16.5", + "size": 0.020325203, + "ndv": 17 + }, + { + "start": "19.7", + "size": 0.020325203, + "ndv": 14 + }, + { + "start": "23.3", + "size": 0.020325203, + "ndv": 16 + }, + { + "start": "31.7", + "size": 0.020325203, + "ndv": 16 + }, + { + "start": "37.5", + "size": 0.020325203, + "ndv": 19 + }, + { + "start": "47.4", + "size": 0.020325203, + "ndv": 18 + }, + { + "start": "55.1", + "size": 0.020325203, + "ndv": 19 + }, + { + "start": "66.7", + "size": 0.020325203, + "ndv": 18 + }, + { + "start": "78.1", + "size": 0.020325203, + "ndv": 15 + }, + { + "start": "86.2", + "size": 0.020325203, + "ndv": 18 + }, + { + "start": "90.7", + "size": 0.020325203, + "ndv": 15 + }, + { + "start": "95.1", + "size": 0.020325203, + "ndv": 14 + }, + { + "start": "97.6", + "size": 0.020325203, + "ndv": 14 + }, + { + "start": "99.9", + "end": "99.9", + "size": 0.015243902, + "ndv": 1 + } + ] +} +analyze select * from Country use index () where Code between 'BBC' and 'GGG'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE Country ALL NULL NULL NULL NULL 239 239.00 24.58 25.52 Using where +analyze select * from Country use index () where Code < 'BBC'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE Country ALL NULL NULL NULL NULL 239 239.00 8.37 7.11 Using where +set histogram_type=@save_histogram_type; +set histogram_size=@save_histogram_size; +DROP SCHEMA world; +use test; +create table t10 ( +a varchar(10) +); +# +# Histograms are not collected for empty tables: +# +analyze table t10 persistent for all; +Table Op Msg_type Msg_text +test.t10 analyze status Engine-independent statistics collected +test.t10 analyze status Table is already up to date +select histogram +from mysql.column_stats where table_name='t10' and db_name=database(); +histogram +NULL +# +# Try with n_buckets > n_rows +# +insert into t10 values ('Berlin'),('Paris'),('Rome'); +set histogram_size=10, histogram_type='json_hb'; +analyze table t10 persistent for all; +Table Op Msg_type Msg_text +test.t10 analyze status Engine-independent statistics collected +test.t10 analyze status OK +select histogram +from mysql.column_stats where table_name='t10' and db_name=database(); +histogram +{ + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "Berlin", + "size": 0.333333333, + "ndv": 1 + }, + { + "start": "Paris", + "size": 0.333333333, + "ndv": 1 + }, + { + "start": "Rome", + "end": "Rome", + "size": 0.333333333, + "ndv": 1 + } + ] +} +drop table t10; +# +# MDEV-26590: Stack smashing/buffer overflow in Histogram_json_hb::parse upon UPDATE on table with long VARCHAR +# +CREATE TABLE t1 (b INT, a VARCHAR(3176)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +SET histogram_type= JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1; +b a +1 foo +2 bar +drop table t1; +# +# MDEV-26589: Assertion failure upon DECODE_HISTOGRAM with NULLs in first column +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (NULL,1), (NULL,2); +SET histogram_type = JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT DECODE_HISTOGRAM(hist_type, histogram) from mysql.column_stats; +DECODE_HISTOGRAM(hist_type, histogram) +NULL +{ + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.5, + "ndv": 1 + }, + { + "start": "2", + "end": "2", + "size": 0.5, + "ndv": 1 + } + ] +} +drop table t1; +# +# MDEV-26711: Values in JSON histograms are not properly quoted +# +create table t1 (a varchar(32)); +insert into t1 values ('this is "quoted" text'); +set histogram_type= JSON_HB; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from t1 where a = 'foo'; +a +drop table t1; +# +# MDEV-26724 Endless loop in json_escape_to_string upon ... empty string +# +CREATE TABLE t1 (f VARCHAR(8)); +INSERT INTO t1 VALUES ('a'),(''),('b'); +SET histogram_type=JSON_HB; +ANALYZE TABLE t PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t analyze Error Table 'test.t' doesn't exist +test.t analyze status Operation failed +select * from t1; +f +a + +b +drop table t1; +create table t1 (a char(1)) character set latin1; +insert into t1 values (0xD1); +select hex(a) from t1; +hex(a) +D1 +set histogram_type='json_hb'; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select decode_histogram(hist_type, histogram) +from mysql.column_stats +where db_name=database() and table_name='t1'; +decode_histogram(hist_type, histogram) +{ + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "Ñ", + "end": "Ñ", + "size": 1, + "ndv": 1 + } + ] +} +select * from t1; +a +Ñ +drop table t1; +# +# Another testcase: use a character that cannot be represented in utf8: +# Also, now it's testcase for: +# MDEV-26764: JSON_HB Histograms: handle BINARY and unassigned characters +# +create table t1 ( a varchar(100) character set cp1251); +insert into t1 values ( _cp1251 x'88'),( _cp1251 x'88'), ( _cp1251 x'88'); +insert into t1 values ( _cp1251 x'98'),( _cp1251 x'98'); +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select hist_type, histogram +from mysql.column_stats +where db_name=database() and table_name='t1'; +hist_type histogram +JSON_HB { + "target_histogram_size": 10, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "€", + "size": 0.6, + "ndv": 1 + }, + { + "start_hex": "98", + "end_hex": "98", + "size": 0.4, + "ndv": 1 + } + ] +} +analyze select * from t1 where a=_cp1251 x'88'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 5.00 60.00 60.00 Using where +drop table t1; +# +# ASAN use-after-poison my_strnxfrm_simple_internal / Histogram_json_hb::range_selectivity ... +# (Just the testcase) +# +CREATE TABLE t1 (f CHAR(8)); +INSERT INTO t1 VALUES ('foo'),('bar'); +SET histogram_type = JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +SELECT * FROM t1 WHERE f > 'qux'; +f +DROP TABLE t1; +# +# MDEV-26737: Outdated VARIABLE_COMMENT for HISTOGRAM_TYPE in I_S.SYSTEM_VARIABLES +# +select variable_comment from information_schema.system_variables where VARIABLE_NAME='HISTOGRAM_TYPE'; +variable_comment +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, JSON_HB - height-balanced, stored as JSON. +# +# MDEV-26709: JSON histogram may contain bucketS than histogram_size allows +# +create table t1 (a int); +insert into t1 values (1),(3),(5),(7); +insert into t1 select 2 from seq_1_to_25; +insert into t1 select 4 from seq_1_to_25; +insert into t1 select 6 from seq_1_to_25; +set histogram_size=4, histogram_type=JSON_HB; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select histogram from mysql.column_stats where table_name = 't1'; +histogram +{ + "target_histogram_size": 4, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "1", + "size": 0.253164557, + "ndv": 2 + }, + { + "start": "2", + "size": 0.253164557, + "ndv": 3 + }, + { + "start": "4", + "size": 0.253164557, + "ndv": 3 + }, + { + "start": "6", + "end": "7", + "size": 0.240506329, + "ndv": 2 + } + ] +} +drop table t1; +# +# MDEV-26750: Estimation for filtered rows is far off with JSON_HB histogram +# +create table t1 (c char(8)); +insert into t1 values ('1x'); +insert into t1 values ('1x'); +insert into t1 values ('1xx'); +insert into t1 values ('0xx'); +insert into t1 select * from t1; +insert into t1 select * from t1; +set histogram_type= JSON_HB; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze +select c from t1 where c > '1'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 16 16.00 75.00 75.00 Using where +drop table t1; +# +# MDEV-26849: JSON Histograms: point selectivity estimates are off for non-existent values +# +create table t0(a int); +insert into t0 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1(a int); +insert into t1 select 100*A.a from t0 A, t0 B, t0 C; +select a, count(*) from t1 group by a order by a; +a count(*) +0 100 +100 100 +200 100 +300 100 +400 100 +500 100 +600 100 +700 100 +800 100 +900 100 +set histogram_type=json_hb, histogram_size=default; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from mysql.column_stats where table_name='t1'; +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 900 0.0000 4.0000 100.0000 10 JSON_HB { + "target_histogram_size": 254, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start": "0", + "size": 0.1, + "ndv": 1 + }, + { + "start": "100", + "size": 0.1, + "ndv": 1 + }, + { + "start": "200", + "size": 0.1, + "ndv": 1 + }, + { + "start": "300", + "size": 0.1, + "ndv": 1 + }, + { + "start": "400", + "size": 0.1, + "ndv": 1 + }, + { + "start": "500", + "size": 0.1, + "ndv": 1 + }, + { + "start": "600", + "size": 0.1, + "ndv": 1 + }, + { + "start": "700", + "size": 0.1, + "ndv": 1 + }, + { + "start": "800", + "size": 0.1, + "ndv": 1 + }, + { + "start": "900", + "end": "900", + "size": 0.1, + "ndv": 1 + } + ] +} +analyze select * from t1 where a=0; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1000.00 10.00 10.00 Using where +analyze select * from t1 where a=50; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1000.00 0.10 0.00 Using where +analyze select * from t1 where a=70; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1000.00 0.10 0.00 Using where +analyze select * from t1 where a=100; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1000.00 10.00 10.00 Using where +analyze select * from t1 where a=150; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1000.00 0.10 0.00 Using where +analyze select * from t1 where a=200; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1000.00 10.00 10.00 Using where +drop table t0,t1; +# +# MDEV-26892: JSON histograms become invalid with a specific (corrupt) value in t +# +create table t1 (a varchar(32)) DEFAULT CHARSET=cp1257; +set histogram_type= JSON_HB, histogram_size= 1; +insert into t1 values ('foo'),(unhex('9C')); +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select * from t1; +a +foo +? +drop table t1; +# +# MDEV-26911: Unexpected ER_DUP_KEY, ASAN errors, double free detected in tcache with JSON_HB histogram +# +SET histogram_type= JSON_HB; +CREATE TABLE t1 (pk INT AUTO_INCREMENT, f VARCHAR(8), PRIMARY KEY (pk)); +INSERT INTO t1 (f) VALUES ('foo'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +ALTER TABLE t1 MODIFY f TEXT, ORDER BY pk; +INSERT INTO t1 (f) VALUES ('bar'); +DROP TABLE t1; +# +# MDEV-26886: Estimation for filtered rows less precise with JSON histogram +# +create table t1 (a tinyint) as select if(seq%3,seq,0) as a from seq_1_to_100; +select count(*) from t1 where a <= 0; +count(*) +33 +set histogram_type = JSON_HB, histogram_size=default; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze select * from t1 where a <= 0; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 33.00 33.00 Using where +analyze select * from t1 where a < 0; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 1.00 0.00 Using where +analyze select * from t1 where a > 0; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 67.00 67.00 Using where +analyze select * from t1 where a >= 0; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 100.00 100.00 Using where +drop table t1; +# +# More test coverage +# +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1(a int); +insert into t1 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C; +create table t2 (a int); +insert into t2 select 1 from t1; +insert into t2 select (a+1)*10 from t0; +insert into t2 values (0); +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +analyze select * from t2 where a < 1; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1011 1011.00 0.10 0.10 Using where +analyze select * from t2 where a =100; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 1011 1011.00 0.10 0.10 Using where +drop table t0,t1,t2; +# +# MDEV-27230: Estimation for filtered rows less precise ... +# +create table t1 (a char(1)); +insert into t1 select chr(seq%26+97) from seq_1_to_50; +insert into t1 select ':' from t1; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze select COUNT(*) FROM t1 WHERE a <> 'a'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 99.00 99.00 Using where +analyze select COUNT(*) FROM t1 WHERE a < 'a'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 100 100.00 50.00 50.00 Using where +drop table t1; +# +# MDEV-27229: Estimation for filtered rows less precise ... #5 +# +create table t1 (id int, a varchar(8)); +insert into t1 select seq, 'bar' from seq_1_to_100; +insert into t1 select id, 'qux' from t1; +set histogram_type=JSON_HB; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze select COUNT(*) FROM t1 WHERE a > 'foo'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 50.00 50.00 Using where +analyze select COUNT(*) FROM t1 WHERE a > 'aaa'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 100.00 100.00 Using where +analyze select COUNT(*) FROM t1 WHERE a >='aaa'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 100.00 100.00 Using where +analyze select COUNT(*) FROM t1 WHERE a > 'bar'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 50.00 50.00 Using where +analyze select COUNT(*) FROM t1 WHERE a >='bar'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 100.00 100.00 Using where +analyze select COUNT(*) FROM t1 WHERE a < 'aaa'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 0.50 0.00 Using where +analyze select COUNT(*) FROM t1 WHERE a <='aaa'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 0.50 0.00 Using where +analyze select COUNT(*) FROM t1 WHERE a < 'bar'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 0.50 0.00 Using where +analyze select COUNT(*) FROM t1 WHERE a <='bar'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 200 200.00 50.00 50.00 Using where +drop table t1; +# +# MDEV-27243: Estimation for filtered rows less precise ... #7 +# (Testcase only) +CREATE TABLE t1 (f TIME); +INSERT INTO t1 SELECT IF(seq%2,'00:00:00',SEC_TO_TIME(seq+7200)) FROM seq_1_to_1000; +SET histogram_type= JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +ANALYZE SELECT * FROM t1 WHERE f > '00:01:00'; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 1000.00 50.00 50.00 Using where +drop table t1; +# +# MDEV-26901: Estimation for filtered rows less precise ... #4 +# +create table t1 (f int); +insert into t1 values +(7),(5),(0),(5),(112),(9),(9),(7),(5),(9), +(1),(7),(0),(6),(6),(2),(1),(6),(169),(7); +select f from t1 where f in (77, 1, 144, 73, 14, 12); +f +1 +1 +set histogram_type= JSON_HB; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze select f from t1 where f in (77, 1, 144, 73, 14, 12); +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 20 20.00 10.00 10.00 Using where +drop table t1; +# +# Test that histograms over BIT fields use hex +# +create table t1 (a BIT(64)); +insert into t1 values +(x'01'),(x'10'),(x'BE562B1A99001918'); +set histogram_type= JSON_HB; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +select histogram +from mysql.column_stats where table_name='t1' and db_name=database(); +histogram +{ + "target_histogram_size": 254, + "collected_at": "REPLACED", + "collected_by": "REPLACED", + "histogram_hb": [ + { + "start_hex": "0000000000000001", + "size": 0.333333333, + "ndv": 1 + }, + { + "start_hex": "0000000000000010", + "size": 0.333333333, + "ndv": 1 + }, + { + "start_hex": "BE562B1A99001918", + "end_hex": "BE562B1A99001918", + "size": 0.333333333, + "ndv": 1 + } + ] +} +drop table t1; diff --git a/mysql-test/main/statistics_json.test b/mysql-test/main/statistics_json.test new file mode 100644 index 00000000000..10583620cda --- /dev/null +++ b/mysql-test/main/statistics_json.test @@ -0,0 +1,462 @@ +--echo # +--echo # Test that we can store JSON arrays in histogram field mysql.column_stats when histogram_type=JSON +--echo # + +let $histogram_type_override='JSON_HB'; +--source statistics.test + +--source include/have_innodb.inc +--source include/have_stat_tables.inc +--source include/have_sequence.inc +--disable_warnings +drop table if exists t1; +--enable_warnings + +set @save_histogram_type=@@histogram_type; +set @save_histogram_size=@@histogram_size; + +call mtr.add_suppression("Failed to parse histogram for table .*"); +create table ten(a int primary key); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +set histogram_size=100; +set histogram_type='double_prec_hb'; +create table t1_bin (a varchar(255)); +insert into t1_bin select concat('a-', a) from ten; +analyze table t1_bin persistent for all; +select hex(histogram) from mysql.column_stats where table_name='t1_bin'; +explain extended select * from t1_bin where a between 'a-3a' and 'zzzzzzzzz'; +analyze select * from t1_bin where a between 'a-3a' and 'zzzzzzzzz'; + +set histogram_type=json_hb; +create table t1_json (a varchar(255)); +insert into t1_json select concat('a-', a) from ten; +analyze table t1_json persistent for all; +--source include/json_hb_histogram.inc +select * from mysql.column_stats where table_name='t1_json'; +explain extended select * from t1_json where a between 'a-3a' and 'zzzzzzzzz'; +analyze select * from t1_json where a between 'a-3a' and 'zzzzzzzzz'; +explain extended select * from t1_json where a < 'b-1a'; +analyze select * from t1_json where a > 'zzzzzzzzz'; + +drop table ten; + +# +# Test different valid JSON strings that are invalid histograms. +# +UPDATE mysql.column_stats +SET histogram='["not-what-you-expect"]' WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":"not-histogram"}' WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":["not-a-bucket"]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"no-expected-members":1}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":{}}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":"aaa", "size":"not-an-integer"}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":"aaa", "size":0.25}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[{"start":"aaa", "size":0.25, "ndv":1}]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +UPDATE mysql.column_stats +SET histogram='{"histogram_hb":[]}' +WHERE table_name='t1_json'; +FLUSH TABLES; +explain select * from t1_json limit 1; + +--source include/have_sequence.inc +create table t2 ( + city varchar(100) +); +set histogram_size=50; +insert into t2 select 'Moscow' from seq_1_to_99; +insert into t2 select 'Helsinki' from seq_1_to_2; +set histogram_type=json_hb; +analyze table t2 persistent for all; +explain extended select * from t2 where city = 'Moscow'; +analyze select * from t2 where city = 'Moscow'; +explain extended select * from t2 where city = 'Helsinki'; +analyze select * from t2 where city = 'helsinki'; +explain extended select * from t2 where city < 'Lagos'; + +drop table t1_bin; +drop table t1_json; +drop table t2; + +DELETE FROM mysql.column_stats; + +create schema world; +use world; +--disable_query_log +--disable_result_log +--disable_warnings +--source include/world_schema_utf8.inc +--source include/world.inc +--enable_warnings +--enable_result_log +--enable_query_log + +set histogram_type='JSON_HB'; +set histogram_size=50; +--disable_result_log +ANALYZE TABLE Country, City, CountryLanguage persistent for all; +--enable_result_log + +--source include/histogram_replaces.inc +SELECT column_name, min_value, max_value, hist_size, hist_type, histogram FROM mysql.column_stats; +analyze select * from Country use index () where Code between 'BBC' and 'GGG'; +analyze select * from Country use index () where Code < 'BBC'; + +set histogram_type=@save_histogram_type; +set histogram_size=@save_histogram_size; + +DROP SCHEMA world; +use test; + +create table t10 ( + a varchar(10) +); + +--echo # +--echo # Histograms are not collected for empty tables: +--echo # +analyze table t10 persistent for all; +select histogram +from mysql.column_stats where table_name='t10' and db_name=database(); + +--echo # +--echo # Try with n_buckets > n_rows +--echo # +insert into t10 values ('Berlin'),('Paris'),('Rome'); +set histogram_size=10, histogram_type='json_hb'; +analyze table t10 persistent for all; +--source include/histogram_replaces.inc +select histogram +from mysql.column_stats where table_name='t10' and db_name=database(); +drop table t10; + +--echo # +--echo # MDEV-26590: Stack smashing/buffer overflow in Histogram_json_hb::parse upon UPDATE on table with long VARCHAR +--echo # + +CREATE TABLE t1 (b INT, a VARCHAR(3176)); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +SET histogram_type= JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +SELECT * FROM t1; +drop table t1; + +--echo # +--echo # MDEV-26589: Assertion failure upon DECODE_HISTOGRAM with NULLs in first column +--echo # + +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (NULL,1), (NULL,2); +SET histogram_type = JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +--source include/histogram_replaces.inc +SELECT DECODE_HISTOGRAM(hist_type, histogram) from mysql.column_stats; +drop table t1; + +--echo # +--echo # MDEV-26711: Values in JSON histograms are not properly quoted +--echo # + +create table t1 (a varchar(32)); +insert into t1 values ('this is "quoted" text'); +set histogram_type= JSON_HB; +analyze table t1 persistent for all; +select * from t1 where a = 'foo'; +drop table t1; + +--echo # +--echo # MDEV-26724 Endless loop in json_escape_to_string upon ... empty string +--echo # +CREATE TABLE t1 (f VARCHAR(8)); +INSERT INTO t1 VALUES ('a'),(''),('b'); +SET histogram_type=JSON_HB; +ANALYZE TABLE t PERSISTENT FOR ALL; +select * from t1; +drop table t1; + +create table t1 (a char(1)) character set latin1; +insert into t1 values (0xD1); +select hex(a) from t1; +set histogram_type='json_hb'; +analyze table t1 persistent for all; + +--source include/histogram_replaces.inc +select decode_histogram(hist_type, histogram) +from mysql.column_stats +where db_name=database() and table_name='t1'; + +select * from t1; +drop table t1; + +--echo # +--echo # Another testcase: use a character that cannot be represented in utf8: +--echo # Also, now it's testcase for: +--echo # MDEV-26764: JSON_HB Histograms: handle BINARY and unassigned characters +--echo # +create table t1 ( a varchar(100) character set cp1251); +insert into t1 values ( _cp1251 x'88'),( _cp1251 x'88'), ( _cp1251 x'88'); +insert into t1 values ( _cp1251 x'98'),( _cp1251 x'98'); +analyze table t1 persistent for all; + +--source include/histogram_replaces.inc +select hist_type, histogram +from mysql.column_stats +where db_name=database() and table_name='t1'; + +analyze select * from t1 where a=_cp1251 x'88'; + +drop table t1; + +--echo # +--echo # ASAN use-after-poison my_strnxfrm_simple_internal / Histogram_json_hb::range_selectivity ... +--echo # (Just the testcase) +--echo # + +CREATE TABLE t1 (f CHAR(8)); +INSERT INTO t1 VALUES ('foo'),('bar'); + +SET histogram_type = JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; + +SELECT * FROM t1 WHERE f > 'qux'; +DROP TABLE t1; + +--echo # +--echo # MDEV-26737: Outdated VARIABLE_COMMENT for HISTOGRAM_TYPE in I_S.SYSTEM_VARIABLES +--echo # +select variable_comment from information_schema.system_variables where VARIABLE_NAME='HISTOGRAM_TYPE'; + +--echo # +--echo # MDEV-26709: JSON histogram may contain bucketS than histogram_size allows +--echo # +create table t1 (a int); +insert into t1 values (1),(3),(5),(7); +insert into t1 select 2 from seq_1_to_25; +insert into t1 select 4 from seq_1_to_25; +insert into t1 select 6 from seq_1_to_25; + +set histogram_size=4, histogram_type=JSON_HB; +analyze table t1 persistent for all; + +--source include/json_hb_histogram.inc +select histogram from mysql.column_stats where table_name = 't1'; + +drop table t1; + +--echo # +--echo # MDEV-26750: Estimation for filtered rows is far off with JSON_HB histogram +--echo # +create table t1 (c char(8)); + +insert into t1 values ('1x'); +insert into t1 values ('1x'); +insert into t1 values ('1xx'); +insert into t1 values ('0xx'); +insert into t1 select * from t1; +insert into t1 select * from t1; + +set histogram_type= JSON_HB; +analyze table t1 persistent for all; +analyze +select c from t1 where c > '1'; + +drop table t1; + +--echo # +--echo # MDEV-26849: JSON Histograms: point selectivity estimates are off for non-existent values +--echo # + +create table t0(a int); +insert into t0 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1(a int); +insert into t1 select 100*A.a from t0 A, t0 B, t0 C; +select a, count(*) from t1 group by a order by a; +set histogram_type=json_hb, histogram_size=default; +analyze table t1 persistent for all; +--source include/json_hb_histogram.inc +select * from mysql.column_stats where table_name='t1'; +analyze select * from t1 where a=0; +analyze select * from t1 where a=50; +analyze select * from t1 where a=70; +analyze select * from t1 where a=100; +analyze select * from t1 where a=150; +analyze select * from t1 where a=200; + +drop table t0,t1; + +--echo # +--echo # MDEV-26892: JSON histograms become invalid with a specific (corrupt) value in t +--echo # +create table t1 (a varchar(32)) DEFAULT CHARSET=cp1257; +set histogram_type= JSON_HB, histogram_size= 1; +insert into t1 values ('foo'),(unhex('9C')); +analyze table t1 persistent for all; + +select * from t1; +drop table t1; + +--echo # +--echo # MDEV-26911: Unexpected ER_DUP_KEY, ASAN errors, double free detected in tcache with JSON_HB histogram +--echo # + +SET histogram_type= JSON_HB; + +CREATE TABLE t1 (pk INT AUTO_INCREMENT, f VARCHAR(8), PRIMARY KEY (pk)); +INSERT INTO t1 (f) VALUES ('foo'); +ANALYZE TABLE t1 PERSISTENT FOR ALL; +ALTER TABLE t1 MODIFY f TEXT, ORDER BY pk; +INSERT INTO t1 (f) VALUES ('bar'); +DROP TABLE t1; + +--echo # +--echo # MDEV-26886: Estimation for filtered rows less precise with JSON histogram +--echo # +create table t1 (a tinyint) as select if(seq%3,seq,0) as a from seq_1_to_100; +select count(*) from t1 where a <= 0; + +set histogram_type = JSON_HB, histogram_size=default; +analyze table t1 persistent for all; +analyze select * from t1 where a <= 0; +analyze select * from t1 where a < 0; +analyze select * from t1 where a > 0; +analyze select * from t1 where a >= 0; +drop table t1; + + +--echo # +--echo # More test coverage +--echo # +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1(a int); +insert into t1 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C; + +create table t2 (a int); +insert into t2 select 1 from t1; +insert into t2 select (a+1)*10 from t0; +insert into t2 values (0); + +analyze table t2 persistent for all; +analyze select * from t2 where a < 1; +analyze select * from t2 where a =100; + +drop table t0,t1,t2; + +--echo # +--echo # MDEV-27230: Estimation for filtered rows less precise ... +--echo # +create table t1 (a char(1)); +insert into t1 select chr(seq%26+97) from seq_1_to_50; +insert into t1 select ':' from t1; +analyze table t1 persistent for all; +analyze select COUNT(*) FROM t1 WHERE a <> 'a'; +analyze select COUNT(*) FROM t1 WHERE a < 'a'; +drop table t1; + +--echo # +--echo # MDEV-27229: Estimation for filtered rows less precise ... #5 +--echo # +create table t1 (id int, a varchar(8)); +insert into t1 select seq, 'bar' from seq_1_to_100; +insert into t1 select id, 'qux' from t1; + +set histogram_type=JSON_HB; +analyze table t1 persistent for all; +analyze select COUNT(*) FROM t1 WHERE a > 'foo'; + +analyze select COUNT(*) FROM t1 WHERE a > 'aaa'; +analyze select COUNT(*) FROM t1 WHERE a >='aaa'; + +analyze select COUNT(*) FROM t1 WHERE a > 'bar'; +analyze select COUNT(*) FROM t1 WHERE a >='bar'; + +# Can enable these after get_avg_frequency issue is resolved: +analyze select COUNT(*) FROM t1 WHERE a < 'aaa'; +analyze select COUNT(*) FROM t1 WHERE a <='aaa'; +analyze select COUNT(*) FROM t1 WHERE a < 'bar'; + +analyze select COUNT(*) FROM t1 WHERE a <='bar'; + +drop table t1; + +--echo # +--echo # MDEV-27243: Estimation for filtered rows less precise ... #7 +--echo # (Testcase only) + +CREATE TABLE t1 (f TIME); +INSERT INTO t1 SELECT IF(seq%2,'00:00:00',SEC_TO_TIME(seq+7200)) FROM seq_1_to_1000; + +SET histogram_type= JSON_HB; +ANALYZE TABLE t1 PERSISTENT FOR ALL; +ANALYZE SELECT * FROM t1 WHERE f > '00:01:00'; +drop table t1; + +--echo # +--echo # MDEV-26901: Estimation for filtered rows less precise ... #4 +--echo # +create table t1 (f int); +insert into t1 values + (7),(5),(0),(5),(112),(9),(9),(7),(5),(9), + (1),(7),(0),(6),(6),(2),(1),(6),(169),(7); + +select f from t1 where f in (77, 1, 144, 73, 14, 12); + +set histogram_type= JSON_HB; +analyze table t1 persistent for all; + +analyze select f from t1 where f in (77, 1, 144, 73, 14, 12); +drop table t1; + + +--echo # +--echo # Test that histograms over BIT fields use hex +--echo # +create table t1 (a BIT(64)); +insert into t1 values + (x'01'),(x'10'),(x'BE562B1A99001918'); +set histogram_type= JSON_HB; +analyze table t1 persistent for all; +--source include/json_hb_histogram.inc +select histogram +from mysql.column_stats where table_name='t1' and db_name=database(); + +drop table t1; + diff --git a/mysql-test/main/statistics_upgrade.result b/mysql-test/main/statistics_upgrade.result new file mode 100644 index 00000000000..6e287115245 --- /dev/null +++ b/mysql-test/main/statistics_upgrade.result @@ -0,0 +1,87 @@ +call mtr.add_suppression("Incorrect definition of table mysql.column_stats:.*"); +set histogram_type=single_prec_hb; +create table t1 (a int); +insert into t1 select seq from seq_1_to_100; +analyze table t1 persistent for all; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +set histogram_type=double_prec_hb, histogram_size=20; +create table t2 (a int); +insert into t2 select seq from seq_1_to_100; +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +CREATE TABLE IF NOT EXISTS t3 ( +db_name varchar(64) NOT NULL, +table_name varchar(64) NOT NULL, +column_name varchar(64) NOT NULL, +min_value varbinary(255) DEFAULT NULL, +max_value varbinary(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=Aria transactional=0 CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns'; +insert into t3 select * from mysql.column_stats; +create table t4 like t3; +insert into t4 select * from t3; +drop table mysql.column_stats; +alter table t3 rename mysql.column_stats; +# Run mysql_upgrade +mysql.innodb_index_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.innodb_table_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.transaction_registry +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.innodb_index_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.innodb_table_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.transaction_registry +Error : Unknown storage engine 'InnoDB' +error : Corrupt +# +# Table definition after upgrade: +# +show create table mysql.column_stats; +Table Create Table +column_stats CREATE TABLE `column_stats` ( + `db_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, + `column_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(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(3) unsigned DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') COLLATE utf8mb3_bin DEFAULT NULL, + `histogram` longblob DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' +select +A.db_name, +A.table_name, +A.hist_type = B.hist_type as hist_type_equal, +A.histogram = B.histogram as histogram_equal +from +t4 A +left join +mysql.column_stats B on A.db_name=B.db_name and +A.table_name=B.table_name and +A.column_name=B.column_name; +db_name table_name hist_type_equal histogram_equal +test t1 1 1 +test t2 1 1 +drop table t1,t2,t4; diff --git a/mysql-test/main/statistics_upgrade.test b/mysql-test/main/statistics_upgrade.test new file mode 100644 index 00000000000..705cf65e053 --- /dev/null +++ b/mysql-test/main/statistics_upgrade.test @@ -0,0 +1,67 @@ +-- source include/mysql_upgrade_preparation.inc +--source include/have_sequence.inc + +call mtr.add_suppression("Incorrect definition of table mysql.column_stats:.*"); + +set histogram_type=single_prec_hb; +create table t1 (a int); +insert into t1 select seq from seq_1_to_100; +analyze table t1 persistent for all; + +set histogram_type=double_prec_hb, histogram_size=20; +create table t2 (a int); +insert into t2 select seq from seq_1_to_100; +analyze table t2 persistent for all; + +# Create a table with old definition +CREATE TABLE IF NOT EXISTS t3 ( + db_name varchar(64) NOT NULL, + table_name varchar(64) NOT NULL, + column_name varchar(64) NOT NULL, + min_value varbinary(255) DEFAULT NULL, + max_value varbinary(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=Aria transactional=0 CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Columns'; + +# Copy the data there +insert into t3 select * from mysql.column_stats; + +create table t4 like t3; +insert into t4 select * from t3; + +# Put the old table in place of mysql.column_stats + +drop table mysql.column_stats; +alter table t3 rename mysql.column_stats; +--echo # Run mysql_upgrade + +--exec $MYSQL_UPGRADE --upgrade-system-tables --force --silent 2>&1 + +let $MYSQLD_DATADIR= `select @@datadir`; +--file_exists $MYSQLD_DATADIR/mysql_upgrade_info +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info + +--echo # +--echo # Table definition after upgrade: +--echo # +show create table mysql.column_stats; + +select + A.db_name, + A.table_name, + A.hist_type = B.hist_type as hist_type_equal, + A.histogram = B.histogram as histogram_equal +from + t4 A + left join + mysql.column_stats B on A.db_name=B.db_name and + A.table_name=B.table_name and + A.column_name=B.column_name; + +drop table t1,t2,t4; diff --git a/mysql-test/main/statistics_upgrade_not_done.result b/mysql-test/main/statistics_upgrade_not_done.result new file mode 100644 index 00000000000..902bf25c242 --- /dev/null +++ b/mysql-test/main/statistics_upgrade_not_done.result @@ -0,0 +1,44 @@ +# Create the old-version of the table +call mtr.add_suppression(".*Incorrect definition of table mysql.column_stats:.*"); +alter table mysql.column_stats rename test.t1; +CREATE TABLE mysql.column_stats ( +`db_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, +`table_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, +`column_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, +`min_value` varbinary(255) DEFAULT NULL, +`max_value` varbinary(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(3) unsigned DEFAULT NULL, +`hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8mb3_bin DEFAULT NULL, +`histogram` varbinary(255) DEFAULT NULL, +PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns'; +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO mysql.column_stats VALUES +('test','t0','a','0','9',0.0000,4.0000,1.0000,5,'DOUBLE_PREC_HB', x'5555AAAA00'); +flush tables; +analyze select * from t0 where a<3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 10 10.00 100.00 30.00 Using where +# restart +select hex(histogram) from mysql.column_stats where table_name='t0' and db_name='test'; +hex(histogram) +5555AAAA00 +analyze select * from t0 where a<3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 10 10.00 100.00 30.00 Using where +create table t2 (a int); +# This currently just pretends that the histogram was collected. +analyze table t2 persistent for all; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status Table is already up to date +select * from mysql.column_stats where table_name='t2' and db_name='test'; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +analyze select * from t0 where a<3; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 SIMPLE t0 ALL NULL NULL NULL NULL 10 10.00 33.33 30.00 Using where +drop table t0, t1, t2; diff --git a/mysql-test/main/statistics_upgrade_not_done.test b/mysql-test/main/statistics_upgrade_not_done.test new file mode 100644 index 00000000000..a74a5f35d83 --- /dev/null +++ b/mysql-test/main/statistics_upgrade_not_done.test @@ -0,0 +1,57 @@ +--source include/not_embedded.inc +--source include/mysql_upgrade_preparation.inc +--source include/have_innodb.inc + +# +# This is like the upgrade test in statistics_upgrade.test, except that we also +# check what happens if one doesn't do the upgrade and attempts to use the new +# server with the old mysql.column_stats table +# +--echo # Create the old-version of the table + +call mtr.add_suppression(".*Incorrect definition of table mysql.column_stats:.*"); + +alter table mysql.column_stats rename test.t1; + +CREATE TABLE mysql.column_stats ( + `db_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, + `table_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, + `column_name` varchar(64) COLLATE utf8mb3_bin NOT NULL, + `min_value` varbinary(255) DEFAULT NULL, + `max_value` varbinary(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(3) unsigned DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') COLLATE utf8mb3_bin DEFAULT NULL, + `histogram` varbinary(255) DEFAULT NULL, + PRIMARY KEY (`db_name`,`table_name`,`column_name`) +) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns'; + +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO mysql.column_stats VALUES +('test','t0','a','0','9',0.0000,4.0000,1.0000,5,'DOUBLE_PREC_HB', x'5555AAAA00'); + +flush tables; +analyze select * from t0 where a<3; + +# Restart the server + +--source include/restart_mysqld.inc + +select hex(histogram) from mysql.column_stats where table_name='t0' and db_name='test'; +analyze select * from t0 where a<3; + +create table t2 (a int); +-- echo # This currently just pretends that the histogram was collected. +analyze table t2 persistent for all; +select * from mysql.column_stats where table_name='t2' and db_name='test'; + +--exec $MYSQL_UPGRADE --upgrade-system-tables --force --silent 2>&1 +let $MYSQLD_DATADIR= `select @@datadir`; +--file_exists $MYSQLD_DATADIR/mysql_upgrade_info +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info + +analyze select * from t0 where a<3; +drop table t0, t1, t2; diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result index 5f38d2a5d35..980db9f3ee1 100644 --- a/mysql-test/main/subselect_mat.result +++ b/mysql-test/main/subselect_mat.result @@ -61,7 +61,7 @@ explain extended select * from t1 where a1 in (select b1 from t2 where b1 > '0'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1`)))) select * from t1 where a1 in (select b1 from t2 where b1 > '0'); @@ -72,7 +72,7 @@ explain extended select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1`)))) select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1); @@ -83,7 +83,7 @@ explain extended select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2); @@ -94,7 +94,7 @@ explain extended select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where; Using temporary +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,min(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`b1` > '0' group by `test`.`t2`.`b1` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`min(b2)`)))) select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1); @@ -321,7 +321,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 4 MATERIALIZED t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` > '0' ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery2>`.`b1` and `test`.`t1`.`a2` = `<subquery2>`.`b2`)))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#3 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#4 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery4>`.`b1` and `test`.`t3`.`c2` = `<subquery4>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery3>`.`c1` and `test`.`t1`.`a2` = `<subquery3>`.`c2`)))) select * from t1 @@ -451,8 +451,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 5 MATERIALIZED t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where -3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),(`test`.`t1`.`a1`,`test`.`t1`.`a2`) in ( <materialize> (/* select#4 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#5 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery5>`.`b1` and `test`.`t3`.`c2` = `<subquery5>`.`b2`)))) ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where `test`.`t1`.`a1` = `<subquery4>`.`c1` and `test`.`t1`.`a2` = `<subquery4>`.`c2`)))) @@ -474,8 +474,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) 4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 5 MATERIALIZED t2i index it2i2 it2i3 18 NULL 5 100.00 Using where; Using index -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where -3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#4 */ select `test`.`t3`.`c1`,`test`.`t3`.`c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`,`test`.`t3`.`c2`>(<in_optimizer>((`test`.`t3`.`c1`,`test`.`t3`.`c2`),(`test`.`t3`.`c1`,`test`.`t3`.`c2`) in ( <materialize> (/* select#5 */ select `test`.`t2i`.`b1`,`test`.`t2i`.`b2` from `test`.`t2i` where `test`.`t2i`.`b2` > '0' ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery5>`.`b1` and `test`.`t3`.`c2` = `<subquery5>`.`b2`)))) ), <primary_index_lookup>(`test`.`t3`.`c1` in <temporary table> on distinct_key where `test`.`t3`.`c1` = `<subquery4>`.`c1` and `test`.`t3`.`c2` = `<subquery4>`.`c2`)))) @@ -496,8 +496,8 @@ select * from t3 where c1 in (select a1 from t1 where a1 > '0' UNION select b1 from t2 where b1 < '9'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where -3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 /* select#1 */ select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`>(<in_optimizer>(`test`.`t3`.`c1`,<exists>(/* select#2 */ select `test`.`t1`.`a1` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t3`.`c1`) = `test`.`t1`.`a1` union /* select#3 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t3`.`c1`) = `test`.`t2`.`b1`))) @@ -711,7 +711,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 DEPENDENT SUBQUERY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where 3 DEPENDENT SUBQUERY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where 3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join) -4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 99.22 Using where +4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where <expr_cache><concat(`test`.`t1`.`a1`,'x')>(<in_optimizer>(concat(`test`.`t1`.`a1`,'x'),<exists>(/* select#2 */ select left(`test`.`t1_16`.`a1`,8) from `test`.`t1_16` where <expr_cache><`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`>(<in_optimizer>((`test`.`t1_16`.`a1`,`test`.`t1_16`.`a2`),<exists>(/* select#3 */ select `test`.`t2_16`.`b1`,`test`.`t2_16`.`b2` from `test`.`t2_16` join `test`.`t2` where `test`.`t2`.`b2` = substr(`test`.`t2_16`.`b2`,1,6) and <expr_cache><`test`.`t2`.`b1`>(<in_optimizer>(`test`.`t2`.`b1`,`test`.`t2`.`b1` in ( <materialize> (/* select#4 */ select `test`.`t3`.`c1` from `test`.`t3` where `test`.`t3`.`c2` > '0' ), <primary_index_lookup>(`test`.`t2`.`b1` in <temporary table> on distinct_key where `test`.`t2`.`b1` = `<subquery4>`.`c1`)))) and <cache>(`test`.`t1_16`.`a1`) = `test`.`t2_16`.`b1` and <cache>(`test`.`t1_16`.`a2`) = `test`.`t2_16`.`b2`))) and <cache>(concat(`test`.`t1`.`a1`,'x')) = left(`test`.`t1_16`.`a1`,8)))) drop table t1_16, t2_16, t3_16; diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result index 695c010692c..97dcf07705c 100644 --- a/mysql-test/main/subselect_sj_mat.result +++ b/mysql-test/main/subselect_sj_mat.result @@ -59,9 +59,9 @@ set @@optimizer_switch='materialization=on,in_to_exists=off,firstmatch=off'; explain extended select * from t1 where a1 in (select b1 from t2 where b1 > '0'); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 99.22 +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func 1 100.00 -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`b1` > '0' select * from t1 where a1 in (select b1 from t2 where b1 > '0'); @@ -71,9 +71,9 @@ a1 a2 explain extended select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 99.22 +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func 1 100.00 -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`b1` > '0' select * from t1 where a1 in (select b1 from t2 where b1 > '0' group by b1); @@ -83,9 +83,9 @@ a1 a2 explain extended select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 99.22 +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 func,func 1 100.00 -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`b1` > '0' select * from t1 where (a1, a2) in (select b1, b2 from t2 where b1 > '0' group by b1, b2); @@ -97,7 +97,7 @@ select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' gr id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 test.t1.a1,test.t1.a2 1 100.00 -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where; Using temporary +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Using temporary Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from <materialize> (/* select#2 */ select `test`.`t2`.`b1`,min(`test`.`t2`.`b2`) from `test`.`t2` where `test`.`t2`.`b1` > '0' group by `test`.`t2`.`b1`) join `test`.`t1` where `<subquery2>`.`b1` = `test`.`t1`.`a1` and `<subquery2>`.`min(b2)` = `test`.`t1`.`a2` select * from t1 where (a1, a2) in (select b1, min(b2) from t2 where b1 > '0' group by b1); @@ -331,12 +331,12 @@ where (a1, a2) in (select b1, b2 from t2 where b1 > '0') and (a1, a2) in (select c1, c2 from t3 where (c1, c2) in (select b1, b2 from t2i where b2 > '0')); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 98.44 +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 16 func,func 1 100.00 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 func,func 1 100.00 -3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 98.44 Using where +3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 3 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 1 100.00 Using index -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 98.44 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and `test`.`t2`.`b1` > '0' and `test`.`t3`.`c2` > '0' select * from t1 @@ -375,12 +375,12 @@ b2 in (select c2 from t3 where c2 LIKE '%03')) and (a1, a2) in (select c1, c2 from t3 where (c1, c2) in (select b1, b2 from t2i where b2 > '0')); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 99.22 +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 16 func,func 1 100.00 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 func,func 1 100.00 -5 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 99.22 Using where +5 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 5 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 1 100.00 Using index -2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 100.00 Using where 4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: @@ -401,10 +401,10 @@ b2 in (select c2 from t3 t3b where c2 LIKE '%03')) and (a1, a2) in (select c1, c2 from t3 t3c where (c1, c2) in (select b1, b2 from t2i where b2 > '0')); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 99.22 +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 16 func,func 1 100.00 -1 PRIMARY t2 ALL NULL NULL NULL NULL 5 99.22 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join) -5 MATERIALIZED t3c ALL NULL NULL NULL NULL 4 99.22 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join) +5 MATERIALIZED t3c ALL NULL NULL NULL NULL 4 100.00 Using where 5 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3c.c1,test.t3c.c2 1 100.00 Using index 4 MATERIALIZED t3b ALL NULL NULL NULL NULL 4 100.00 Using where 3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where @@ -434,12 +434,12 @@ where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and (a1, a2) in (select c1, c2 from t3i where (c1, c2) in (select b1, b2 from t2i where b2 > '0'))); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL # # # 3 99.22 # +1 PRIMARY t1 ALL NULL # # # 3 100.00 # 1 PRIMARY <subquery5> eq_ref distinct_key # # # 1 100.00 # 1 PRIMARY <subquery2> eq_ref distinct_key # # # 1 100.00 # -5 MATERIALIZED t3 ALL NULL # # # 4 99.22 # +5 MATERIALIZED t3 ALL NULL # # # 4 100.00 # 5 MATERIALIZED t2i ref it2i1,it2i2,it2i3 # # # 1 100.00 # -2 MATERIALIZED t2 ALL NULL # # # 5 99.22 # +2 MATERIALIZED t2 ALL NULL # # # 5 100.00 # 4 MATERIALIZED t3 ALL NULL # # # 4 100.00 # 3 MATERIALIZED t3 ALL NULL # # # 4 100.00 # 7 UNION t1i range it1i1,it1i2,it1i3 # # # 3 100.00 # @@ -472,12 +472,12 @@ where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where (a1, a2) in (select c1, c2 from t3 where (c1, c2) in (select b1, b2 from t2i where b2 > '0')); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 99.22 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where 1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 16 func,func 1 100.00 -4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 99.22 Using where +4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 4 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 1 100.00 Using index -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where -3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) where `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0' @@ -496,12 +496,12 @@ where (c1, c2) in (select b1, b2 from t2i where b2 > '0')) and a1 = c1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -1 PRIMARY t3 ALL NULL NULL NULL NULL 4 99.22 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) 1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 16 func,func 1 100.00 -4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 99.22 Using where +4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 100.00 Using where 4 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 1 100.00 Using index -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where -3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0' @@ -522,8 +522,8 @@ select * from t3 where c1 in (select a1 from t1 where a1 > '0' UNION select b1 from t2 where b1 < '9'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where -2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where -3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where +3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 100.00 Using where NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 /* select#1 */ select `test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t3` where <expr_cache><`test`.`t3`.`c1`>(<in_optimizer>(`test`.`t3`.`c1`,<exists>(/* select#2 */ select `test`.`t1`.`a1` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t3`.`c1`) = `test`.`t1`.`a1` union /* select#3 */ select `test`.`t2`.`b1` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t3`.`c1`) = `test`.`t2`.`b1`))) @@ -738,7 +738,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 1 PRIMARY t1_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Start temporary; Using join buffer (flat, BNL join) 1 PRIMARY t2_16 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) -1 PRIMARY t3 ALL NULL NULL NULL NULL 4 99.22 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join) 1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; End temporary; Using join buffer (flat, BNL join) Warnings: Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t3` join `test`.`t2_16` join `test`.`t2` join `test`.`t1_16`) where `test`.`t2`.`b1` = `test`.`t3`.`c1` and `test`.`t2_16`.`b1` = `test`.`t1_16`.`a1` and `test`.`t2_16`.`b2` = `test`.`t1_16`.`a2` and `test`.`t2`.`b2` = substr(`test`.`t1_16`.`a2`,1,6) and `test`.`t3`.`c2` > '0' and concat(`test`.`t1`.`a1`,'x') = left(`test`.`t1_16`.`a1`,8) diff --git a/mysql-test/main/system_mysql_db.result b/mysql-test/main/system_mysql_db.result index d0d1e7c1175..dcc71da3677 100644 --- a/mysql-test/main/system_mysql_db.result +++ b/mysql-test/main/system_mysql_db.result @@ -234,8 +234,8 @@ column_stats CREATE TABLE `column_stats` ( `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 utf8mb3_bin DEFAULT NULL, - `histogram` varbinary(255) DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') COLLATE utf8mb3_bin DEFAULT NULL, + `histogram` longblob DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; diff --git a/mysql-test/main/system_mysql_db_fix40123.result b/mysql-test/main/system_mysql_db_fix40123.result index 127e2c49642..4ab80425a35 100644 --- a/mysql-test/main/system_mysql_db_fix40123.result +++ b/mysql-test/main/system_mysql_db_fix40123.result @@ -272,8 +272,8 @@ column_stats CREATE TABLE `column_stats` ( `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 utf8mb3_bin DEFAULT NULL, - `histogram` varbinary(255) DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') COLLATE utf8mb3_bin DEFAULT NULL, + `histogram` longblob DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result index fd0074c7f54..4244ab47d50 100644 --- a/mysql-test/main/system_mysql_db_fix50030.result +++ b/mysql-test/main/system_mysql_db_fix50030.result @@ -276,8 +276,8 @@ column_stats CREATE TABLE `column_stats` ( `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 utf8mb3_bin DEFAULT NULL, - `histogram` varbinary(255) DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') COLLATE utf8mb3_bin DEFAULT NULL, + `histogram` longblob DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result index a7d705c4158..59341406315 100644 --- a/mysql-test/main/system_mysql_db_fix50117.result +++ b/mysql-test/main/system_mysql_db_fix50117.result @@ -256,8 +256,8 @@ column_stats CREATE TABLE `column_stats` ( `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 utf8mb3_bin DEFAULT NULL, - `histogram` varbinary(255) DEFAULT NULL, + `hist_type` enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') COLLATE utf8mb3_bin DEFAULT NULL, + `histogram` longblob DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`column_name`) ) ENGINE=Aria DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Columns' show create table index_stats; diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index ef4832cdb8a..b50ae58df28 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -13,9 +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 NEVER NULL def mysql column_stats column_name 3 NULL NO varchar 64 192 NULL NULL NULL utf8mb3 utf8mb3_bin varchar(64) PRI select,insert,update,references NEVER NULL def mysql column_stats db_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8mb3 utf8mb3_bin varchar(64) PRI select,insert,update,references NEVER NULL -def mysql column_stats histogram 11 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) select,insert,update,references NEVER NULL +def mysql column_stats histogram 11 NULL YES longblob 4294967295 4294967295 NULL NULL NULL NULL NULL longblob select,insert,update,references NEVER NULL def mysql column_stats hist_size 9 NULL YES tinyint NULL NULL 3 0 NULL NULL NULL tinyint(3) unsigned select,insert,update,references NEVER NULL -def mysql column_stats hist_type 10 NULL YES enum 14 42 NULL NULL NULL utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') select,insert,update,references NEVER NULL +def mysql column_stats hist_type 10 NULL YES enum 14 42 NULL NULL NULL utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') select,insert,update,references NEVER NULL def mysql column_stats max_value 5 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) select,insert,update,references NEVER NULL def mysql column_stats min_value 4 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) select,insert,update,references NEVER NULL def mysql column_stats nulls_ratio 6 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4) select,insert,update,references NEVER NULL @@ -345,8 +345,8 @@ 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 utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') -1.0000 mysql column_stats histogram varbinary 255 255 NULL NULL varbinary(255) +3.0000 mysql column_stats hist_type enum 14 42 utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') +1.0000 mysql column_stats histogram longblob 4294967295 4294967295 NULL NULL longblob 3.0000 mysql db Host char 255 765 utf8mb3 utf8mb3_bin char(255) 3.0000 mysql db Db char 64 192 utf8mb3 utf8mb3_bin char(64) 3.0000 mysql db User char 128 384 utf8mb3 utf8mb3_bin char(128) diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result index 1a794c2828d..96751dfd176 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result @@ -13,9 +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) NEVER NULL def mysql column_stats column_name 3 NULL NO varchar 64 192 NULL NULL NULL utf8mb3 utf8mb3_bin varchar(64) PRI NEVER NULL def mysql column_stats db_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8mb3 utf8mb3_bin varchar(64) PRI NEVER NULL -def mysql column_stats histogram 11 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) NEVER NULL +def mysql column_stats histogram 11 NULL YES longblob 4294967295 4294967295 NULL NULL NULL NULL NULL longblob NEVER NULL def mysql column_stats hist_size 9 NULL YES tinyint NULL NULL 3 0 NULL NULL NULL tinyint(3) unsigned NEVER NULL -def mysql column_stats hist_type 10 NULL YES enum 14 42 NULL NULL NULL utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') NEVER NULL +def mysql column_stats hist_type 10 NULL YES enum 14 42 NULL NULL NULL utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') NEVER NULL def mysql column_stats max_value 5 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) NEVER NULL def mysql column_stats min_value 4 NULL YES varbinary 255 255 NULL NULL NULL NULL NULL varbinary(255) NEVER NULL def mysql column_stats nulls_ratio 6 NULL YES decimal NULL NULL 12 4 NULL NULL NULL decimal(12,4) NEVER NULL @@ -342,8 +342,8 @@ 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 utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') -1.0000 mysql column_stats histogram varbinary 255 255 NULL NULL varbinary(255) +3.0000 mysql column_stats hist_type enum 14 42 utf8mb3 utf8mb3_bin enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB') +1.0000 mysql column_stats histogram longblob 4294967295 4294967295 NULL NULL longblob 3.0000 mysql db Host char 255 765 utf8mb3 utf8mb3_bin char(255) 3.0000 mysql db Db char 64 192 utf8mb3 utf8mb3_bin char(64) 3.0000 mysql db User char 128 384 utf8mb3 utf8mb3_bin char(128) diff --git a/mysql-test/suite/sys_vars/r/histogram_type_basic.result b/mysql-test/suite/sys_vars/r/histogram_type_basic.result index db42204ac1f..c24192002aa 100644 --- a/mysql-test/suite/sys_vars/r/histogram_type_basic.result +++ b/mysql-test/suite/sys_vars/r/histogram_type_basic.result @@ -1,11 +1,11 @@ SET @start_global_value = @@global.histogram_type; SELECT @start_global_value; @start_global_value -DOUBLE_PREC_HB +JSON_HB SET @start_session_value = @@session.histogram_type; SELECT @start_session_value; @start_session_value -DOUBLE_PREC_HB +JSON_HB SET @@global.histogram_type = 1; SET @@global.histogram_type = DEFAULT; SELECT @@global.histogram_type; @@ -71,9 +71,9 @@ HISTOGRAM_TYPE DOUBLE_PREC_HB SET @@global.histogram_type = @start_global_value; SELECT @@global.histogram_type; @@global.histogram_type -DOUBLE_PREC_HB +JSON_HB SET @@session.histogram_type = @start_session_value; SELECT @@session.histogram_type; @@session.histogram_type -DOUBLE_PREC_HB +JSON_HB set sql_mode=''; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index b1d2a6595b3..fc9d8db4b9f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -1205,11 +1205,11 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME HISTOGRAM_TYPE VARIABLE_SCOPE SESSION VARIABLE_TYPE ENUM -VARIABLE_COMMENT 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. +VARIABLE_COMMENT 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, JSON_HB - height-balanced, stored as JSON. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST SINGLE_PREC_HB,DOUBLE_PREC_HB +ENUM_VALUE_LIST SINGLE_PREC_HB,DOUBLE_PREC_HB,JSON_HB READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME HOSTNAME diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 7b811a011ff..177584cf79d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -1305,11 +1305,11 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME HISTOGRAM_TYPE VARIABLE_SCOPE SESSION VARIABLE_TYPE ENUM -VARIABLE_COMMENT 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. +VARIABLE_COMMENT 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, JSON_HB - height-balanced, stored as JSON. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST SINGLE_PREC_HB,DOUBLE_PREC_HB +ENUM_VALUE_LIST SINGLE_PREC_HB,DOUBLE_PREC_HB,JSON_HB READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME HOSTNAME diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index cee47a0e5d6..b48e9baf12b 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -314,7 +314,7 @@ DROP TABLE tmp_proxies_priv; 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=Aria transactional=0 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 varbinary(255) DEFAULT NULL, max_value varbinary(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=Aria transactional=0 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 varbinary(255) DEFAULT NULL, max_value varbinary(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','JSON_HB'), histogram longblob, PRIMARY KEY (db_name,table_name,column_name) ) engine=Aria transactional=0 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=Aria transactional=0 CHARACTER SET utf8 COLLATE utf8_bin comment='Statistics on Indexes'; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 038d5384dda..172fe46ae7e 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -835,3 +835,11 @@ IF 1 = (SELECT count(*) FROM information_schema.VIEWS WHERE TABLE_CATALOG = 'def END IF// DELIMITER ; + +-- +-- Upgrade mysql.column_stats table +-- + +ALTER TABLE column_stats + modify hist_type enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB'), + modify histogram longblob; diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 3c9b7246309..dc1f32187e8 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -151,6 +151,7 @@ SET (SQL_SOURCE sql_analyze_stmt.cc sql_join_cache.cc create_options.cc multi_range_read.cc + opt_histogram_json.cc opt_index_cond_pushdown.cc opt_subselect.cc opt_table_elimination.cc sql_expression_cache.cc gcalc_slicescan.cc gcalc_tools.cc diff --git a/sql/field.cc b/sql/field.cc index b72b0357c23..75d15cbdea1 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1108,19 +1108,27 @@ Field_longstr::pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field) relative position of the field value in the numeric interval [min,max] */ -double Field::pos_in_interval_val_real(Field *min, Field *max) +double pos_in_interval_for_double(double midp_val, double min_val, + double max_val) { double n, d; - n= val_real() - min->val_real(); + n= midp_val - min_val; if (n < 0) return 0.0; - d= max->val_real() - min->val_real(); + d= max_val - min_val; if (d <= 0) return 1.0; return MY_MIN(n/d, 1.0); } +double Field::pos_in_interval_val_real(Field *min, Field *max) +{ + return pos_in_interval_for_double(val_real(), min->val_real(), + max->val_real()); +} + + static inline ulonglong char_prefix_to_ulonglong(uchar *src) { @@ -1178,22 +1186,32 @@ static inline double safe_substract(ulonglong a, ulonglong b) double Field::pos_in_interval_val_str(Field *min, Field *max, uint data_offset) { + return pos_in_interval_for_string(charset(), + ptr + data_offset, data_length(), + min->ptr + data_offset, min->data_length(), + max->ptr + data_offset, max->data_length() + ); +} + + +double pos_in_interval_for_string(CHARSET_INFO *cset, + const uchar *midp_val, uint32 midp_len, + const uchar *min_val, uint32 min_len, + const uchar *max_val, uint32 max_len) +{ uchar mp_prefix[sizeof(ulonglong)]; uchar minp_prefix[sizeof(ulonglong)]; uchar maxp_prefix[sizeof(ulonglong)]; ulonglong mp, minp, maxp; - charset()->strnxfrm(mp_prefix, sizeof(mp), - ptr + data_offset, - data_length()); - charset()->strnxfrm(minp_prefix, sizeof(minp), - min->ptr + data_offset, - min->data_length()); - charset()->strnxfrm(maxp_prefix, sizeof(maxp), - max->ptr + data_offset, - max->data_length()); - mp= char_prefix_to_ulonglong(mp_prefix); + + cset->strnxfrm(mp_prefix, sizeof(mp), midp_val, midp_len); + cset->strnxfrm(minp_prefix, sizeof(minp), min_val, min_len); + cset->strnxfrm(maxp_prefix, sizeof(maxp), max_val, max_len); + + 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= safe_substract(mp, minp); if (n < 0) diff --git a/sql/field.h b/sql/field.h index 7be16a1457e..078e22c6161 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1514,11 +1514,20 @@ public: if (null_ptr) null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*); } + + /* + Copy the Field's value to buff. The value will be in table->record[] + format. + */ void get_image(uchar *buff, uint length, CHARSET_INFO *cs) const { get_image(buff, length, ptr, cs); } virtual void get_image(uchar *buff, uint length, const uchar *ptr_arg, CHARSET_INFO *cs) const { memcpy(buff,ptr_arg,length); } + + /* + Set Field's value to the value in *buf. + */ virtual void set_image(const uchar *buff,uint length, CHARSET_INFO *cs) { memcpy(ptr,buff,length); } @@ -1857,6 +1866,7 @@ public: { return (double) 0.5; } + virtual bool pos_through_val_str() { return false;} /* Check if comparison between the field and an item unambiguously @@ -2142,6 +2152,8 @@ public: { return pos_in_interval_val_str(min, max, length_size()); } + bool pos_through_val_str() override {return true;} + bool test_if_equality_guarantees_uniqueness(const Item *const_item) const override; SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, KEY_PART *key_part, @@ -5895,5 +5907,12 @@ ulonglong TABLE::vers_start_id() const return static_cast<ulonglong>(vers_start_field()->val_int()); } +double pos_in_interval_for_string(CHARSET_INFO *cset, + const uchar *midp_val, uint32 midp_len, + const uchar *min_val, uint32 min_len, + const uchar *max_val, uint32 max_len); + +double pos_in_interval_for_double(double midp_val, + double min_val, double max_val); #endif /* FIELD_INCLUDED */ diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d4bf28a9c21..00413f95e32 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -503,7 +503,7 @@ err: const char *histogram_types[] = - {"SINGLE_PREC_HB", "DOUBLE_PREC_HB", 0}; + {"SINGLE_PREC_HB", "DOUBLE_PREC_HB", "JSON_HB", 0}; static TYPELIB histogram_types_typelib= { array_elements(histogram_types), "histogram_types", @@ -533,6 +533,14 @@ String *Item_func_decode_histogram::val_str(String *str) null_value= 1; return 0; } + + if (type == JSON_HB) + { + // It's a JSON histogram. Return it as-is. + null_value= 0; + return res; + } + if (type == DOUBLE_PREC_HB && res->length() % 2 != 0) res->length(res->length() - 1); // one byte is unused diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h index 9e7081c96d1..7840476b878 100644 --- a/sql/my_json_writer.h +++ b/sql/my_json_writer.h @@ -238,6 +238,8 @@ public: Json_writer& add_member(const char *name, size_t len); /* Add atomic values */ + + /* Note: the add_str methods do not do escapes. Should this change? */ void add_str(const char* val); void add_str(const char* val, size_t num_bytes); void add_str(const String &str); diff --git a/sql/opt_histogram_json.cc b/sql/opt_histogram_json.cc new file mode 100644 index 00000000000..f2be4e5c0fb --- /dev/null +++ b/sql/opt_histogram_json.cc @@ -0,0 +1,1188 @@ +/* + Copyright (c) 2021, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include "mariadb.h" +#include "sql_base.h" +#include "my_json_writer.h" +#include "sql_statistics.h" +#include "opt_histogram_json.h" + + +/* + @brief + Un-escape a JSON string and save it into *out. + + @detail + There's no way to tell how much space is needed for the output. + Start with a small string and increase its size until json_unescape() + succeeds. +*/ + +static bool json_unescape_to_string(const char *val, int val_len, String* out) +{ + // Make sure 'out' has some memory allocated. + if (!out->alloced_length() && out->alloc(128)) + return true; + + while (1) + { + uchar *buf= (uchar*)out->ptr(); + out->length(out->alloced_length()); + + int res= json_unescape(&my_charset_utf8mb4_bin, + (const uchar*)val, + (const uchar*)val + val_len, + out->charset(), + buf, buf + out->length()); + if (res >= 0) + { + out->length(res); + return false; // Ok + } + + // We get here if the unescaped string didn't fit into memory. + if (out->alloc(out->alloced_length()*2)) + return true; + } +} + + +/* + @brief + Escape a JSON string and save it into *out. + + @detail + There's no way to tell how much space is needed for the output. + Start with a small string and increase its size until json_escape() + succeeds. +*/ + +static int json_escape_to_string(const String *str, String* out) +{ + // Make sure 'out' has some memory allocated. + if (!out->alloced_length() && out->alloc(128)) + return JSON_ERROR_OUT_OF_SPACE; + + while (1) + { + uchar *buf= (uchar*)out->ptr(); + out->length(out->alloced_length()); + const uchar *str_ptr= (const uchar*)str->ptr(); + + int res= json_escape(str->charset(), + str_ptr, + str_ptr + str->length(), + &my_charset_utf8mb4_bin, + buf, buf + out->length()); + if (res >= 0) + { + out->length(res); + return 0; // Ok + } + + if (res != JSON_ERROR_OUT_OF_SPACE) + return res; // Some conversion error + + // Out of space error. Try with a bigger buffer + if (out->alloc(out->alloced_length()*2)) + return JSON_ERROR_OUT_OF_SPACE; + } +} + + +class Histogram_json_builder : public Histogram_builder +{ + Histogram_json_hb *histogram; + /* Number of buckets in the histogram */ + uint hist_width; + + /* + Number of rows that we intend to have in the bucket. That is, this is + + n_rows_in_table / hist_width + + Actual number of rows in the buckets we produce may vary because of + "popular values" and rounding. + */ + longlong bucket_capacity; + + /* Number of the buckets already collected */ + uint n_buckets_collected; + + /* + TRUE means do not try to represent values as UTF-8 text in histogram + storage. Use start_hex/end_hex for all values. + */ + bool force_binary; + + /* Data about the bucket we are filling now */ + struct CurBucket + { + /* Number of values in the bucket so far. */ + longlong size; + + /* Number of distinct values in the bucket */ + int ndv; + }; + CurBucket bucket; + + /* Used to create the JSON representation of the histogram. */ + Json_writer writer; + +public: + + Histogram_json_builder(Histogram_json_hb *hist, Field *col, uint col_len, + ha_rows rows) + : Histogram_builder(col, col_len, rows), histogram(hist) + { + /* + When computing number of rows in the bucket, round it UP. This way, we + will not end up with a histogram that has more buckets than intended. + + We may end up producing a histogram with fewer buckets than intended, but + this is considered tolerable. + */ + bucket_capacity= (longlong)round(rows2double(records) / histogram->get_width() + 0.5); + if (bucket_capacity == 0) + bucket_capacity= 1; + hist_width= histogram->get_width(); + n_buckets_collected= 0; + bucket.ndv= 0; + bucket.size= 0; + force_binary= (col->type() == MYSQL_TYPE_BIT); + + writer.start_object(); + append_histogram_params(); + + writer.add_member(Histogram_json_hb::JSON_NAME).start_array(); + } + + ~Histogram_json_builder() override = default; + +private: + bool bucket_is_empty() { return bucket.ndv == 0; } + + void append_histogram_params() + { + char buf[128]; + + time_t cur_time_t= my_time(0); + struct tm curtime; + localtime_r(&cur_time_t, &curtime); + + my_snprintf(buf, sizeof(buf), "%d-%02d-%02d %2d:%02d:%02d %s", + curtime.tm_year + 1900, + curtime.tm_mon+1, + curtime.tm_mday, + curtime.tm_hour, + curtime.tm_min, + curtime.tm_sec, + system_time_zone); + + writer.add_member("target_histogram_size").add_ull(hist_width); + writer.add_member("collected_at").add_str(buf); + writer.add_member("collected_by").add_str(server_version); + } + /* + Flush the current bucket out (to JSON output), and set it to be empty. + */ + void finalize_bucket() + { + double fract= (double) bucket.size / records; + writer.add_member("size").add_double(fract); + writer.add_member("ndv").add_ll(bucket.ndv); + writer.end_object(); + n_buckets_collected++; + + bucket.ndv= 0; + bucket.size= 0; + } + + /* + Same as finalize_bucket() but also provide the bucket's end value. + */ + bool finalize_bucket_with_end_value(void *elem) + { + if (append_column_value(elem, false)) + return true; + finalize_bucket(); + return false; + } + + /* + Write the first value group to the bucket. + @param elem The value we are writing + @param cnt The number of such values. + */ + bool start_bucket(void *elem, longlong cnt) + { + DBUG_ASSERT(bucket.size == 0); + writer.start_object(); + if (append_column_value(elem, true)) + return true; + + bucket.ndv= 1; + bucket.size= cnt; + return false; + } + + /* + Append the passed value into the JSON writer as string value + */ + bool append_column_value(void *elem, bool is_start) + { + StringBuffer<MAX_FIELD_WIDTH> val; + + // Get the text representation of the value + column->store_field_value((uchar*) elem, col_length); + String *str= column->val_str(&val); + + // Escape the value for JSON + StringBuffer<MAX_FIELD_WIDTH> escaped_val; + int rc= JSON_ERROR_ILLEGAL_SYMBOL; + if (!force_binary) + { + rc= json_escape_to_string(str, &escaped_val); + if (!rc) + { + writer.add_member(is_start? "start": "end"); + writer.add_str(escaped_val.c_ptr_safe()); + return false; + } + } + if (rc == JSON_ERROR_ILLEGAL_SYMBOL) + { + escaped_val.set_hex(val.ptr(), val.length()); + writer.add_member(is_start? "start_hex": "end_hex"); + writer.add_str(escaped_val.c_ptr_safe()); + return false; + } + return true; + } + + /* + Append a value group of cnt values. + */ + void append_to_bucket(longlong cnt) + { + bucket.ndv++; + bucket.size += cnt; + } + +public: + /* + @brief + Add data to the histogram. + + @detail + The call signals to add a "value group" of elem_cnt rows, each of which + has the same value that is provided in *elem. + + Subsequent next() calls will add values that are greater than the + current one. + + @return + 0 - OK + */ + int next(void *elem, element_count elem_cnt) override + { + counters.next(elem, elem_cnt); + ulonglong count= counters.get_count(); + + /* + Ok, we've got a "value group" of elem_cnt identical values. + + If we take the values from the value group and put them into + the current bucket, how many values will be left after we've + filled the bucket? + */ + longlong overflow= bucket.size + elem_cnt - bucket_capacity; + + /* + Case #1: This value group should be put into a separate bucket, if + A. It fills the current bucket and also fills the next bucket, OR + B. It fills the current bucket, which was empty. + */ + if (overflow >= bucket_capacity || (bucket_is_empty() && overflow >= 0)) + { + // Finalize the current bucket + if (!bucket_is_empty()) + finalize_bucket(); + + // Start/end the separate bucket for this value group. + if (start_bucket(elem, elem_cnt)) + return 1; // OOM + + if (records == count) + { + if (finalize_bucket_with_end_value(elem)) + return 1; + } + else + finalize_bucket(); + } + else if (overflow >= 0) + { + /* + Case #2: is when Case#1 doesn't hold, but we can still fill the + current bucket. + */ + + // If the bucket was empty, it would have been case #1. + DBUG_ASSERT(!bucket_is_empty()); + + /* + Finalize the current bucket. Put there enough values to make it hold + bucket_capacity values. + */ + append_to_bucket(bucket_capacity - bucket.size); + if (records == count && !overflow) + { + if (finalize_bucket_with_end_value(elem)) + return 1; + } + else + finalize_bucket(); + + if (overflow > 0) + { + // Then, start the new bucket with the remaining values. + if (start_bucket(elem, overflow)) + return 1; + } + } + else + { + // Case #3: there's not enough values to fill the current bucket. + if (bucket_is_empty()) + { + if (start_bucket(elem, elem_cnt)) + return 1; + } + else + append_to_bucket(elem_cnt); + } + + if (records == count) + { + // This is the final value group. + if (!bucket_is_empty()) + { + if (finalize_bucket_with_end_value(elem)) + return 1; + } + } + return 0; + } + + /* + @brief + Finalize the creation of histogram + */ + void finalize() override + { + writer.end_array(); + writer.end_object(); + Binary_string *json_string= (Binary_string *) writer.output.get_string(); + histogram->set_json_text(n_buckets_collected, + json_string->c_ptr(), + (size_t)json_string->length()); + } +}; + + +Histogram_builder *Histogram_json_hb::create_builder(Field *col, uint col_len, + ha_rows rows) +{ + return new Histogram_json_builder(this, col, col_len, rows); +} + + +void Histogram_json_hb::init_for_collection(MEM_ROOT *mem_root, + Histogram_type htype_arg, + ulonglong size_arg) +{ + DBUG_ASSERT(htype_arg == JSON_HB); + size= (size_t)size_arg; +} + + +/* + A syntax sugar interface to json_string_t +*/ +class Json_string +{ + json_string_t str; +public: + explicit Json_string(const char *name) + { + json_string_set_str(&str, (const uchar*)name, + (const uchar*)name + strlen(name)); + json_string_set_cs(&str, system_charset_info); + } + json_string_t *get() { return &str; } +}; + + +/* + This [partially] saves the JSON parser state and then can rollback the parser + to it. + + The goal of this is to be able to make multiple json_key_matches() calls: + + Json_saved_parser_state save(je); + if (json_key_matches(je, KEY_NAME_1)) { + ... + return; + } + save.restore_to(je); + if (json_key_matches(je, KEY_NAME_2)) { + ... + } + + This allows one to parse JSON objects where [optional] members come in any + order. +*/ + +class Json_saved_parser_state +{ + const uchar *c_str; + my_wc_t c_next; + int state; +public: + explicit Json_saved_parser_state(const json_engine_t *je) : + c_str(je->s.c_str), + c_next(je->s.c_next), + state(je->state) + {} + void restore_to(json_engine_t *je) + { + je->s.c_str= c_str; + je->s.c_next= c_next; + je->state= state; + } +}; + + +/* + @brief + Read a constant from JSON document and save it in *out. + + @detail + The JSON document stores constant in text form, we need to save it in + KeyTupleFormat. String constants in JSON may be escaped. +*/ + +bool read_bucket_endpoint(json_engine_t *je, Field *field, String *out, + const char **err) +{ + if (json_read_value(je)) + return true; + + if (je->value_type != JSON_VALUE_STRING && + je->value_type != JSON_VALUE_NUMBER) + { + *err= "String or number expected"; + return true; + } + + const char* je_value= (const char*)je->value; + if (je->value_type == JSON_VALUE_STRING && je->value_escaped) + { + StringBuffer<128> unescape_buf; + if (json_unescape_to_string(je_value, je->value_len, &unescape_buf)) + { + *err= "Un-escape error"; + return true; + } + field->store_text(unescape_buf.ptr(), unescape_buf.length(), + unescape_buf.charset()); + } + else + field->store_text(je_value, je->value_len, &my_charset_utf8mb4_bin); + + out->alloc(field->pack_length()); + uint bytes= field->get_key_image((uchar*)out->ptr(), + field->key_length(), Field::itRAW); + out->length(bytes); + return false; +} + + +bool read_hex_bucket_endpoint(json_engine_t *je, Field *field, String *out, + const char **err) +{ + if (json_read_value(je)) + return true; + + if (je->value_type != JSON_VALUE_STRING || je->value_escaped || + (je->value_len & 1)) + { + *err= "Expected a hex string"; + return true; + } + StringBuffer<128> buf; + + for (auto pc= je->value; pc < je->value + je->value_len; pc+=2) + { + int hex_char1= hexchar_to_int(pc[0]); + int hex_char2= hexchar_to_int(pc[1]); + if (hex_char1 == -1 || hex_char2 == -1) + { + *err= "Expected a hex string"; + return true; + } + buf.append((hex_char1 << 4) | hex_char2); + } + + field->store_text(buf.ptr(), buf.length(), field->charset()); + out->alloc(field->pack_length()); + uint bytes= field->get_key_image((uchar*)out->ptr(), + field->key_length(), Field::itRAW); + out->length(bytes); + return false; +} + + +/* + @brief Parse a JSON reprsentation for one histogram bucket + + @param je The JSON parser object + @param field Table field we are using histogram (used to convert + endpoints from text representation to binary) + @param total_size INOUT Fraction of the table rows in the buckets parsed so + far. + @param assigned_last_end OUT TRUE<=> The bucket had "end" members, the + function has saved it in + this->last_bucket_end_endp + @param err OUT If function returns 1, this *may* be set to point to text + describing the error. + + @detail + + Parse a JSON object in this form: + + { "start": "value", "size":nnn.nn, "ndv": nnn, "end": "value"} + + Unknown members are ignored. + + @return + 0 OK + 1 Parse Error + -1 EOF +*/ +int Histogram_json_hb::parse_bucket(json_engine_t *je, Field *field, + double *total_size, + bool *assigned_last_end, + const char **err) +{ + *assigned_last_end= false; + if (json_scan_next(je)) + return 1; + if (je->state != JST_VALUE) + { + if (je->state == JST_ARRAY_END) + return -1; // EOF + else + return 1; // An error + } + + if (json_scan_next(je) || je->state != JST_OBJ_START) + { + *err= "Expected an object in the buckets array"; + return 1; + } + + bool have_start= false; + bool have_size= false; + bool have_ndv= false; + + double size_d; + longlong ndv_ll; + StringBuffer<128> value_buf; + int rc; + + while (!(rc= json_scan_next(je)) && je->state != JST_OBJ_END) + { + Json_saved_parser_state save1(je); + Json_string start_str("start"); + if (json_key_matches(je, start_str.get())) + { + if (read_bucket_endpoint(je, field, &value_buf, err)) + return 1; + + have_start= true; + continue; + } + save1.restore_to(je); + + Json_string size_str("size"); + if (json_key_matches(je, size_str.get())) + { + if (json_read_value(je)) + return 1; + + const char *size= (const char*)je->value_begin; + char *size_end= (char*)je->value_end; + int conv_err; + size_d= my_strtod(size, &size_end, &conv_err); + if (conv_err) + { + *err= ".size member must be a floating-point value"; + return 1; + } + have_size= true; + continue; + } + save1.restore_to(je); + + Json_string ndv_str("ndv"); + if (json_key_matches(je, ndv_str.get())) + { + if (json_read_value(je)) + return 1; + + const char *ndv= (const char*)je->value_begin; + char *ndv_end= (char*)je->value_end; + int conv_err; + ndv_ll= my_strtoll10(ndv, &ndv_end, &conv_err); + if (conv_err) + { + *err= ".ndv member must be an integer value"; + return 1; + } + have_ndv= true; + continue; + } + save1.restore_to(je); + + Json_string end_str("end"); + if (json_key_matches(je, end_str.get())) + { + if (read_bucket_endpoint(je, field, &value_buf, err)) + return 1; + last_bucket_end_endp.assign(value_buf.ptr(), value_buf.length()); + *assigned_last_end= true; + continue; + } + save1.restore_to(je); + + // Less common endoints: + Json_string start_hex_str("start_hex"); + if (json_key_matches(je, start_hex_str.get())) + { + if (read_hex_bucket_endpoint(je, field, &value_buf, err)) + return 1; + + have_start= true; + continue; + } + save1.restore_to(je); + + Json_string end_hex_str("end_hex"); + if (json_key_matches(je, end_hex_str.get())) + { + if (read_hex_bucket_endpoint(je, field, &value_buf, err)) + return 1; + last_bucket_end_endp.assign(value_buf.ptr(), value_buf.length()); + *assigned_last_end= true; + continue; + } + save1.restore_to(je); + + + // Some unknown member. Skip it. + if (json_skip_key(je)) + return 1; + } + + if (rc) + return 1; + + if (!have_start) + { + *err= "\"start\" element not present"; + return 1; + } + if (!have_size) + { + *err= "\"size\" element not present"; + return 1; + } + if (!have_ndv) + { + *err= "\"ndv\" element not present"; + return 1; + } + + *total_size += size_d; + + buckets.push_back({std::string(value_buf.ptr(), value_buf.length()), + *total_size, ndv_ll}); + + return 0; // Ok, continue reading +} + + +/* + @brief + Parse the histogram from its on-disk JSON representation + + @detail + See opt_histogram_json.h, class Histogram_json_hb for description of the + data format. + + @return + false OK + True Error +*/ + +bool Histogram_json_hb::parse(MEM_ROOT *mem_root, const char *db_name, + const char *table_name, Field *field, + Histogram_type type_arg, + const char *hist_data, size_t hist_data_len) +{ + json_engine_t je; + int rc; + const char *err= "JSON parse error"; + double total_size; + int end_element; + bool end_assigned; + DBUG_ENTER("Histogram_json_hb::parse"); + DBUG_ASSERT(type_arg == JSON_HB); + + json_scan_start(&je, &my_charset_utf8mb4_bin, + (const uchar*)hist_data, + (const uchar*)hist_data+hist_data_len); + + if (json_scan_next(&je)) + goto err; + + if (je.state != JST_OBJ_START) + { + err= "Root JSON element must be a JSON object"; + goto err; + } + + while (1) + { + if (json_scan_next(&je)) + goto err; + if (je.state == JST_OBJ_END) + break; // End of object + + if (je.state != JST_KEY) + goto err; // Can' really have this: JSON object has keys in it + + Json_string hist_key_name(JSON_NAME); + if (json_key_matches(&je, hist_key_name.get())) + { + total_size= 0.0; + end_element= -1; + if (json_scan_next(&je)) + goto err; + + if (je.state != JST_ARRAY_START) + { + err= "histogram_hb must contain an array"; + goto err; + } + + while (!(rc= parse_bucket(&je, field, &total_size, &end_assigned, &err))) + { + if (end_assigned && end_element != -1) + end_element= (int)buckets.size(); + } + if (rc > 0) // Got error other than EOF + goto err; + } + else + { + // Some unknown member. Skip it. + if (json_skip_key(&je)) + return 1; + } + } + + if (buckets.size() < 1) + { + err= "Histogram must have at least one bucket"; + goto err; + } + + if (end_element == -1) + { + buckets.back().start_value= last_bucket_end_endp; + } + else if (end_element < (int)buckets.size()) + { + err= ".end is only allowed in the last bucket"; + goto err; + } + + DBUG_RETURN(false); // Ok +err: + THD *thd= current_thd; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_JSON_HISTOGRAM_PARSE_FAILED, + ER_THD(thd, ER_JSON_HISTOGRAM_PARSE_FAILED), + db_name, table_name, + err, (je.s.c_str - (const uchar*)hist_data)); + sql_print_error(ER_THD(thd, ER_JSON_HISTOGRAM_PARSE_FAILED), + db_name, table_name, err, + (je.s.c_str - (const uchar*)hist_data)); + + DBUG_RETURN(true); +} + + +static +void store_key_image_to_rec_no_null(Field *field, const char *ptr, size_t len) +{ + MY_BITMAP *old_map= dbug_tmp_use_all_columns(field->table, + &field->table->write_set); + field->set_key_image((const uchar*)ptr, (uint)len); + dbug_tmp_restore_column_map(&field->table->write_set, old_map); +} + + +static +double position_in_interval(Field *field, const uchar *key, uint key_len, + const std::string& left, const std::string& right) +{ + double res; + if (field->pos_through_val_str()) + { + StringBuffer<64> buf1, buf2, buf3; + + store_key_image_to_rec_no_null(field, left.data(), left.size()); + String *min_str= field->val_str(&buf1); + /* + Make sure we've saved a copy of the data, not a pointer into the + field->ptr. We will overwrite the contents of field->ptr with the next + store_key_image_to_rec_no_null call + */ + if (&buf1 != min_str) + buf1.copy(*min_str); + else + buf1.copy(); + + store_key_image_to_rec_no_null(field, right.data(), right.size()); + String *max_str= field->val_str(&buf2); + /* Same as above */ + if (&buf2 != max_str) + buf2.copy(*max_str); + else + buf2.copy(); + + store_key_image_to_rec_no_null(field, (const char*)key, key_len); + String *midp_str= field->val_str(&buf3); + + res= pos_in_interval_for_string(field->charset(), + (const uchar*)midp_str->ptr(), midp_str->length(), + (const uchar*)buf1.ptr(), buf1.length(), + (const uchar*)buf2.ptr(), buf2.length()); + } + else + { + store_key_image_to_rec_no_null(field, left.data(), field->key_length()); + double min_val_real= field->val_real(); + + store_key_image_to_rec_no_null(field, right.data(), field->key_length()); + double max_val_real= field->val_real(); + + store_key_image_to_rec_no_null(field, (const char*)key, field->key_length()); + double midp_val_real= field->val_real(); + + res= pos_in_interval_for_double(midp_val_real, min_val_real, max_val_real); + } + return res; +} + + +double Histogram_json_hb::point_selectivity(Field *field, key_range *endpoint, + double avg_sel) +{ + const uchar *key = endpoint->key; + if (field->real_maybe_null()) + key++; + + // If the value is outside of the histogram's range, this will "clip" it to + // first or last bucket. + int endp_cmp; + int idx= find_bucket(field, key, &endp_cmp); + + double sel; + + if (buckets[idx].ndv == 1 && (endp_cmp!=0)) + { + /* + The bucket has a single value and it doesn't match! Return a very + small value. + */ + sel= 0.0; + } + else + { + /* + We get here when: + * The bucket has one value and this is the value we are looking for. + * The bucket has multiple values. Then, assume + */ + sel= (buckets[idx].cum_fract - get_left_fract(idx)) / buckets[idx].ndv; + } + return sel; +} + + +double Histogram_json_hb::get_left_fract(int idx) +{ + if (!idx) + return 0.0; + else + return buckets[idx-1].cum_fract; +} + +std::string& Histogram_json_hb::get_end_value(int idx) +{ + if (idx == (int)buckets.size()-1) + return last_bucket_end_endp; + else + return buckets[idx+1].start_value; +} + +/* + @param field The table field histogram is for. We don't care about the + field's current value, we only need its virtual functions to + perform various operations + + @param min_endp Left endpoint, or NULL if there is none + @param max_endp Right endpoint, or NULL if there is none +*/ + +double Histogram_json_hb::range_selectivity(Field *field, key_range *min_endp, + key_range *max_endp, double avg_sel) +{ + double min, max; + + if (min_endp && !(field->real_maybe_null() && min_endp->key[0])) + { + bool exclusive_endp= (min_endp->flag == HA_READ_AFTER_KEY)? true: false; + const uchar *min_key= min_endp->key; + uint min_key_len= min_endp->length; + if (field->real_maybe_null()) + { + min_key++; + min_key_len--; + } + + // Find the leftmost bucket that contains the lookup value. + // (If the lookup value is to the left of all buckets, find bucket #0) + int endp_cmp; + int idx= find_bucket(field, min_key, &endp_cmp); + + double sel; + // Special handling for buckets with ndv=1: + if (buckets[idx].ndv == 1) + { + if (endp_cmp < 0) + sel= 0.0; + else if (endp_cmp > 0) + sel= 1.0; + else // endp_cmp == 0.0 + sel= (exclusive_endp)? 1.0 : 0.0; + } + else + { + sel= position_in_interval(field, min_key, min_key_len, + buckets[idx].start_value, + get_end_value(idx)); + } + double left_fract= get_left_fract(idx); + min= left_fract + sel * (buckets[idx].cum_fract - left_fract); + } + else + min= 0.0; + + if (max_endp) + { + // The right endpoint cannot be NULL + DBUG_ASSERT(!(field->real_maybe_null() && max_endp->key[0])); + bool inclusive_endp= (max_endp->flag == HA_READ_AFTER_KEY)? true: false; + const uchar *max_key= max_endp->key; + uint max_key_len= max_endp->length; + if (field->real_maybe_null()) + { + max_key++; + max_key_len--; + } + int endp_cmp; + int idx= find_bucket(field, max_key, &endp_cmp); + + if ((endp_cmp == 0) && !inclusive_endp) + { + /* + The range is "col < $CONST" and we've found a bucket starting with + $CONST. + */ + if (idx > 0) + { + // Move to the previous bucket + endp_cmp= 1; + idx--; + } + else + endp_cmp= -1; + } + double sel; + + // Special handling for buckets with ndv=1: + if (buckets[idx].ndv == 1) + { + if (endp_cmp < 0) + sel= 0.0; + else if (endp_cmp > 0) + sel= 1.0; + else // endp_cmp == 0.0 + sel= inclusive_endp? 1.0 : 0.0; + } + else + { + sel= position_in_interval(field, max_key, max_key_len, + buckets[idx].start_value, + get_end_value(idx)); + } + double left_fract= get_left_fract(idx); + max= left_fract + sel * (buckets[idx].cum_fract - left_fract); + } + else + max= 1.0; + + return max - min; +} + + +void Histogram_json_hb::serialize(Field *field) +{ + field->store(json_text.data(), json_text.size(), &my_charset_bin); +} + + +static int SGN(int x) +{ + if (!x) + return 0; + return (x < 0)? -1 : 1; +} + + +/* + @brief + Find the leftmost histogram bucket such that "lookup_val >= start_value". + + @param field Field object (used to do value comparisons) + @param lookup_val The lookup value in KeyTupleFormat. + @param cmp OUT How the lookup_val compares to found_bucket.left_bound: + 0 - lookup_val == bucket.left_bound + >0 - lookup_val > bucket.left_bound (the most typical) + <0 - lookup_val < bucket.left_bound. This can only happen + for the first bucket, for all other buckets we would just + pick the previous bucket and have cmp>=0. + @return + The bucket index +*/ + +int Histogram_json_hb::find_bucket(const Field *field, const uchar *lookup_val, + int *cmp) +{ + int res; + int low= 0; + int high= (int)buckets.size() - 1; + *cmp= 1; // By default, (bucket[retval].start_value < *lookup_val) + + while (low + 1 < high) + { + int middle= (low + high) / 2; + res= field->key_cmp((uchar*)buckets[middle].start_value.data(), lookup_val); + if (!res) + { + *cmp= res; + low= middle; + goto end; + } + else if (res < 0) + low= middle; + else //res > 0 + high= middle; + } + + /* + If low and high were assigned a value in the above loop and we got here, + then the following holds: + + bucket[low].start_value < lookup_val < bucket[high].start_value + + Besides that, there are two special cases: low=0 and high=last_bucket. + Handle them below. + */ + if (low == 0) + { + res= field->key_cmp(lookup_val, (uchar*)buckets[0].start_value.data()); + if (res <= 0) + *cmp= res; + else // res>0, lookup_val > buckets[0].start_value + { + res= field->key_cmp(lookup_val, (uchar*)buckets[high].start_value.data()); + if (res >= 0) // lookup_val >= buckets[high].start_value + { + // Move to that bucket + low= high; + *cmp= res; + } + else + *cmp= 1; + } + } + else if (high == (int)buckets.size() - 1) + { + res= field->key_cmp(lookup_val, (uchar*)buckets[high].start_value.data()); + if (res >= 0) + { + // Ok the value is in the last bucket. + *cmp= res; + low= high; + } + else + { + // The value is in the 'low' bucket. + res= field->key_cmp(lookup_val, (uchar*)buckets[low].start_value.data()); + *cmp= res; + } + } + +end: + // Verification: *cmp has correct value + DBUG_ASSERT(SGN(*cmp) == + SGN(field->key_cmp(lookup_val, + (uchar*)buckets[low].start_value.data()))); + // buckets[low] <= lookup_val, with one exception of the first bucket. + DBUG_ASSERT(low == 0 || + field->key_cmp((uchar*)buckets[low].start_value.data(), lookup_val)<= 0); + // buckets[low+1] > lookup_val, with one exception of the last bucket + DBUG_ASSERT(low == (int)buckets.size()-1 || + field->key_cmp((uchar*)buckets[low+1].start_value.data(), lookup_val)> 0); + return low; +} diff --git a/sql/opt_histogram_json.h b/sql/opt_histogram_json.h new file mode 100644 index 00000000000..e9b69869f4b --- /dev/null +++ b/sql/opt_histogram_json.h @@ -0,0 +1,148 @@ +/* + Copyright (c) 2021, MariaDB Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include "sql_statistics.h" + +/* + An equi-height histogram which stores real values for bucket bounds. + + Handles @@histogram_type=JSON_HB + + Histogram format in JSON: + + { + // The next three are saved but not currently analyzed: + "target_histogram_size": nnn, + "collected_at": "(date and time)", + "collected_by": "(server version)", + + "histogram_hb": [ + { "start": "value", "size":nnn.nn, "ndv": nnn }, + ... + + // Optionally, start and/or end can be replaced with _hex variant + { "start_hex: "value", "size":nnn.nn, "ndv":nnn}, + + ... + { "start": "value", "size":nnn.nn, "ndv": nnn, "end": "value"}, + ] + } + + Histogram is a JSON object. It has some global properties and "histogram_hb" + member whose value is a JSON array of histogram buckets. + + Each bucket is an object with these members: + "start" - the first value in the bucket. + "size" - fraction of table rows that is contained in the bucket. + "ndv" - Number of Distinct Values in the bucket. + "end" - Optionally, the last value in the bucket. + + A bucket is a single-point bucket if it has ndv=1. + + Most buckets have no "end" member: the bucket is assumed to contain all + values up to the "start" of the next bucket. + + The exception is single-point buckets where last value is the same as the + first value. + + start/end can be replaced with start_hex/end_hex. In _hex variant, the + constant is encoded in hex. This encoding is used to handle so called + "unassigned characters": some non-UTF8 charsets have byte combinations that + are not mapped to any UTF8 character. +*/ + +class Histogram_json_hb : public Histogram_base +{ + size_t size; /* Number of elements in the histogram */ + + /* Collection-time only: collected histogram in the JSON form. */ + std::string json_text; + + struct Bucket + { + // The left endpoint in KeyTupleFormat. The endpoint is inclusive, this + // value is in this bucket. + std::string start_value; + + // Cumulative fraction: The fraction of table rows that fall into this + // and preceding buckets. + double cum_fract; + + // Number of distinct values in the bucket. + longlong ndv; + }; + + std::vector<Bucket> buckets; + + std::string last_bucket_end_endp; + +public: + static constexpr const char* JSON_NAME="histogram_hb"; + + bool parse(MEM_ROOT *mem_root, const char *db_name, const char *table_name, + Field *field, Histogram_type type_arg, + const char *hist_data, size_t hist_data_len) override; + + void serialize(Field *field) override; + + Histogram_builder *create_builder(Field *col, uint col_len, + ha_rows rows) override; + + // returns number of buckets in the histogram + uint get_width() override + { + return (uint)size; + } + + Histogram_type get_type() override + { + return JSON_HB; + } + + /* + @brief + This used to be the size of the histogram on disk, which was redundant + (one can check the size directly). Return the number of buckets instead. + */ + uint get_size() override + { + return (uint)size; + } + + void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, + ulonglong size) override; + + double point_selectivity(Field *field, key_range *endpoint, + double avg_sel) override; + double range_selectivity(Field *field, key_range *min_endp, + key_range *max_endp, double avg_sel) override; + + void set_json_text(ulonglong sz, const char *json_text_arg, + size_t json_text_len) + { + size= (size_t) sz; + json_text.assign(json_text_arg, json_text_len); + } + +private: + int parse_bucket(json_engine_t *je, Field *field, double *cumulative_size, + bool *assigned_last_end, const char **err); + + double get_left_fract(int idx); + std::string& get_end_value(int idx); + int find_bucket(const Field *field, const uchar *lookup_val, int *cmp); +}; + diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 06063cb9ae1..37cf054dfb0 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3277,7 +3277,10 @@ double records_in_column_ranges(PARAM *param, uint idx, break; } total_rows += rows; - } + } + if (total_rows == 0) + total_rows= MY_MIN(1, rows2double(param->table->stat_records())); + return total_rows; } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 2d90793b90f..3b5c8010a6d 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -8913,3 +8913,5 @@ ER_PARTITION_CONVERT_SUBPARTITIONED eng "Convert partition is not supported for subpartitioned table." ER_PROVIDER_NOT_LOADED eng "MariaDB tried to use the %s, but its provider plugin is not loaded" +ER_JSON_HISTOGRAM_PARSE_FAILED + eng "Failed to parse histogram for table %s.%s: %s at offset %d." diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 26e3d67641d..028838b65e4 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1045,6 +1045,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, else compl_result_code= HA_ADMIN_FAILED; + if (table->table) + free_statistics_for_table(thd, table->table); if (compl_result_code) result_code= HA_ADMIN_FAILED; else diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 1f034f490c8..84d0902193b 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -28,11 +28,15 @@ #include "sql_base.h" #include "key.h" #include "sql_statistics.h" +#include "opt_histogram_json.h" #include "opt_range.h" #include "uniques.h" #include "sql_show.h" #include "sql_partition.h" +#include <vector> +#include <string> + /* The system variable 'use_stat_tables' can take one of the following values: @@ -57,8 +61,11 @@ the collected statistics in the persistent statistical tables only when the value of the variable 'use_stat_tables' is not equal to "never". -*/ - +*/ + +Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type, + THD *owner); + /* Currently there are only 3 persistent statistical tables */ static const uint STATISTICS_TABLES= 3; @@ -178,12 +185,12 @@ TABLE_FIELD_TYPE column_stat_fields[COLUMN_STAT_N_FIELDS] = }, { { STRING_WITH_LEN("hist_type") }, - { STRING_WITH_LEN("enum('SINGLE_PREC_HB','DOUBLE_PREC_HB')") }, + { STRING_WITH_LEN("enum('SINGLE_PREC_HB','DOUBLE_PREC_HB','JSON_HB')") }, { STRING_WITH_LEN("utf8mb3") } }, { { STRING_WITH_LEN("histogram") }, - { STRING_WITH_LEN("varbinary(255)") }, + { STRING_WITH_LEN("longblob") }, { NULL, 0 } } }; @@ -307,7 +314,7 @@ public: inline void init(THD *thd, Field * table_field); inline bool add(); - inline void finish(ha_rows rows, double sample_fraction); + inline bool finish(MEM_ROOT *mem_root, ha_rows rows, double sample_fraction); inline void cleanup(); }; @@ -1064,15 +1071,23 @@ public: stat_field->store(stats->get_avg_frequency()); break; case COLUMN_STAT_HIST_SIZE: - stat_field->store(stats->histogram.get_size()); + // Note: this is dumb. the histogram size is stored with the + // histogram! + stat_field->store(stats->histogram? + stats->histogram->get_size() : 0); break; case COLUMN_STAT_HIST_TYPE: - stat_field->store(stats->histogram.get_type() + 1); + if (stats->histogram) + stat_field->store(stats->histogram->get_type() + 1); + else + stat_field->set_null(); break; case COLUMN_STAT_HISTOGRAM: - stat_field->store((char *)stats->histogram.get_values(), - stats->histogram.get_size(), &my_charset_bin); - break; + if (stats->histogram) + stats->histogram->serialize(stat_field); + else + stat_field->set_null(); + break; } } } @@ -1100,6 +1115,8 @@ public: void get_stat_values() { table_field->read_stats->set_all_nulls(); + // default: hist_type=NULL means there's no histogram + table_field->read_stats->histogram_type_on_disk= INVALID_HISTOGRAM; if (table_field->read_stats->min_value) table_field->read_stats->min_value->set_null(); @@ -1111,7 +1128,7 @@ public: char buff[MAX_FIELD_WIDTH]; String val(buff, sizeof(buff), &my_charset_bin); - for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HIST_TYPE; i++) + for (uint i= COLUMN_STAT_MIN_VALUE; i <= COLUMN_STAT_HISTOGRAM; i++) { Field *stat_field= stat_table->field[i]; @@ -1155,13 +1172,28 @@ public: 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()); + /* + Ignore the contents of mysql.column_stats.hist_size. We take the + size from the mysql.column_stats.histogram column, itself. + */ 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; + { + /* + Save the histogram type. The histogram itself will be read in + read_histograms_for_table(). + */ + Histogram_type hist_type= (Histogram_type) (stat_field->val_int() - + 1); + table_field->read_stats->histogram_type_on_disk= hist_type; + break; + } + case COLUMN_STAT_HISTOGRAM: + /* + Do nothing here: we take the histogram length from the 'histogram' + column itself + */ + break; } } } @@ -1182,9 +1214,9 @@ public: 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() + Histogram_base * load_histogram(MEM_ROOT *mem_root) { if (find_stat()) { @@ -1194,14 +1226,60 @@ public: 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()); + Histogram_type hist_type= + table_field->read_stats->histogram_type_on_disk; + + Histogram_base *hist; + if (!(hist= create_histogram(mem_root, hist_type, NULL))) + return NULL; + Field *field= table->field[table_field->field_index]; + if (!hist->parse(mem_root, db_name->str, table_name->str, + field, hist_type, + val.ptr(), val.length())) + { + table_field->read_stats->histogram= hist; + return hist; + } + else + delete hist; } + return NULL; } - }; +bool Histogram_binary::parse(MEM_ROOT *mem_root, const char*, const char*, + Field*, Histogram_type type_arg, + const char *hist_data, size_t hist_data_len) +{ + /* On-disk an in-memory formats are the same. Just copy the data. */ + type= type_arg; + size= (uint8) hist_data_len; // 'size' holds the size of histogram in bytes + if (!(values= (uchar*)alloc_root(mem_root, hist_data_len))) + return true; + + memcpy(values, hist_data, hist_data_len); + return false; +} + +/* + Save the histogram data info a table field. +*/ +void Histogram_binary::serialize(Field *field) +{ + field->store((char*)values, size, &my_charset_bin); +} + +void Histogram_binary::init_for_collection(MEM_ROOT *mem_root, + Histogram_type htype_arg, + ulonglong size_arg) +{ + type= htype_arg; + values= (uchar*)alloc_root(mem_root, (size_t)size_arg); + size= (uint8) size_arg; +} + + /* An object of the class Index_stat is created to read statistical data on tables from the statistical table table_stat, to update @@ -1512,62 +1590,39 @@ public: } }; -/* - Histogram_builder is a helper class that is used to build histograms - for columns -*/ - -class Histogram_builder +class Histogram_binary_builder : public 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 */ + Histogram_binary *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 */ - /* number of distinct values that occured only once */ - ulonglong count_distinct_single_occurence; -public: - Histogram_builder(Field *col, uint col_len, ha_rows rows) - : column(col), col_length(col_len), records(rows) +public: + Histogram_binary_builder(Field *col, uint col_len, ha_rows rows) + : Histogram_builder(col, col_len, rows) { Column_statistics *col_stats= col->collected_stats; min_value= col_stats->min_value; max_value= col_stats->max_value; - histogram= &col_stats->histogram; + histogram= (Histogram_binary*)col_stats->histogram; hist_width= histogram->get_width(); bucket_capacity= (double) records / (hist_width + 1); curr_bucket= 0; - count= 0; - count_distinct= 0; - count_distinct_single_occurence= 0; } - ulonglong get_count_distinct() const { return count_distinct; } - ulonglong get_count_single_occurence() const + int next(void *elem, element_count elem_cnt) override { - return count_distinct_single_occurence; - } - - int next(void *elem, element_count elem_cnt) - { - count_distinct++; - if (elem_cnt == 1) - count_distinct_single_occurence++; - count+= elem_cnt; + counters.next(elem, elem_cnt); + ulonglong count= counters.get_count(); 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)); + column->pos_in_interval(min_value, max_value)); curr_bucket++; while (curr_bucket != hist_width && count > bucket_capacity * (curr_bucket + 1)) @@ -1578,25 +1633,51 @@ public: } return 0; } + void finalize() override {} }; +Histogram_builder *Histogram_binary::create_builder(Field *col, uint col_len, + ha_rows rows) +{ + return new Histogram_binary_builder(col, col_len, rows); +} + + +Histogram_base *create_histogram(MEM_ROOT *mem_root, Histogram_type hist_type, + THD *owner) +{ + Histogram_base *res= NULL; + switch (hist_type) { + case SINGLE_PREC_HB: + case DOUBLE_PREC_HB: + res= new Histogram_binary(); + break; + case JSON_HB: + res= new Histogram_json_hb(); + break; + default: + DBUG_ASSERT(0); + } + + if (res) + res->set_owner(owner); + return res; +} + + C_MODE_START -int histogram_build_walk(void *elem, element_count elem_cnt, void *arg) +static 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); } - - -static int count_distinct_single_occurence_walk(void *elem, - element_count count, void *arg) +int basic_stats_collector_walk(void *elem, element_count count, + void *arg) { - ((ulonglong*)arg)[0]+= 1; - if (count == 1) - ((ulonglong*)arg)[1]+= 1; + ((Basic_stats_collector*)arg)->next(elem, count); return 0; } @@ -1681,23 +1762,35 @@ public: */ void walk_tree() { - ulonglong counts[2] = {0, 0}; - tree->walk(table_field->table, - count_distinct_single_occurence_walk, counts); - distincts= counts[0]; - distincts_single_occurence= counts[1]; + Basic_stats_collector stats_collector; + tree->walk(table_field->table, basic_stats_collector_walk, + (void*)&stats_collector ); + distincts= stats_collector.get_count_distinct(); + distincts_single_occurence= stats_collector.get_count_single_occurence(); } /* @brief Calculate a histogram of the tree */ - void walk_tree_with_histogram(ha_rows rows) + bool walk_tree_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); - distincts= hist_builder.get_count_distinct(); - distincts_single_occurence= hist_builder.get_count_single_occurence(); + Histogram_base *hist= table_field->collected_stats->histogram; + Histogram_builder *hist_builder= + hist->create_builder(table_field, tree_key_length, rows); + + if (tree->walk(table_field->table, histogram_build_walk, + (void*)hist_builder)) + { + delete hist_builder; + return true; // Error + } + hist_builder->finalize(); + distincts= hist_builder->counters.get_count_distinct(); + distincts_single_occurence= hist_builder->counters. + get_count_single_occurence(); + delete hist_builder; + return false; } ulonglong get_count_distinct() @@ -1712,20 +1805,11 @@ public: /* @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() + Histogram_base *get_histogram() { - return table_field->collected_stats->histogram.get_values(); + return table_field->collected_stats->histogram; } }; @@ -2125,26 +2209,13 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) ulonglong *idx_avg_frequency= (ulonglong*) alloc_root(&table->mem_root, sizeof(ulonglong) * key_parts); - uint hist_size= thd->variables.histogram_size; - Histogram_type hist_type= (Histogram_type) (thd->variables.histogram_type); - uchar *histogram= NULL; - if (hist_size > 0) - { - if ((histogram= (uchar *) alloc_root(&table->mem_root, - hist_size * columns))) - bzero(histogram, hist_size * columns); - - } - - if (!table_stats || !column_stats || !index_stats || !idx_avg_frequency || - (hist_size && !histogram)) + if (!table_stats || !column_stats || !index_stats || !idx_avg_frequency) 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) * columns); @@ -2152,10 +2223,7 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) { 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; + column_stats->histogram = NULL; (*field_ptr)->collected_stats= column_stats++; } } @@ -2177,6 +2245,25 @@ int alloc_statistics_for_table(THD* thd, TABLE *table) DBUG_RETURN(0); } +/* + Free the "local" statistics for table. + We only free the statistics that is not on MEM_ROOT and needs to be + explicitly freed. +*/ +void free_statistics_for_table(THD *thd, TABLE *table) +{ + for (Field **field_ptr= table->field; *field_ptr; field_ptr++) + { + // Only delete the histograms that are exclusivly owned by this thread + if ((*field_ptr)->collected_stats && + (*field_ptr)->collected_stats->histogram && + (*field_ptr)->collected_stats->histogram->get_owner() == thd) + { + delete (*field_ptr)->collected_stats->histogram; + (*field_ptr)->collected_stats->histogram= NULL; + } + } +} /** @brief @@ -2383,7 +2470,8 @@ bool Column_statistics_collected::add() */ inline -void Column_statistics_collected::finish(ha_rows rows, double sample_fraction) +bool Column_statistics_collected::finish(MEM_ROOT *mem_root, ha_rows rows, + double sample_fraction) { double val; @@ -2401,13 +2489,32 @@ void Column_statistics_collected::finish(ha_rows rows, double sample_fraction) } if (count_distinct) { - uint hist_size= count_distinct->get_hist_size(); + uint hist_size= current_thd->variables.histogram_size; + Histogram_type hist_type= + (Histogram_type) (current_thd->variables.histogram_type); + bool have_histogram= false; + if (hist_size != 0 && hist_type != INVALID_HISTOGRAM) + { + have_histogram= true; + histogram= create_histogram(mem_root, hist_type, current_thd); + histogram->init_for_collection(mem_root, hist_type, hist_size); + } /* Compute cardinality statistics and optionally histogram. */ - if (hist_size == 0) + if (!have_histogram) count_distinct->walk_tree(); else - count_distinct->walk_tree_with_histogram(rows - nulls); + { + if (count_distinct->walk_tree_with_histogram(rows - nulls)) + { + delete histogram; + histogram= NULL; + + delete count_distinct; + count_distinct= NULL; + return true; // Error + } + } ulonglong distincts= count_distinct->get_count_distinct(); ulonglong distincts_single_occurence= @@ -2442,15 +2549,14 @@ void Column_statistics_collected::finish(ha_rows rows, double sample_fraction) set_not_null(COLUMN_STAT_AVG_FREQUENCY); } else - hist_size= 0; - histogram.set_size(hist_size); + have_histogram= false; + set_not_null(COLUMN_STAT_HIST_SIZE); - if (hist_size && distincts) + if (have_histogram && distincts && histogram) { 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; } @@ -2459,7 +2565,8 @@ void Column_statistics_collected::finish(ha_rows rows, double sample_fraction) val= 1.0; set_avg_frequency(val); set_not_null(COLUMN_STAT_AVG_FREQUENCY); - } + } + return false; } @@ -2710,7 +2817,10 @@ int collect_statistics_for_table(THD *thd, TABLE *table) continue; bitmap_set_bit(table->write_set, table_field->field_index); if (!rc) - table_field->collected_stats->finish(rows, sample_fraction); + { + rc= table_field->collected_stats->finish(&table->mem_root, rows, + sample_fraction); + } else table_field->collected_stats->cleanup(); } @@ -2790,7 +2900,7 @@ int update_statistics_for_table(THD *thd, TABLE *table) start_new_trans new_trans(thd); - if (open_stat_tables(thd, tables, TRUE)) + if ((open_stat_tables(thd, tables, TRUE))) DBUG_RETURN(rc); save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); @@ -2916,16 +3026,17 @@ 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; + bool have_histograms= false; 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(); + if (table_field->read_stats->histogram_type_on_disk != INVALID_HISTOGRAM) + have_histograms= true; } - table_share->stats_cb.total_hist_size= total_hist_size; + table_share->stats_cb.have_histograms= have_histograms; /* Read statistics from the statistical table index_stats */ stat_table= stat_tables[INDEX_STAT].table; @@ -3021,6 +3132,9 @@ void delete_stat_values_for_table_share(TABLE_SHARE *table_share) delete column_stats->max_value; column_stats->max_value= NULL; } + + delete column_stats->histogram; + column_stats->histogram=NULL; } } @@ -3065,28 +3179,28 @@ int read_histograms_for_table(THD *thd, TABLE *table, TABLE_LIST *stat_tables) if (stats_cb->start_histograms_load()) { - uchar *histogram= (uchar *) alloc_root(&stats_cb->mem_root, - stats_cb->total_hist_size); - if (!histogram) - { - stats_cb->abort_histograms_load(); - DBUG_RETURN(1); - } - memset(histogram, 0, stats_cb->total_hist_size); - Column_stat column_stat(stat_tables[COLUMN_STAT].table, table); + + /* + The process of histogram loading makes use of the field it is for. Mark + all fields as readable/writable in order to allow that. + */ + MY_BITMAP *old_sets[2]; + dbug_tmp_use_all_columns(table, old_sets, &table->read_set, &table->write_set); + for (Field **field_ptr= table->s->field; *field_ptr; field_ptr++) { Field *table_field= *field_ptr; - if (uint hist_size= table_field->read_stats->histogram.get_size()) + if (table_field->read_stats->histogram_type_on_disk != INVALID_HISTOGRAM) { column_stat.set_key_fields(table_field); - table_field->read_stats->histogram.set_values(histogram); - column_stat.get_histogram_value(); - histogram+= hist_size; + table_field->read_stats->histogram= + column_stat.load_histogram(&stats_cb->mem_root); } } stats_cb->end_histograms_load(); + + dbug_tmp_restore_column_maps(&table->read_set, &table->write_set, old_sets); } table->histograms_are_read= true; DBUG_RETURN(0); @@ -3775,15 +3889,11 @@ double get_column_range_cardinality(Field *field, if (avg_frequency > 1.0 + 0.000001 && col_stats->min_max_values_are_provided()) { - Histogram *hist= &col_stats->histogram; - if (hist->is_usable(thd)) + Histogram_base *hist = col_stats->histogram; + if (hist && hist->is_usable(thd)) { - store_key_image_to_rec(field, (uchar *) min_endp->key, - field->key_length()); - double pos= field->pos_in_interval(col_stats->min_value, - col_stats->max_value); res= col_non_nulls * - hist->point_selectivity(pos, + hist->point_selectivity(field, min_endp, avg_frequency / col_non_nulls); } } @@ -3798,34 +3908,41 @@ double get_column_range_cardinality(Field *field, { if (col_stats->min_max_values_are_provided()) { - double sel, min_mp_pos, max_mp_pos; - - if (min_endp && !(field->null_ptr && min_endp->key[0])) + Histogram_base *hist= col_stats->histogram; + double avg_frequency= col_stats->get_avg_frequency(); + double sel; + if (hist && hist->is_usable(thd)) { - store_key_image_to_rec(field, (uchar *) min_endp->key, - field->key_length()); - min_mp_pos= field->pos_in_interval(col_stats->min_value, - col_stats->max_value); + sel= hist->range_selectivity(field, min_endp, max_endp, + avg_frequency / col_non_nulls); + res= col_non_nulls * sel; } else - min_mp_pos= 0.0; - if (max_endp) { - store_key_image_to_rec(field, (uchar *) max_endp->key, - field->key_length()); - max_mp_pos= field->pos_in_interval(col_stats->min_value, - col_stats->max_value); - } - else - max_mp_pos= 1.0; + double min_mp_pos, max_mp_pos; + if (min_endp && !(field->null_ptr && min_endp->key[0])) + { + store_key_image_to_rec(field, (uchar *) min_endp->key, + field->key_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, + field->key_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_usable(thd)) - sel= hist->range_selectivity(min_mp_pos, max_mp_pos); - else - sel= (max_mp_pos - min_mp_pos); - res= col_non_nulls * sel; - set_if_bigger(res, col_stats->get_avg_frequency()); + sel = (max_mp_pos - min_mp_pos); + res= col_non_nulls * sel; + set_if_bigger(res, avg_frequency); + } } else res= col_non_nulls; @@ -3835,13 +3952,13 @@ double get_column_range_cardinality(Field *field, return res; } - - /* Estimate selectivity of "col=const" using a histogram - @param pos Position of the "const" between column's min_value and - max_value. This is a number in [0..1] range. + @param field the field to estimate its selectivity. + + @param endpoint The constant + @param avg_sel Average selectivity of condition "col=const" in this table. It is calcuated as (#non_null_values / #distinct_values). @@ -3870,9 +3987,15 @@ double get_column_range_cardinality(Field *field, value. */ -double Histogram::point_selectivity(double pos, double avg_sel) +double Histogram_binary::point_selectivity(Field *field, key_range *endpoint, + double avg_sel) { double sel; + Column_statistics *col_stats= field->read_stats; + store_key_image_to_rec(field, (uchar *) endpoint->key, + field->key_length()); + double pos= field->pos_in_interval(col_stats->min_value, + col_stats->max_value); /* Find the bucket that contains the value 'pos'. */ uint min= find_bucket(pos, TRUE); uint pos_value= (uint) (pos * prec_factor()); @@ -3906,7 +4029,7 @@ double Histogram::point_selectivity(double pos, double avg_sel) /* The value 'pos' fits within one single histogram bucket. - Histogram buckets have the same numbers of rows, but they cover + Histogram_binary buckets have the same numbers of rows, but they cover different ranges of values. We assume that values are uniformly distributed across the [0..1] value @@ -3951,6 +4074,43 @@ double Histogram::point_selectivity(double pos, double avg_sel) return sel; } + +double Histogram_binary::range_selectivity(Field *field, + key_range *min_endp, + key_range *max_endp, + double avg_sel) +{ + double sel, min_mp_pos, max_mp_pos; + Column_statistics *col_stats= field->read_stats; + + if (min_endp && !(field->null_ptr && min_endp->key[0])) + { + store_key_image_to_rec(field, (uchar *) min_endp->key, + field->key_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, + field->key_length()); + max_mp_pos= + field->pos_in_interval(col_stats->min_value, col_stats->max_value); + } + else + max_mp_pos= 1.0; + + double bucket_sel= 1.0 / (get_width() + 1); + uint min= find_bucket(min_mp_pos, TRUE); + uint max= find_bucket(max_mp_pos, FALSE); + sel= bucket_sel * (max - min + 1); + + set_if_bigger(sel, avg_sel); + return sel; +} + /* Check whether the table is one of the persistent statistical tables. */ diff --git a/sql/sql_statistics.h b/sql/sql_statistics.h index 35b3aa33acc..c0df15ea4ad 100644 --- a/sql/sql_statistics.h +++ b/sql/sql_statistics.h @@ -16,6 +16,9 @@ #ifndef SQL_STATISTICS_H #define SQL_STATISTICS_H +#include <vector> +#include <string> + /* For COMPLEMENTARY_FOR_QUERIES and PREFERABLY_FOR_QUERIES they are similar to the COMPLEMENTARY and PREFERABLY respectively except that @@ -42,7 +45,9 @@ typedef enum enum_histogram_type { SINGLE_PREC_HB, - DOUBLE_PREC_HB + DOUBLE_PREC_HB, + JSON_HB, + INVALID_HISTOGRAM } Histogram_type; enum enum_stat_tables @@ -120,6 +125,7 @@ int read_statistics_for_tables(THD *thd, TABLE_LIST *tables); int collect_statistics_for_table(THD *thd, TABLE *table); void delete_stat_values_for_table_share(TABLE_SHARE *table_share); int alloc_statistics_for_table(THD *thd, TABLE *table); +void free_statistics_for_table(THD *thd, TABLE *table); int update_statistics_for_table(THD *thd, TABLE *table); int delete_statistics_for_table(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *tab); int delete_statistics_for_column(THD *thd, TABLE *tab, Field *col); @@ -140,9 +146,82 @@ double get_column_range_cardinality(Field *field, bool is_stat_table(const LEX_CSTRING *db, LEX_CSTRING *table); bool is_eits_usable(Field* field); -class Histogram +class Histogram_builder; + +/* + Common base for all histograms +*/ +class Histogram_base { +public: + virtual bool parse(MEM_ROOT *mem_root, + const char *db_name, const char *table_name, + Field *field, Histogram_type type_arg, + const char *hist_data, size_t hist_data_len)= 0; + virtual void serialize(Field *to_field)= 0; + + virtual Histogram_type get_type()=0; + + virtual uint get_width()=0; + + /* + The creation-time workflow is: + * create a histogram + * init_for_collection() + * create_builder() + * feed the data to the builder + * serialize(); + */ + virtual void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, + ulonglong size)=0; + virtual Histogram_builder *create_builder(Field *col, uint col_len, + ha_rows rows)=0; + + /* + This function checks that histograms should be usable only when + 1) the level of optimizer_use_condition_selectivity > 3 + */ + bool is_usable(THD *thd) + { + return thd->variables.optimizer_use_condition_selectivity > 3; + } + + + virtual double point_selectivity(Field *field, key_range *endpoint, + double avg_sel)=0; + virtual double range_selectivity(Field *field, key_range *min_endp, + key_range *max_endp, double avg_sel)=0; + + /* + Legacy: return the size of the histogram on disk. + This will be stored in mysql.column_stats.hist_size column. + The value is not really needed as one can look at + LENGTH(mysql.column_stats.histogram) directly. + */ + virtual uint get_size()=0; + virtual ~Histogram_base()= default; + + Histogram_base() : owner(NULL) {} + + /* + Memory management: a histogram may be (exclusively) "owned" by a particular + thread (done for histograms that are being collected). By default, a + histogram has owner==NULL and is not owned by any particular thread. + */ + THD *get_owner() { return owner; } + void set_owner(THD *thd) { owner=thd; } +private: + THD *owner; +}; + + +/* + A Height-balanced histogram that stores numeric fractions +*/ + +class Histogram_binary : public Histogram_base +{ private: Histogram_type type; uint8 size; /* Size of values array, in bytes */ @@ -155,22 +234,25 @@ private: return ((uint) (1 << 8) - 1); case DOUBLE_PREC_HB: return ((uint) (1 << 16) - 1); + default: + DBUG_ASSERT(0); } return 1; } public: - uint get_width() + uint get_width() override { switch (type) { case SINGLE_PREC_HB: return size; case DOUBLE_PREC_HB: return size / 2; + default: + DBUG_ASSERT(0); } return 0; } - private: uint get_value(uint i) { @@ -180,6 +262,8 @@ private: return (uint) (((uint8 *) values)[i]); case DOUBLE_PREC_HB: return (uint) uint2korr(values + i * 2); + default: + DBUG_ASSERT(0); } return 0; } @@ -224,70 +308,124 @@ private: } public: + uint get_size() override {return (uint)size;} - uint get_size() { return (uint) size; } - - Histogram_type get_type() { return type; } - - uchar *get_values() { return (uchar *) values; } + Histogram_type get_type() override { return type; } - 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(); } - - /* - This function checks that histograms should be usable only when - 1) the level of optimizer_use_condition_selectivity > 3 - 2) histograms have been collected - */ - bool is_usable(THD *thd) - { - return thd->variables.optimizer_use_condition_selectivity > 3 && - is_available(); - } + bool parse(MEM_ROOT *mem_root, const char*, const char*, Field*, + Histogram_type type_arg, const char *hist_data, + size_t hist_data_len) override; + void serialize(Field *to_field) override; + void init_for_collection(MEM_ROOT *mem_root, Histogram_type htype_arg, + ulonglong size) override; + Histogram_builder *create_builder(Field *col, uint col_len, + ha_rows rows) override; void set_value(uint i, double val) { switch (type) { - case SINGLE_PREC_HB: + case SINGLE_PREC_HB: ((uint8 *) values)[i]= (uint8) (val * prec_factor()); return; case DOUBLE_PREC_HB: int2store(values + i * 2, val * prec_factor()); return; + default: + DBUG_ASSERT(0); + return; } } void set_prev_value(uint i) { switch (type) { - case SINGLE_PREC_HB: + case SINGLE_PREC_HB: ((uint8 *) values)[i]= ((uint8 *) values)[i-1]; return; case DOUBLE_PREC_HB: int2store(values + i * 2, uint2korr(values + i * 2 - 2)); return; + default: + DBUG_ASSERT(0); + 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 range_selectivity(Field *field, key_range *min_endp, + key_range *max_endp, double avg_sel) override; + /* Estimate selectivity of "col=const" using a histogram */ - double point_selectivity(double pos, double avg_sel); + double point_selectivity(Field *field, key_range *endpoint, + double avg_sel) override; +}; + + +/* + This is used to collect the the basic statistics from a Unique object: + - count of values + - count of distinct values + - count of distinct values that have occurred only once +*/ + +class Basic_stats_collector +{ + ulonglong count; /* number of values retrieved */ + ulonglong count_distinct; /* number of distinct values retrieved */ + /* number of distinct values that occured only once */ + ulonglong count_distinct_single_occurence; + +public: + Basic_stats_collector() + { + count= 0; + count_distinct= 0; + count_distinct_single_occurence= 0; + } + + ulonglong get_count_distinct() const { return count_distinct; } + ulonglong get_count_single_occurence() const + { + return count_distinct_single_occurence; + } + ulonglong get_count() const { return count; } + + void next(void *elem, element_count elem_cnt) + { + count_distinct++; + if (elem_cnt == 1) + count_distinct_single_occurence++; + count+= elem_cnt; + } +}; + + +/* + Histogram_builder is a helper class that is used to build histograms + for columns. + + Do not create directly, call Histogram->get_builder(...); +*/ + +class Histogram_builder +{ +protected: + 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 */ + + Histogram_builder(Field *col, uint col_len, ha_rows rows) : + column(col), col_length(col_len), records(rows) + {} + +public: + // A histogram builder will also collect the counters + Basic_stats_collector counters; + + virtual int next(void *elem, element_count elem_cnt)=0; + virtual void finalize()=0; + virtual ~Histogram_builder(){} }; @@ -308,7 +446,6 @@ public: /* Array of records per key for index prefixes */ ulonglong *idx_avg_frequency; - uchar *histograms; /* Sequence of histograms */ }; @@ -370,8 +507,10 @@ private: ulonglong avg_frequency; public: + /* Histogram type as specified in mysql.column_stats.hist_type */ + Histogram_type histogram_type_on_disk; - Histogram histogram; + Histogram_base *histogram; uint32 no_values_provided_bitmap() { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 7127cbc00f6..447c1f07310 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -6496,7 +6496,8 @@ static Sys_var_enum Sys_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.", + "DOUBLE_PREC_HB - double precision height-balanced, " + "JSON_HB - height-balanced, stored as JSON.", SESSION_VAR(histogram_type), CMD_LINE(REQUIRED_ARG), histogram_types, DEFAULT(1)); diff --git a/sql/table.h b/sql/table.h index 6aa75df39c6..221e18bc926 100644 --- a/sql/table.h +++ b/sql/table.h @@ -679,16 +679,21 @@ class TABLE_STATISTICS_CB public: MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */ Table_statistics *table_stats; /* Structure to access the statistical data */ - ulong total_hist_size; /* Total size of all histograms */ + + /* + Whether the table has histograms. + (If the table has none, histograms_are_ready() can finish sooner) + */ + bool have_histograms; bool histograms_are_ready() const { - return !total_hist_size || hist_state.is_ready(); + return !have_histograms || hist_state.is_ready(); } bool start_histograms_load() { - return total_hist_size && hist_state.start_load(); + return have_histograms && hist_state.start_load(); } void end_histograms_load() { hist_state.end_load(); } diff --git a/strings/json_lib.c b/strings/json_lib.c index 7b895c216b5..836255bdf28 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1637,7 +1637,7 @@ int json_escape(CHARSET_INFO *str_cs, if (c_len < 0) { /* JSON buffer is depleted. */ - return -1; + return JSON_ERROR_OUT_OF_SPACE; } /* JSON charset cannot convert this character. */ @@ -1649,7 +1649,7 @@ int json_escape(CHARSET_INFO *str_cs, json+= c_len, json_end)) <= 0) { /* JSON buffer is depleted. */ - return -1; + return JSON_ERROR_OUT_OF_SPACE; } json+= c_len; @@ -1682,11 +1682,11 @@ int json_escape(CHARSET_INFO *str_cs, continue; } /* JSON buffer is depleted. */ - return -1; + return JSON_ERROR_OUT_OF_SPACE; } } else /* c_len == 0, an illegal symbol. */ - return -1; + return JSON_ERROR_ILLEGAL_SYMBOL; } return (int)(json - json_start); |