因为,您的数据库引擎是“InnoDB”
,默认情况下,InnoDB 中的所有用户数据都存储在包含 B 树索引的页面中
B-tree are good for following lookups:
● Exact full value (= xxx)
● Range of values (BETWEEN xx AND yy)
● Column prefix (LIKE 'xx%')
● Leftmost prefix
所以,对于你的查询,与其使用索引什么的去优化,不如考虑加快查询速度。
您可以通过创建覆盖索引来加快查询速度。
覆盖索引指的是这种情况all fields selected in a query are covered by an index
,在这种情况下是 InnoDB(不是 MyISAM )will never read the data in the table, but only use the data in the index
,。significantly speeding up the select
请注意,在 InnoDB 中,主键包含在所有二级索引中,因此在某种程度上,所有二级索引都是复合索引。这意味着如果您在 InnoDB 上运行以下查询:
SELECT `moduleName` ,`menuName`
FROM `Modules1`
WHERE 'abc_def' LIKE(CONCAT(`moduleName`,'%'))
MySQL will always use a covering index and will not access the actual table
To believe, go to **Explain**
What does Explain statement mean?
table:
指示输出受到影响的表。
type:
向我们展示正在使用哪种类型的连接。从最好到最差的类型是:system、const、eq_ref、ref、range、index、all
possible_keys:
指示 MySQL 可以选择哪些索引来查找此表中的行
key:
表示 MySQL 实际决定使用的键(索引)。如果 MySQL 决定使用 possible_keys 索引之一来查找行,则该索引被列为键值。
key_len:
这是使用的密钥的长度。越短越好。
ref:
使用哪一列(或常数)
rows:
MySQL 认为它必须检查以执行查询的行数。
extra Extra info:
在这里看到的不好的是“使用临时”和“使用文件排序”
我有 1,990 行。
我的实验:
我会推荐 Isern 的 where 子句解决方案
case 1) no indexes
explain select `moduleName` ,`menuName` FROM `Modules1` WHERE moduleName = SUBSTRING('abc_def', 1, LENGTH(moduleName));
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | Modules | ALL | NULL | NULL | NULL | NULL | 2156 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
创建覆盖索引的方法
case 2) ALTER TABLE `test`.`Modules1` ADD index `mod_name` (`moduleName`)
explain select `moduleName` ,`menuName` FROM `Modules1` WHERE moduleName = SUBSTRING('abc_def', 1, LENGTH(moduleName));
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | Modules | ALL | NULL | NULL | NULL | NULL | 2156 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
在这里,它显示正在使用的索引。见栏目:key、Extra
case 3) ALTER TABLE `test`.`Modules1` DROP INDEX `mod_name` ,
ADD INDEX `mod_name` ( `moduleName` , `menuName` )
explain select `moduleName` ,`menuName` FROM `Modules1` WHERE moduleName = SUBSTRING('abc_def', 1, LENGTH(moduleName));
+----+-------------+----------+-------+---------------+----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+----------+---------+------+------+--------------------------+
| 1 | SIMPLE | Modules | index | NULL | mod_name | 1069 | NULL | 2066 | Using where; Using index |
+----+-------------+----------+-------+---------------+----------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
case 4) ALTER TABLE `test`.`Modules1` DROP INDEX `mod_name` ,
ADD INDEX `mod_name` ( `ID` , `moduleName` , `menuName` )
explain select `moduleName` ,`menuName` FROM `Modules1` WHERE moduleName = SUBSTRING('abc_def', 1, LENGTH(moduleName));
+----+-------------+----------+-------+---------------+----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+----------+---------+------+------+--------------------------+
| 1 | SIMPLE | Modules | index | NULL | mod_name | 1073 | NULL | 2061 | Using where; Using index |
+----+-------------+----------+-------+---------------+----------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
编辑:
use where moduleName regexp "^(a|ab|abc|abc_|abc_d|abc_de|abc_def)$";
in place of substring()