From 01c82173dd8b6ea627dec949dbc57dfcc94a656d Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 26 Jan 2023 11:38:31 +0200 Subject: [PATCH] Removed /2 of InnoDB ref_per_key[] estimates The original code was there to favor index search over table scan. This is not needed anymore as the cost calculations for table scans and index lookups are now more exact. --- mysql-test/main/derived_split_innodb.result | 8 +++---- mysql-test/main/join_outer_innodb.result | 8 +++---- mysql-test/main/mdev-25830.result | 8 +++---- mysql-test/main/order_by_innodb.result | 2 +- mysql-test/main/subselect2.result | 4 ++-- mysql-test/main/subselect_innodb.result | 24 +++++++++++++++++++ mysql-test/main/subselect_innodb.test | 14 +++++++++++ mysql-test/main/update_use_source.result | 2 +- .../suite/innodb/r/innodb-index-online.result | 2 +- .../suite/innodb/r/innodb_bug57252.result | 2 +- mysql-test/suite/innodb/r/innodb_stats.result | 8 +++---- .../suite/innodb/r/innodb_stats_fetch.result | 8 +++---- storage/innobase/handler/ha_innodb.cc | 7 ------ 13 files changed, 64 insertions(+), 33 deletions(-) diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result index b119b7a6c0e..9569b85c234 100644 --- a/mysql-test/main/derived_split_innodb.result +++ b/mysql-test/main/derived_split_innodb.result @@ -208,8 +208,8 @@ t2 where t1.id = dt.id and t1.itemid = dt.itemid and t2.id=t1.itemid; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 -1 PRIMARY t1 ref idx idx 4 test.t2.id 1 -1 PRIMARY ref key0 key0 9 test.t2.id,test.t1.id 1 +1 PRIMARY ref key1 key1 4 test.t2.id 1 +1 PRIMARY t1 ref idx idx 4 test.t2.id 3 Using where 2 DERIVED t3 ref idx1,idx2 idx1 4 const 5 Using where; Using index select t1.id, t1.itemid, dt.id, t2.id from t1, @@ -227,8 +227,8 @@ t2 where t1.id = dt.id and t1.itemid = dt.itemid and t2.id=t1.itemid; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 -1 PRIMARY t1 ref idx idx 4 test.t2.id 1 -1 PRIMARY ref key0 key0 9 test.t2.id,test.t1.id 1 +1 PRIMARY ref key1 key1 4 test.t2.id 1 +1 PRIMARY t1 ref idx idx 4 test.t2.id 3 Using where 2 DERIVED t3 ref idx1 idx1 4 const 5 Using where; Using index select t1.id, t1.itemid, dt.id, t2.id from t1, diff --git a/mysql-test/main/join_outer_innodb.result b/mysql-test/main/join_outer_innodb.result index 71ff11781a8..208113b4870 100644 --- a/mysql-test/main/join_outer_innodb.result +++ b/mysql-test/main/join_outer_innodb.result @@ -448,9 +448,9 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t12 eq_ref PRIMARY PRIMARY 4 test.t11.k3 1 Using where 1 SIMPLE l2 eq_ref PRIMARY PRIMARY 4 test.t11.k4 1 Using where 1 SIMPLE t9 ref PRIMARY PRIMARY 1 test.t1.a4 1 -1 SIMPLE t13 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where +1 SIMPLE t13 ref PRIMARY,m3 m3 8 const,test.t1.a1 3 Using index 1 SIMPLE l4 eq_ref PRIMARY PRIMARY 4 test.t13.m2 1 Using where -1 SIMPLE m2 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where +1 SIMPLE m2 ref PRIMARY,m3 m3 8 const,test.t1.a1 3 Using index 1 SIMPLE l3 eq_ref PRIMARY PRIMARY 4 test.m2.m2 1 Using where 1 SIMPLE t14 eq_ref PRIMARY PRIMARY 2 test.t1.a8 1 Using where 1 SIMPLE t15 eq_ref PRIMARY PRIMARY 2 test.t1.a9 1 Using where @@ -471,9 +471,9 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t12 eq_ref PRIMARY PRIMARY 4 test.t11.k3 1 Using where 1 SIMPLE l2 eq_ref PRIMARY PRIMARY 4 test.t11.k4 1 Using where 1 SIMPLE t9 ref PRIMARY PRIMARY 1 test.t1.a4 1 -1 SIMPLE t13 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where +1 SIMPLE t13 ref PRIMARY,m3 m3 8 const,test.t1.a1 3 Using index 1 SIMPLE l4 eq_ref PRIMARY PRIMARY 4 test.t13.m2 1 Using where -1 SIMPLE m2 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where +1 SIMPLE m2 ref PRIMARY,m3 m3 8 const,test.t1.a1 3 Using index 1 SIMPLE l3 eq_ref PRIMARY PRIMARY 4 test.m2.m2 1 Using where 1 SIMPLE t14 eq_ref PRIMARY PRIMARY 2 test.t1.a8 1 Using where 1 SIMPLE t15 eq_ref PRIMARY PRIMARY 2 test.t1.a9 1 Using where diff --git a/mysql-test/main/mdev-25830.result b/mysql-test/main/mdev-25830.result index 2c606205565..6de3e5836d3 100644 --- a/mysql-test/main/mdev-25830.result +++ b/mysql-test/main/mdev-25830.result @@ -25,8 +25,8 @@ ORDER BY sysapproval_approver0.`order` LIMIT 0, 50 ; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 SIMPLE task2 range PRIMARY,sys_class_name_2,sys_domain_path PRIMARY 96 NULL 1 0.00 100.00 100.00 Using where; Using temporary; Using filesort -1 SIMPLE task1 ref PRIMARY,task_parent,sys_class_name_2,sys_domain_path task_parent 99 test.task2.sys_id 1 NULL 100.00 NULL Using index condition; Using where -1 SIMPLE sysapproval_approver0 ref sysapproval_approver_ref5,sys_domain_path,sysapproval_approver_CHG1975376 sysapproval_approver_ref5 99 test.task1.sys_id 1 NULL 100.00 NULL Using index condition; Using where +1 SIMPLE task1 ref PRIMARY,task_parent,sys_class_name_2,sys_domain_path task_parent 99 test.task2.sys_id 2 NULL 100.00 NULL Using index condition; Using where +1 SIMPLE sysapproval_approver0 ref sysapproval_approver_ref5,sys_domain_path,sysapproval_approver_CHG1975376 sysapproval_approver_ref5 99 test.task1.sys_id 3 NULL 100.00 NULL Using index condition; Using where set optimizer_use_condition_selectivity=4; analyze SELECT sysapproval_approver0.`sys_id` FROM ((sysapproval_approver sysapproval_approver0 @@ -48,8 +48,8 @@ ORDER BY sysapproval_approver0.`order` LIMIT 0, 50 ; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 SIMPLE task2 range PRIMARY,sys_class_name_2,sys_domain_path PRIMARY 96 NULL 1 0.00 100.00 100.00 Using where; Using temporary; Using filesort -1 SIMPLE task1 ref PRIMARY,task_parent,sys_class_name_2,sys_domain_path task_parent 99 test.task2.sys_id 1 NULL 100.00 NULL Using index condition; Using where -1 SIMPLE sysapproval_approver0 ref sysapproval_approver_ref5,sys_domain_path,sysapproval_approver_CHG1975376 sysapproval_approver_ref5 99 test.task1.sys_id 1 NULL 100.00 NULL Using index condition; Using where +1 SIMPLE task1 ref PRIMARY,task_parent,sys_class_name_2,sys_domain_path task_parent 99 test.task2.sys_id 2 NULL 100.00 NULL Using index condition; Using where +1 SIMPLE sysapproval_approver0 ref sysapproval_approver_ref5,sys_domain_path,sysapproval_approver_CHG1975376 sysapproval_approver_ref5 99 test.task1.sys_id 3 NULL 100.00 NULL Using index condition; Using where drop table sysapproval_approver,task; set global innodb_stats_persistent= @innodb_stats_persistent_save; set global innodb_stats_persistent_sample_pages= diff --git a/mysql-test/main/order_by_innodb.result b/mysql-test/main/order_by_innodb.result index 11287f25698..ad4acad3319 100644 --- a/mysql-test/main/order_by_innodb.result +++ b/mysql-test/main/order_by_innodb.result @@ -258,7 +258,7 @@ dd.d1, dd.d2, dd.id limit 1 id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL # 1 PRIMARY t2 eq_ref PRIMARY,id2 id2 8 test.t1.id,func # Using where; Using index -2 DEPENDENT SUBQUERY dd ref id2,for_latest_sort id2 4 test.t1.id # Using where; Using filesort +2 DEPENDENT SUBQUERY dd range id2,for_latest_sort for_latest_sort 6 NULL # Using where drop table t1,t2,t3; # End of 10.2 tests # diff --git a/mysql-test/main/subselect2.result b/mysql-test/main/subselect2.result index 0d2f7372887..e62f0617574 100644 --- a/mysql-test/main/subselect2.result +++ b/mysql-test/main/subselect2.result @@ -125,8 +125,8 @@ DOCID DOCNAME DOCTYPEID FOLDERID AUTHOR CREATED TITLE SUBTITLE DOCABSTRACT PUBLI c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff17444553544200 c373e9f5ad0796c0eca4444553544200 Goldilocks 2003-06-09 11:21:06 Title: Last Discussion NULL Setting new abstract and keeping doc checked out 2003-06-09 10:51:26 2003-06-09 10:51:26 NULL NULL NULL 03eea05112b845949f3fd03278b5fe43 2003-06-09 11:21:06 admin 0 NULL Discussion NULL NULL EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3_a.FOLDERID FROM t3 as t3_a WHERE t3_a.PARENTID IN(SELECT t3_b.FOLDERID FROM t3 as t3_b WHERE t3_b.PARENTID IN(SELECT t3_c.FOLDERID FROM t3 as t3_c WHERE t3_c.PARENTID IN(SELECT t3_d.FOLDERID FROM t3 as t3_d WHERE t3_d.PARENTID IN(SELECT t3_e.FOLDERID FROM t3 as t3_e WHERE t3_e.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3_e.FOLDERNAME = 'Level1') AND t3_d.FOLDERNAME = 'Level2') AND t3_c.FOLDERNAME = 'Level3') AND t3_b.FOLDERNAME = 'CopiedFolder') AND t3_a.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion'; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 ALL DDOCTYPEID_IDX,DFOLDERID_IDX NULL NULL NULL 9 Using where -1 PRIMARY t4 eq_ref PRIMARY PRIMARY 34 test.t2.DOCTYPEID 1 +1 PRIMARY t4 ALL PRIMARY NULL NULL NULL 10 +1 PRIMARY t2 ALL DDOCTYPEID_IDX,DFOLDERID_IDX NULL NULL NULL 9 Using where; Using join buffer (flat, BNL join) 1 PRIMARY t1 eq_ref PRIMARY PRIMARY 34 test.t2.DOCID 1 1 PRIMARY t3_a eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t2.FOLDERID 1 Using where 1 PRIMARY t3_b eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3_a.PARENTID 1 Using where diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result index b74ad66366f..2ce0096831b 100644 --- a/mysql-test/main/subselect_innodb.result +++ b/mysql-test/main/subselect_innodb.result @@ -560,6 +560,7 @@ id select_type table type possible_keys key key_len ref rows Extra # # MDEV-6081: ORDER BY+ref(const): selectivity is very incorrect (MySQL Bug#14338686) # +insert into t2 select seq,seq,seq from seq_10000_to_11000; alter table t2 add key2 int; update t2 set key2=key1; alter table t2 add key(key2); @@ -580,6 +581,29 @@ t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL # 2 DEPENDENT SUBQUERY t2 ref key1 key1 5 test.t1.a # Using where; Using filesort +select +(SELECT +concat(id, '-', key1, '-', col1) +FROM t2 +WHERE t2.key1 = t1.a +ORDER BY t2.key2 ASC LIMIT 1) +from +t1; +(SELECT +concat(id, '-', key1, '-', col1) +FROM t2 +WHERE t2.key1 = t1.a +ORDER BY t2.key2 ASC LIMIT 1) +100-0-123456 +101-1-123456 +102-2-123456 +103-3-123456 +104-4-123456 +105-5-123456 +106-6-123456 +107-7-123456 +108-8-123456 +109-9-123456 drop table t1,t2; # # MDEV-12931: semi-join in ON expression of STRAIGHT_JOIN diff --git a/mysql-test/main/subselect_innodb.test b/mysql-test/main/subselect_innodb.test index e354ddc4496..c1dd58887b0 100644 --- a/mysql-test/main/subselect_innodb.test +++ b/mysql-test/main/subselect_innodb.test @@ -1,5 +1,6 @@ -- source include/no_valgrind_without_big.inc -- source include/have_innodb.inc +-- source include/have_sequence.inc # Note: the tests uses only non-semijoin subqueries so semi-join switch # settings are not relevant. @@ -568,6 +569,11 @@ from --echo # MDEV-6081: ORDER BY+ref(const): selectivity is very incorrect (MySQL Bug#14338686) --echo # + +# Table t2 has 100 equal values / key value, which causes it to prefer index scan instead of ref +# Fix it by adding more different values to key1 +insert into t2 select seq,seq,seq from seq_10000_to_11000; + alter table t2 add key2 int; update t2 set key2=key1; alter table t2 add key(key2); @@ -583,6 +589,14 @@ explain select ORDER BY t2.key2 ASC LIMIT 1) from t1; +select + (SELECT + concat(id, '-', key1, '-', col1) + FROM t2 + WHERE t2.key1 = t1.a + ORDER BY t2.key2 ASC LIMIT 1) +from + t1; drop table t1,t2; diff --git a/mysql-test/main/update_use_source.result b/mysql-test/main/update_use_source.result index 2774e7ee92d..91b2f7c8890 100644 --- a/mysql-test/main/update_use_source.result +++ b/mysql-test/main/update_use_source.result @@ -317,7 +317,7 @@ rollback; explain update t1 set c1=0 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 > 3; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 range t1_c2 t1_c2 5 NULL 2 Using where -2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 4 Using index +2 DEPENDENT SUBQUERY a ref t1_c2 t1_c2 5 test.t1.c2 8 Using index start transaction; update t1 set c1=c1+10 where exists (select 'X' from t1 a where a.c2 = t1.c2) and c2 >= 3; affected rows: 4 diff --git a/mysql-test/suite/innodb/r/innodb-index-online.result b/mysql-test/suite/innodb/r/innodb-index-online.result index 6404a3812b3..150f950d591 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online.result +++ b/mysql-test/suite/innodb/r/innodb-index-online.result @@ -204,7 +204,7 @@ CREATE INDEX c2d ON t1(c2); SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment Ignored t1 0 PRIMARY 1 c1 A 80 NULL NULL BTREE NO -t1 1 c2d 1 c2 A 10 NULL NULL YES BTREE NO +t1 1 c2d 1 c2 A 5 NULL NULL YES BTREE NO EXPLAIN SELECT COUNT(*) FROM t1 WHERE c2 > 3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range c2d c2d 5 NULL 32 Using where; Using index diff --git a/mysql-test/suite/innodb/r/innodb_bug57252.result b/mysql-test/suite/innodb/r/innodb_bug57252.result index 66183c2c42d..18e47900e41 100644 --- a/mysql-test/suite/innodb/r/innodb_bug57252.result +++ b/mysql-test/suite/innodb/r/innodb_bug57252.result @@ -1,5 +1,5 @@ cardinality -2 +1 Table Op Msg_type Msg_text test.bug57252 analyze status Engine-independent statistics collected test.bug57252 analyze status OK diff --git a/mysql-test/suite/innodb/r/innodb_stats.result b/mysql-test/suite/innodb/r/innodb_stats.result index b300af767c6..cb5247f081e 100644 --- a/mysql-test/suite/innodb/r/innodb_stats.result +++ b/mysql-test/suite/innodb/r/innodb_stats.result @@ -151,7 +151,7 @@ INDEX_NAME a_key SEQ_IN_INDEX 1 COLUMN_NAME a COLLATION A -CARDINALITY 2 +CARDINALITY 1 SUB_PART NULL PACKED NULL NULLABLE YES @@ -204,7 +204,7 @@ INDEX_NAME a_key SEQ_IN_INDEX 1 COLUMN_NAME a COLLATION A -CARDINALITY 3 +CARDINALITY 1 SUB_PART NULL PACKED NULL NULLABLE YES @@ -257,7 +257,7 @@ INDEX_NAME a_key SEQ_IN_INDEX 1 COLUMN_NAME a COLLATION A -CARDINALITY 2 +CARDINALITY 1 SUB_PART NULL PACKED NULL NULLABLE YES @@ -522,7 +522,7 @@ INDEX_NAME a_key SEQ_IN_INDEX 1 COLUMN_NAME a COLLATION A -CARDINALITY 10 +CARDINALITY 5 SUB_PART NULL PACKED NULL NULLABLE YES diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch.result b/mysql-test/suite/innodb/r/innodb_stats_fetch.result index d7b7d78ec71..6df1831db48 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch.result @@ -131,16 +131,16 @@ FROM information_schema.statistics WHERE table_name = 'test_ps_fetch' ORDER BY index_name, seq_in_index; seq_in_index 1 column_name c -cardinality 6 +cardinality 3 seq_in_index 2 column_name d -cardinality 22 +cardinality 11 seq_in_index 1 column_name a -cardinality 40 +cardinality 20 seq_in_index 2 column_name b -cardinality 200 +cardinality 90 SELECT table_rows, avg_row_length, max_data_length, index_length FROM information_schema.tables WHERE table_name = 'test_ps_fetch'; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a625ca56347..7cba8c46fff 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -14891,13 +14891,6 @@ ha_innobase::info_low( innodb_rec_per_key(index, j, stats.records)); - /* Since MySQL seems to favor table scans - too much over index searches, we pretend - index selectivity is 2 times better than - our estimate: */ - - rec_per_key_int = rec_per_key_int / 2; - if (rec_per_key_int == 0) { rec_per_key_int = 1; }