From: Jorgen Loland Date: March 15 2011 1:31pm Subject: bzr commit into mysql-trunk branch (jorgen.loland:3279) List-Archive: http://lists.mysql.com/commits/133027 Message-Id: <20110315133108.EB03779E@atum21.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============3202706166791089546==" --===============3202706166791089546== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/jl208045/mysql/wl4800/mysql-next-mr-opt-backporting-wl4800/ based on revid:guilhem.bichot@stripped 3279 Jorgen Loland 2011-03-15 Added test case for multiple ranges over a multi-keypart range Trace failed to print all but the final range in the chosen_range_access_summary{} section of the optimizer trace. Fixed by navigating to the first range interval before printing ranges. modified: mysql-test/include/optimizer_trace_range.inc mysql-test/r/optimizer_trace_range_no_prot.result mysql-test/r/optimizer_trace_range_ps_prot.result sql/opt_range.cc === modified file 'mysql-test/include/optimizer_trace_range.inc' --- a/mysql-test/include/optimizer_trace_range.inc 2011-01-18 13:00:16 +0000 +++ b/mysql-test/include/optimizer_trace_range.inc 2011-03-15 13:31:03 +0000 @@ -120,6 +120,13 @@ EXPLAIN SELECT * FROM t2 WHERE key1a = 5 --echo SELECT * FROM information_schema.OPTIMIZER_TRACE; +# Multiple ranges on key parts in same index +--echo +EXPLAIN SELECT * FROM t2 WHERE (key1a = 5 and key1b < 10 and key1b > 2) or + (key1a = 4 and key1b < 7 and key1b > 3); +--echo +SELECT * FROM information_schema.OPTIMIZER_TRACE; + # more_expensive_than_table_scan --echo EXPLAIN SELECT * FROM t1 WHERE (key1 > 1 OR key2 > 2); === modified file 'mysql-test/r/optimizer_trace_range_no_prot.result' --- a/mysql-test/r/optimizer_trace_range_no_prot.result 2011-03-01 10:55:27 +0000 +++ b/mysql-test/r/optimizer_trace_range_no_prot.result 2011-03-15 13:31:03 +0000 @@ -2111,6 +2111,207 @@ EXPLAIN SELECT * FROM t2 WHERE key1a = 5 ] /* steps */ } 0 +EXPLAIN SELECT * FROM t2 WHERE (key1a = 5 and key1b < 10 and key1b > 2) or +(key1a = 4 and key1b < 7 and key1b > 3); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range PRIMARY,i1b PRIMARY 8 NULL 2 Using index condition + +SELECT * FROM information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE +EXPLAIN SELECT * FROM t2 WHERE (key1a = 5 and key1b < 10 and key1b > 2) or +(key1a = 4 and key1b < 7 and key1b > 3) { + "steps": [ + { + "join_preparation": { + "select#": 1, + "steps": [ + { + "expanded_query": "/* select#1 */ select `test`.`t2`.`key1a` AS `key1a`,`test`.`t2`.`key1b` AS `key1b`,`test`.`t2`.`key2` AS `key2`,`test`.`t2`.`key2_1` AS `key2_1`,`test`.`t2`.`key2_2` AS `key2_2`,`test`.`t2`.`key3` AS `key3` from `test`.`t2` where (((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))" + } + ] /* steps */ + } /* join_preparation */ + }, + { + "join_optimization": { + "select#": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "(((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "(((`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2) and multiple equal(5, `test`.`t2`.`key1a`)) or ((`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3) and multiple equal(4, `test`.`t2`.`key1a`)))" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "(((`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2) and multiple equal(5, `test`.`t2`.`key1a`)) or ((`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3) and multiple equal(4, `test`.`t2`.`key1a`)))" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "(((`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2) and multiple equal(5, `test`.`t2`.`key1a`)) or ((`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3) and multiple equal(4, `test`.`t2`.`key1a`)))" + } + ] /* steps */ + } /* condition_processing */ + }, + { + "ref_optimizer_key_uses": [ + ] /* ref_optimizer_key_uses */ + }, + { + "records_estimation": [ + { + "database": "test", + "table": "t2", + "range_analysis": { + "table_scan": { + "records": 1024, + "cost": 215.15 + } /* table_scan */, + "potential_range_indices": [ + { + "index": "PRIMARY", + "usable": true, + "key_parts": [ + "key1a", + "key1b" + ] /* key_parts */ + }, + { + "index": "i1b", + "usable": true, + "key_parts": [ + "key1b", + "key1a" + ] /* key_parts */ + }, + { + "index": "i2_1", + "usable": false, + "cause": "not_applicable" + }, + { + "index": "i2_2", + "usable": false, + "cause": "not_applicable" + } + ] /* potential_range_indices */, + "setup_range_conditions": [ + ] /* setup_range_conditions */, + "group_index_range": { + "chosen": false, + "cause": "not_group_by_or_distinct" + } /* group_index_range */, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "PRIMARY", + "ranges": [ + "4 <= key1a <= 4 AND 3 < key1b < 7", + "5 <= key1a <= 5 AND 2 < key1b < 10" + ] /* ranges */, + "index_only": false, + "records": 2, + "cost": 4.41, + "rowid_ordered": false, + "chosen": true + }, + { + "index": "i1b", + "ranges": [ + "2 < key1b <= 3 AND 5 <= key1a <= 5", + "3 < key1b < 7", + "7 <= key1b < 10 AND 5 <= key1a <= 5" + ] /* ranges */, + "index_only": false, + "records": 6, + "cost": 10.21, + "rowid_ordered": false, + "chosen": false, + "cause": "cost" + } + ] /* range_scan_alternatives */, + "analyzing_roworder_intersect": { + "usable": false, + "cause": "too_few_roworder_scans" + } /* analyzing_roworder_intersect */ + } /* analyzing_range_alternatives */, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "PRIMARY", + "records": 2, + "ranges": [ + "4 <= key1a <= 4 AND 3 < key1b < 7", + "5 <= key1a <= 5 AND 2 < key1b < 10" + ] /* ranges */ + } /* range_access_plan */, + "records_for_plan": 2, + "cost_for_plan": 4.41, + "chosen": true + } /* chosen_range_access_summary */ + } /* range_analysis */ + } + ] /* records_estimation */ + }, + { + "considered_execution_plans": [ + { + "database": "test", + "table": "t2", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "range", + "records": 2, + "cost": 4.41, + "chosen": true + } + ] /* considered_access_paths */ + } /* best_access_path */, + "cost_for_plan": 4.41, + "records_for_plan": 2, + "chosen": true + } + ] /* considered_execution_plans */ + }, + { + "attaching_conditions_to_tables": { + "original_condition": "(((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))", + "attached_conditions_computation": [ + ] /* attached_conditions_computation */, + "attached_conditions_summary": [ + { + "database": "test", + "table": "t2", + "attached": "(((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))" + } + ] /* attached_conditions_summary */ + } /* attaching_conditions_to_tables */ + }, + { + "refine_plan": [ + { + "database": "test", + "table": "t2", + "scan_type": "table" + } + ] /* refine_plan */ + } + ] /* steps */ + } /* join_optimization */ + }, + { + "join_execution": { + "select#": 1, + "steps": [ + ] /* steps */ + } /* join_execution */ + } + ] /* steps */ +} 0 + EXPLAIN SELECT * FROM t1 WHERE (key1 > 1 OR key2 > 2); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL i1,i2 NULL NULL NULL 1024 Using where === modified file 'mysql-test/r/optimizer_trace_range_ps_prot.result' --- a/mysql-test/r/optimizer_trace_range_ps_prot.result 2011-03-01 10:55:27 +0000 +++ b/mysql-test/r/optimizer_trace_range_ps_prot.result 2011-03-15 13:31:03 +0000 @@ -2111,6 +2111,207 @@ EXPLAIN SELECT * FROM t2 WHERE key1a = 5 ] /* steps */ } 0 +EXPLAIN SELECT * FROM t2 WHERE (key1a = 5 and key1b < 10 and key1b > 2) or +(key1a = 4 and key1b < 7 and key1b > 3); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range PRIMARY,i1b PRIMARY 8 NULL 2 Using index condition + +SELECT * FROM information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE +EXPLAIN SELECT * FROM t2 WHERE (key1a = 5 and key1b < 10 and key1b > 2) or +(key1a = 4 and key1b < 7 and key1b > 3) { + "steps": [ + { + "join_preparation": { + "select#": 1, + "steps": [ + { + "expanded_query": "/* select#1 */ select `test`.`t2`.`key1a` AS `key1a`,`test`.`t2`.`key1b` AS `key1b`,`test`.`t2`.`key2` AS `key2`,`test`.`t2`.`key2_1` AS `key2_1`,`test`.`t2`.`key2_2` AS `key2_2`,`test`.`t2`.`key3` AS `key3` from `test`.`t2` where (((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))" + } + ] /* steps */ + } /* join_preparation */ + }, + { + "join_optimization": { + "select#": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "(((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "(((`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2) and multiple equal(5, `test`.`t2`.`key1a`)) or ((`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3) and multiple equal(4, `test`.`t2`.`key1a`)))" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "(((`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2) and multiple equal(5, `test`.`t2`.`key1a`)) or ((`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3) and multiple equal(4, `test`.`t2`.`key1a`)))" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "(((`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2) and multiple equal(5, `test`.`t2`.`key1a`)) or ((`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3) and multiple equal(4, `test`.`t2`.`key1a`)))" + } + ] /* steps */ + } /* condition_processing */ + }, + { + "ref_optimizer_key_uses": [ + ] /* ref_optimizer_key_uses */ + }, + { + "records_estimation": [ + { + "database": "test", + "table": "t2", + "range_analysis": { + "table_scan": { + "records": 1024, + "cost": 215.15 + } /* table_scan */, + "potential_range_indices": [ + { + "index": "PRIMARY", + "usable": true, + "key_parts": [ + "key1a", + "key1b" + ] /* key_parts */ + }, + { + "index": "i1b", + "usable": true, + "key_parts": [ + "key1b", + "key1a" + ] /* key_parts */ + }, + { + "index": "i2_1", + "usable": false, + "cause": "not_applicable" + }, + { + "index": "i2_2", + "usable": false, + "cause": "not_applicable" + } + ] /* potential_range_indices */, + "setup_range_conditions": [ + ] /* setup_range_conditions */, + "group_index_range": { + "chosen": false, + "cause": "not_group_by_or_distinct" + } /* group_index_range */, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "PRIMARY", + "ranges": [ + "4 <= key1a <= 4 AND 3 < key1b < 7", + "5 <= key1a <= 5 AND 2 < key1b < 10" + ] /* ranges */, + "index_only": false, + "records": 2, + "cost": 4.41, + "rowid_ordered": false, + "chosen": true + }, + { + "index": "i1b", + "ranges": [ + "2 < key1b <= 3 AND 5 <= key1a <= 5", + "3 < key1b < 7", + "7 <= key1b < 10 AND 5 <= key1a <= 5" + ] /* ranges */, + "index_only": false, + "records": 6, + "cost": 10.21, + "rowid_ordered": false, + "chosen": false, + "cause": "cost" + } + ] /* range_scan_alternatives */, + "analyzing_roworder_intersect": { + "usable": false, + "cause": "too_few_roworder_scans" + } /* analyzing_roworder_intersect */ + } /* analyzing_range_alternatives */, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "PRIMARY", + "records": 2, + "ranges": [ + "4 <= key1a <= 4 AND 3 < key1b < 7", + "5 <= key1a <= 5 AND 2 < key1b < 10" + ] /* ranges */ + } /* range_access_plan */, + "records_for_plan": 2, + "cost_for_plan": 4.41, + "chosen": true + } /* chosen_range_access_summary */ + } /* range_analysis */ + } + ] /* records_estimation */ + }, + { + "considered_execution_plans": [ + { + "database": "test", + "table": "t2", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "range", + "records": 2, + "cost": 4.41, + "chosen": true + } + ] /* considered_access_paths */ + } /* best_access_path */, + "cost_for_plan": 4.41, + "records_for_plan": 2, + "chosen": true + } + ] /* considered_execution_plans */ + }, + { + "attaching_conditions_to_tables": { + "original_condition": "(((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))", + "attached_conditions_computation": [ + ] /* attached_conditions_computation */, + "attached_conditions_summary": [ + { + "database": "test", + "table": "t2", + "attached": "(((`test`.`t2`.`key1a` = 5) and (`test`.`t2`.`key1b` < 10) and (`test`.`t2`.`key1b` > 2)) or ((`test`.`t2`.`key1a` = 4) and (`test`.`t2`.`key1b` < 7) and (`test`.`t2`.`key1b` > 3)))" + } + ] /* attached_conditions_summary */ + } /* attaching_conditions_to_tables */ + }, + { + "refine_plan": [ + { + "database": "test", + "table": "t2", + "scan_type": "table" + } + ] /* refine_plan */ + } + ] /* steps */ + } /* join_optimization */ + }, + { + "join_execution": { + "select#": 1, + "steps": [ + ] /* steps */ + } /* join_execution */ + } + ] /* steps */ +} 0 + EXPLAIN SELECT * FROM t1 WHERE (key1 > 1 OR key2 > 2); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL i1,i2 NULL NULL NULL 1024 Using where === modified file 'sql/opt_range.cc' --- a/sql/opt_range.cc 2011-02-16 15:06:06 +0000 +++ b/sql/opt_range.cc 2011-03-15 13:31:03 +0000 @@ -2018,13 +2018,17 @@ void TRP_RANGE::trace_basic_info(const P add_utf8("index", cur_key.name).add("records", records); Opt_trace_array trace_range(param->thd->opt_trace, "ranges"); - for (const SEL_ARG *current= key; - current; - current= current->next) + + const SEL_ARG *current_range= key; + // make current_range point to the first interval + while (current_range->prev) + current_range= current_range->prev; + + while (current_range) { String range_info; range_info.set_charset(system_charset_info); - for (const SEL_ARG *part= current; + for (const SEL_ARG *part= current_range; part; part= part->next_key_part) { @@ -2034,6 +2038,7 @@ void TRP_RANGE::trace_basic_info(const P part->min_flag | part->max_flag); } trace_range.add_utf8(range_info.ptr(), range_info.length()); + current_range= current_range->next; } #endif } --===============3202706166791089546== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/jorgen.loland@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: jorgen.loland@stripped\ # ldnelxkial1qrfn4 # target_branch: file:///export/home/jl208045/mysql/wl4800/mysql-next-\ # mr-opt-backporting-wl4800/ # testament_sha1: 93d733e823f0c06b3995c18c574b078dd8e2797e # timestamp: 2011-03-15 14:31:08 +0100 # source_branch: file:///export/home/jl208045/mysql/wl4800/mysql-next-\ # mr-opt-backporting-wl4800/ # base_revision_id: guilhem.bichot@stripped\ # 2m2iiabbmo3bb576 # # Begin bundle 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 --===============3202706166791089546==--