Need yours help optimizing one mysql query. Lets take simple table for example.
CREATE TABLE `Modules` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`moduleName` varchar(100) NOT NULL,
`menuName` varchar(255) NOT NULL,
PRIMARY KEY (`ID`),
KEY `moduleName` (`moduleName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Lets Fill it with some data:
INSERT INTO `Modules` (`moduleName` ,`menuName`)
VALUES
('abc1', 'name1'),
('abc', 'name2'),
('ddf', 'name3'),
('ccc', 'name4'),
('fer', 'name5');
And some sample string. Let it be abc_def
;
Traditionally we are trying to find all the rows containing search string.
On the contrary, my task is, to find all rows which contains moduleName
in input string. For now I have following query to get desired result:
SELECT `moduleName` ,`menuName`
FROM `Modules`
WHERE 'abc_def' LIKE(CONCAT(`moduleName`,'%'))
This will return
moduleName | menuName
---------------------------
abc | name2
The problem is, that this query is not using index.
Is there some way to force it to use one?
One of the first things you can do to optimize your queries is to focus on indexing. Indexes are used to help operations find data more quickly in tables stored in the database. You can help your index be more efficient by indexing all your predicates by WHERE, JOIN, ORDER BY, and GROUP BY clauses.
Try these five tips to boost the speed of your database: Make sure all of your tables have primary keysRunning a table without a primary key is like running a four-cylinder engine with only two active pistons. Open every table in Design view and make sure each has a primary key.
You seem to misunderstand what is index and how it can help to speed up a query.
Let's look at what is your moduleName
index. It is basically a sorted list of mappings from moduleName to ID. And what you are selecting?
SELECT moduleName, menuName
FROM Modules
WHERE 'abc_def' LIKE CONCAT(moduleName,'%');
That is you want some two fields for each row that has some relation to a somehow mapped value of moduleName field. How can ever index help you? There is no exact match, and there is no way to take advantage from the fact that we have moduleNames sorted.
What you need to take advantage from the index, is to have a check for exact match in the condition:
SELECT moduleName, menuName
FROM Modules
WHERE moduleName = LEFT('abc_def', LENGTH(moduleName));
Now we do have an exact match, but since the right part of the condition depends on the moduleName as well, this condition will be checked for each row. Since in his case MySQL can not predict how many rows will match, but it can predict that it will need randon disk access to fetch menuNames for each matching row, MySQL will not use the index.
So you have basically two approaches:
(moduleName, menuName)
, then all results for query will be fetched from the index directly (that is from memory).Approach #2 (see SQLfiddle) will get you an index hit with a simple query, and should offer much better performances on a larger table. On small tables, I (i.e., lserni - see comment) don't think it's worth the effort.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With