summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2022-01-19 18:35:27 +0300
committerSergei Petrunia <psergey@askmonty.org>2022-01-19 18:35:27 +0300
commitda78030ec87e30d2218a0de182ffb87fc541da97 (patch)
tree7f7ce9bb818d56679eaf034b52f05738b8d83da1
parente222e44d1bfc995870430bb90d8ac97e91f66cb4 (diff)
parentce4956f3229a8b2c26a4913fdbc190b5c822cb8e (diff)
downloadmariadb-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
-rw-r--r--include/json_lib.h14
-rw-r--r--libmysqld/CMakeLists.txt1
-rw-r--r--mysql-test/include/default_mysqld.cnf1
-rw-r--r--mysql-test/include/histogram_replaces.inc1
-rw-r--r--mysql-test/include/json_hb_histogram.inc3
-rw-r--r--mysql-test/main/derived_cond_pushdown.result8
-rw-r--r--mysql-test/main/group_min_max.result8
-rw-r--r--mysql-test/main/join_cache.result2
-rw-r--r--mysql-test/main/join_outer.result4
-rw-r--r--mysql-test/main/join_outer_jcl6.result4
-rw-r--r--mysql-test/main/mysqld--help.result3
-rw-r--r--mysql-test/main/opt_trace.result70
-rw-r--r--mysql-test/main/partition.result4
-rw-r--r--mysql-test/main/selectivity.result16
-rw-r--r--mysql-test/main/selectivity_innodb.result16
-rw-r--r--mysql-test/main/statistics.result98
-rw-r--r--mysql-test/main/statistics.test79
-rw-r--r--mysql-test/main/statistics_json.result8324
-rw-r--r--mysql-test/main/statistics_json.test462
-rw-r--r--mysql-test/main/statistics_upgrade.result87
-rw-r--r--mysql-test/main/statistics_upgrade.test67
-rw-r--r--mysql-test/main/statistics_upgrade_not_done.result44
-rw-r--r--mysql-test/main/statistics_upgrade_not_done.test57
-rw-r--r--mysql-test/main/subselect_mat.result24
-rw-r--r--mysql-test/main/subselect_sj_mat.result60
-rw-r--r--mysql-test/main/system_mysql_db.result4
-rw-r--r--mysql-test/main/system_mysql_db_fix40123.result4
-rw-r--r--mysql-test/main/system_mysql_db_fix50030.result4
-rw-r--r--mysql-test/main/system_mysql_db_fix50117.result4
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql.result8
-rw-r--r--mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result8
-rw-r--r--mysql-test/suite/sys_vars/r/histogram_type_basic.result8
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_embedded.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result4
-rw-r--r--scripts/mysql_system_tables.sql2
-rw-r--r--scripts/mysql_system_tables_fix.sql8
-rw-r--r--sql/CMakeLists.txt1
-rw-r--r--sql/field.cc44
-rw-r--r--sql/field.h19
-rw-r--r--sql/item_strfunc.cc10
-rw-r--r--sql/my_json_writer.h2
-rw-r--r--sql/opt_histogram_json.cc1188
-rw-r--r--sql/opt_histogram_json.h148
-rw-r--r--sql/opt_range.cc5
-rw-r--r--sql/share/errmsg-utf8.txt2
-rw-r--r--sql/sql_admin.cc2
-rw-r--r--sql/sql_statistics.cc490
-rw-r--r--sql/sql_statistics.h223
-rw-r--r--sql/sys_vars.cc3
-rw-r--r--sql/table.h11
-rw-r--r--strings/json_lib.c8
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);