mariadb/mysql-test/main/opt_trace_index_merge_innodb.result
Monty 515b9ad05a Added EQ_REF chaining to the greedy_optimizer
MDEV-28073 Slow query performance in MariaDB when using many table

The idea is to prefer and chain EQ_REF tables (tables that uses an
unique key to find a row) when searching for the best table combination.
This significantly reduces row combinations that has to be examined.
This is optimization is enabled when setting optimizer_prune_level=2
(which is now default).

Implementation:
- optimizer_prune_level has a new level, 2, which enables EQ_REF
  optimization in addition to the pruning done by level 1.
  Level 2 is now default.
- Added JOIN::eq_ref_tables that contains bits of tables that could use
  potentially use EQ_REF access in the query.  This is calculated
  in sort_and_filter_keyuse()

Under optimizer_prune_level=2:
- When the greedy_optimizer notices that the preceding table was an
  EQ_REF table, it tries to add an EQ_REF table next. If an EQ_REF
  table exists, only this one will be considered at this level.
  We also collect all EQ_REF tables chained by the next levels and these
  are ignored on the starting level as we have already examined these.
  If no EQ_REF table exists, we continue as normal.

This optimization speeds up the greedy_optimizer combination test with
~25%

Other things:
- I ported the changes in MySQL 5.7 to greedy_optimizer.test to MariaDB
  to be able to ensure we can handle all cases that MySQL can do.
- I have run all tests with --mysqld=--optimizer_prune_level=1 to verify that
  there where no test changes.
2022-07-26 22:27:29 +07:00

287 lines
9.3 KiB
Text

set @innodb_stats_persistent_save= @@innodb_stats_persistent;
set @innodb_stats_persistent_sample_pages_save=
@@innodb_stats_persistent_sample_pages;
set global innodb_stats_persistent= 1;
set global innodb_stats_persistent_sample_pages=100;
create table t1
(
pk1 int not null,
pk2 int not null,
key1 int not null,
key2 int not null,
key (key1),
key (key2),
primary key (pk1, pk2)
)engine=Innodb;
analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
set optimizer_trace="enabled=on";
set @tmp_index_merge_ror_cpk=@@optimizer_switch;
set optimizer_switch='extended_keys=off';
explain select * from t1 where pk1 != 0 and key1 = 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref PRIMARY,key1 key1 4 const 1 Using index condition
select * from information_schema.OPTIMIZER_TRACE;
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain select * from t1 where pk1 != 0 and key1 = 1 {
"steps": [
{
"join_preparation": {
"select_id": 1,
"steps": [
{
"expanded_query": "select t1.pk1 AS pk1,t1.pk2 AS pk2,t1.key1 AS key1,t1.key2 AS key2 from t1 where t1.pk1 <> 0 and t1.key1 = 1"
}
]
}
},
{
"join_optimization": {
"select_id": 1,
"steps": [
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "t1.pk1 <> 0 and t1.key1 = 1",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)"
},
{
"transformation": "constant_propagation",
"resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)"
}
]
}
},
{
"table_dependencies": [
{
"table": "t1",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": []
}
]
},
{
"ref_optimizer_key_uses": [
{
"table": "t1",
"index": "key1",
"field": "key1",
"equals": "1",
"null_rejecting": false
}
]
},
{
"rows_estimation": [
{
"table": "t1",
"range_analysis": {
"table_scan": {
"rows": 1000,
"cost": 206
},
"potential_range_indexes": [
{
"index": "PRIMARY",
"usable": true,
"key_parts": ["pk1", "pk2"]
},
{
"index": "key1",
"usable": true,
"key_parts": ["key1"]
},
{
"index": "key2",
"usable": false,
"cause": "not applicable"
}
],
"setup_range_conditions": [],
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "PRIMARY",
"ranges": ["(pk1) < (0)", "(0) < (pk1)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 1000,
"cost": 204.27,
"chosen": true
},
{
"index": "key1",
"ranges": ["(1) <= (key1) <= (1)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 1,
"cost": 1.345146475,
"chosen": true
}
],
"analyzing_roworder_intersect": {
"intersecting_indexes": [
{
"index": "key1",
"index_scan_cost": 1.000146475,
"cumulated_index_scan_cost": 1.000146475,
"disk_sweep_cost": 1.004153686,
"cumulative_total_cost": 2.004300162,
"usable": true,
"matching_rows_now": 1,
"intersect_covering_with_this_index": false,
"chosen": true
}
],
"clustered_pk": {
"clustered_pk_added_to_intersect": false,
"cause": "cost"
},
"chosen": false,
"cause": "cost"
},
"analyzing_index_merge_union": []
},
"group_index_range": {
"chosen": false,
"cause": "no group by or distinct"
},
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "key1",
"rows": 1,
"ranges": ["(1) <= (key1) <= (1)"]
},
"rows_for_plan": 1,
"cost_for_plan": 1.345146475,
"chosen": true
}
}
},
{
"table": "t1",
"rowid_filters": [
{
"key": "key1",
"build_cost": 0.130146475,
"rows": 1
}
]
},
{
"selectivity_for_indexes": [
{
"index_name": "key1",
"selectivity_from_index": 0.001
},
{
"index_name": "PRIMARY",
"selectivity_from_index": 1
}
],
"selectivity_for_columns": [],
"cond_selectivity": 0.001
}
]
},
{
"considered_execution_plans": [
{
"plan_prefix": [],
"get_costs_for_tables": [
{
"best_access_path": {
"table": "t1",
"considered_access_paths": [
{
"access_type": "ref",
"index": "key1",
"used_range_estimates": true,
"rows": 1,
"cost": 1.125146475,
"chosen": true
},
{
"type": "scan",
"chosen": false,
"cause": "cost"
}
],
"chosen_access_method": {
"type": "ref",
"records": 1,
"cost": 1.125146475,
"uses_join_buffering": false
}
}
}
]
},
{
"plan_prefix": [],
"table": "t1",
"rows_for_plan": 1,
"cost_for_plan": 1.325146475
}
]
},
{
"best_join_order": ["t1"]
},
{
"substitute_best_equal": {
"condition": "WHERE",
"resulting_condition": "t1.key1 = 1 and t1.pk1 <> 0"
}
},
{
"attaching_conditions_to_tables": {
"attached_conditions_computation": [],
"attached_conditions_summary": [
{
"table": "t1",
"attached": "t1.pk1 <> 0"
}
]
}
}
]
}
},
{
"join_execution": {
"select_id": 1,
"steps": []
}
}
]
} 0 0
drop table t1;
set @@optimizer_switch= @tmp_index_merge_ror_cpk;
set global innodb_stats_persistent= @innodb_stats_persistent_save;
set global innodb_stats_persistent_sample_pages=
@innodb_stats_persistent_sample_pages_save;
#
# MDEV-18962: ASAN heap-buffer-overflow in Single_line_formatting_helper::on_add_str with optimizer trace
#
CREATE TABLE t1 (a date not null, b time, key(a), key(b)) ENGINE=InnoDB;
INSERT INTO t1 VALUES ('1991-09-09','00:00:00'),('2032-08-24','02:22:24');
SET SESSION optimizer_trace = 'enabled=on';
SELECT * FROM t1 WHERE b IS NULL AND a = '2000-01-01';
a b
DROP TABLE t1;
set optimizer_trace="enabled=off";