MySQLOnRocksDB/mysql-5.6
forked from facebook/mysql-5.6

Loading…
Inefficient optimizer plan #82
so, if the optimizer chose PK, there would be three components
link_type=1, id1=1, id2 in (1,2)
while for id1_type there are two:
id1=1, link_type=1
If one forces the use of PK:
MySQL [test]> explain select id1, id2, link_type, visibility, data, time, version from linktable force index(PRIMARY) where id1 = 1 and link_type = 1 and id2 in (1, 2);
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | linktable | range | PRIMARY | PRIMARY | 24 | NULL | 2 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
Then all three conditions are used to construct range access (note key_len=24). ICP would not have helped here.
EXPLAIN also shows Index Condition Pushdown is not used. This is because MyRocks doesn't support ICP on the primary key. Doing index scan on PK translates into rocksdb::DB->Get(lookup_tuple) calls. The calls retrieve both PK values and the record, there is no point where MyRocks could check ICP and decide not to read the record.
So, I think that ICP in MyRocks has nothing to do with this bug.
Still, using index id1_type instead of PRIMARY looks like a non-optimal choice. Two possible sources of problem:
ha_rocksdb::records_in_range() calls for PRIMARY and id1_type produce poor estimates that cause wrong index choice.
records_in_range() estimates are adequate, but then the optimizer calls handler->index_only_read_time() and handler->read_time() for PK and id1_type, and the returned costs are such that the wrong index is used.
@yoshinorim , can you post an optimizer trace for the EXPLAIN of the query?
Right, I was wrong... this is nothing to do with ICP:)
Optimizer statistics was as follows.
"rows_estimation": [
{
"table": "`linktable`",
"range_analysis": {
"table_scan": {
"rows": 1000,
"cost": 262.1
},
"potential_range_indices": [
{
"index": "PRIMARY",
"usable": true,
"key_parts": [
"link_type",
"id1",
"id2"
]
},
{
"index": "id1_type",
"usable": true,
"key_parts": [
"id1",
"link_type",
"visibility",
"time",
"version",
"data",
"id2"
]
}
],
"best_covering_index_scan": {
"index": "id1_type",
"cost": 1200,
"chosen": false,
"cause": "cost"
},
"setup_range_conditions": [
],
"group_index_range": {
"chosen": false,
"cause": "not_group_by_or_distinct"
},
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "PRIMARY",
"ranges": [
"1 <= link_type <= 1 AND 1 <= id1 <= 1 AND 1 <= id2 <= 1",
"1 <= link_type <= 1 AND 1 <= id1 <= 1 AND 2 <= id2 <= 2"
],
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 2,
"cost": 1.51,
"chosen": true
},
{
"index": "id1_type",
"ranges": [
"1 <= id1 <= 1 AND 1 <= link_type <= 1"
],
"index_dives_for_eq_ranges": true,
"rowid_ordered": false,
"using_mrr": false,
"index_only": true,
"rows": 1,
"cost": 1.26,
"chosen": true
}
],
"analyzing_roworder_intersect": {
"usable": false,
"cause": "too_few_roworder_scans"
}
},
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "id1_type",
"rows": 1,
"ranges": [
"1 <= id1 <= 1 AND 1 <= link_type <= 1"
]
},
"rows_for_plan": 1,
"cost_for_plan": 1.26,
"chosen": true
}
}
}
]
},
{
"considered_execution_plans": [
{
"plan_prefix": [
],
"table": "`linktable`",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "ref",
"index": "PRIMARY",
"rows": 2,
"cost": 2.4,
"chosen": true
},
{
"access_type": "ref",
"index": "id1_type",
"rows": 1,
"cost": 1.2,
"chosen": true
},
{
"access_type": "range",
"cause": "heuristic_index_cheaper",
"chosen": false
}
]
},
"cost_for_plan": 1.2,
"rows_for_plan": 1,
"chosen": true
}
]
},
How to repeat:
then
PRIMARY key should be used here. If id1_type is used, "id2 in (1,2)" can't be used to filter rows by the index.