Since, your dtabase engine is "InnoDB"
All user data by default in InnoDB is stored in pages comprising a B-tree index
B-tree are good for following lookups:
● Exact full value (= xxx)
● Range of values (BETWEEN xx AND yy)
● Column prefix (LIKE 'xx%')
● Leftmost prefix
So, for your query, rather than using index or something to optimize,
we can think of speeding up the query.
You can speed up the query by creating covering index .
A covering index refers to the case when all fields selected in a query are covered by an index
, in that case InnoDB (not MyISAM) will never read the data in the table, but only use the data in the index
, significantly speeding up the select
.
Note that in InnoDB the primary key is included in all secondary indexes, so in a way all secondary indexes are compound indexes.
This means that if you run the following query on 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:
Indicates which table the output is affected.
type:
Shows us which type of join is being used. From best to worst
the types are: system, const, eq_ref, ref, range, index, all
possible_keys:
Indicates which indices MySQL can choose from to find the rows in this table
key:
Indicates the key (index) that MySQL actually decided to use. If MySQL decides to use one of the possible_keys indexes to look up rows, that index is listed as the key value.
key_len:
It's the length of the key used. The shorter the better.
ref:
Which column (or constant) is used
rows:
The number of rows MySQL believes it must examine to execute the query.
extra Extra info:
the bad ones to see here are "using temporary" and "using filesort"
I had 1,990 rows.
My Experiments:
I would recommend Isern's solution for where clause
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)
Ways of creating covering indexes
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 |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
Here, it shows index being used. See the columns: 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)
edit:
use where moduleName regexp "^(a|ab|abc|abc_|abc_d|abc_de|abc_def)$";
in place of substring()