Dal momento che, il motore dtabase è "InnoDB" Tutti i dati degli utenti per impostazione predefinita in InnoDB viene memorizzato in pagine che compongono un indice B-tree
B-tree are good for following lookups:
● Exact full value (= xxx)
● Range of values (BETWEEN xx AND yy)
● Column prefix (LIKE 'xx%')
● Leftmost prefix
Così, per la tua ricerca, piuttosto che utilizzare indice o qualcosa da ottimizzare, , possiamo pensare a velocizzando la query.
È possibile velocizzare la query creando indice di copertura.
Un indice di copertura si riferisce al caso in cui all fields selected in a query are covered by an index
, in tal caso InnoDB (non MyISAM) will never read the data in the table, but only use the data in the index
, significantly speeding up the select
. Si noti che in InnoDB la chiave primaria è inclusa in tutti gli indici secondari, quindi in un certo senso tutti gli indici secondari sono indici composti. Questo significa che se si esegue la seguente query su 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:
Indica quale tabella l'uscita è interessato.
type:
Mostra il tipo di join utilizzato. Dal migliore al peggiore i tipi sono: il sistema, const, eq_ref, ref, gamma, indice, tutto
possible_keys:
Indica che gli indici MySQL può scegliere per trovare le righe in questa tabella
key:
Indica la chiave (indice) che MySQL ha effettivamente deciso di utilizzare. Se MySQL decide di utilizzare uno degli indici possible_keys per cercare le righe, tale indice viene elencato come valore chiave.
key_len:
È la lunghezza della chiave utilizzata. Più corto è, meglio è.
ref:
quale colonna (o costante) viene utilizzato
rows:
Il numero di righe MySQL ritiene esso deve verificare per eseguire la query.
extra Extra info:
i cattivi da vedere qui sono "utilizzando temporaneo" e "utilizzando FileSort"
ho avuto 1.990 righe.
miei esperimenti:
mi sento di raccomandare la soluzione di Isern per cui la clausola
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)
modi di creare che coprono indici
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 |
+----+-------------+----------+------+---------------+------+---------+------+------+-------------+
Qui, mostra l'indice utilizzato. Vedere le colonne: chiave, 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()
È possibile creare indice di copertura e si può vedere la tabella utilizza l'indice automaticamente . –