【发布时间】:2021-12-28 03:54:04
【问题描述】:
根据我对 MySQL 文档的理解:
只要比较运算符为
=、<=>或IS NULL,优化器就会尝试使用其他关键部分来确定区间。如果运算符为>、<、>=、<=、!=、<>、BETWEEN或LIKE,则优化器使用它,但不再考虑关键部分。
https://dev.mysql.com/doc/refman/5.6/en/range-optimization.html#range-access-multi-part
我试图优化以下查询:
SELECT col3 FROM tbl2 WHERE col3 = 'fHI' AND col1 > 20 AND col4 > 0.5;
其中tbl2 定义为:
CREATE TABLE `tbl2` (
`col1` int NOT NULL,
`col2` varchar(512) NOT NULL DEFAULT '',
`col3` varchar(512) DEFAULT NULL,
`col4` double DEFAULT NULL,
PRIMARY KEY (`col2`),
KEY `cd1` (`col3`,`col1`,`col4`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
我的印象是使用的列将是col3 和col1,因为col1 上的谓词使用> 运算符。但是,优化器计划说它按照计划使用所有三个索引键列。
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "92.10"
},
"table": {
"table_name": "tbl2",
"access_type": "index",
"possible_keys": [
"cd1"
],
"key": "cd1",
"used_key_parts": [
"col3",
"col1",
"col4"
],
"key_length": "528",
"rows_examined_per_scan": 901,
"rows_produced_per_join": 881,
"filtered": "97.78",
"using_index": true,
"cost_info": {
"read_cost": "4.00",
"eval_cost": "88.10",
"prefix_cost": "92.10",
"data_read_per_join": "901K"
},
"used_columns": [
"col1",
"col3",
"col4"
],
"attached_condition": "((`test`.`tbl2`.`col3` = 'fHI') and (`test`.`tbl2`.`col1` > 20) and (`test`.`tbl2`.`col4` > 0.5))"
}
}
}
是文档错误还是col4 以不同的方式使用?
【问题讨论】:
-
@ysth - 这是 MySQL 8.0
-
这给了你什么?
EXPLAIN FORMAT=JSON SELECT col3, col2 FROM tbl2 WHERE col3 = 'fHI' AND col1 > 20 AND col4 > 0.5;(我添加了col2,因此索引将不再“覆盖”。) -
@RickJames - 它给了我这个:ctxt.io/2/AABgHhIzFg 除了
used_columns有一个额外的col2条目之外,它完全一样 -
@RickJames 那是因为
col2是PK。我在其中添加了另一个整数列col5并改为使用EXPLAIN FORMAT=JSON SELECT col3, col5 FROM tbl2 WHERE col3 = 'fHI' AND col1 > 20 AND col4 > 0.5;。计划恢复为全表扫描。 -
糟糕——这就是我要找的。 (我错过了 col2 是 PK。)无论如何,“覆盖”在大多数情况下对性能是有益的。
标签: mysql indexing database-administration