I'm trying to optimize this query.
SELECT * FROM sales_reps
WHERE account_id = 1
AND (state = 'enabled')
AND (clients >= 5 OR revenue >= 10000)
ORDER BY name, platform, client_group, from_date
All the field in the ORDER BY
clause are string except from_date
which is a date. (account_id, name, platform, client_group, from_date)
is a unique key combination.
I tried creating indexes with combination or those fields but when I do explain it doesn't seem to be using it. The table would have about 2 million rows for each account.
Any thoughts on how I could go about optimizing it?
Update 1: Here is the explain and result:
EXPLAIN SELECT *
FROM `sales_reps`
WHERE `sales_reps`.`account_id` = 1
AND state = 'enabled'
AND (clients >= 1 OR revenue >= 100)
ORDER BY name,platform,client_group,from_date
Here is the result
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE sales_reps ALL account_id_4,account_id NULL NULL NULL 33215 Using where; Using filesort
account_id_4
is the index with the following keys account_id, state(10), name, platform, ad_group, from_date, clicks, impressions
Update 2: Here is the full table structure:
CREATE TABLE `sales_reps` (
`account_id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`platform` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`client_group` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
`state` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`status` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`max_cpc` decimal(8,2) NOT NULL DEFAULT '0.00',
`match_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`first_page_cpc` decimal(8,2) DEFAULT '0.00',
`top_page_cpc` decimal(8,2) DEFAULT '0.00',
`quality_score` decimal(8,2) DEFAULT '0.00',
`revenue` int(11) DEFAULT NULL,
`clients` int(11) DEFAULT NULL,
`conversions` int(11) DEFAULT NULL,
`cost` decimal(8,2) DEFAULT '0.00',
`average_position` decimal(8,2) DEFAULT '0.00',
`campaign` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`phone_view` int(11) DEFAULT '0',
`website_view` int(11) DEFAULT '0',
`request_submit` int(11) DEFAULT '0',
UNIQUE KEY `account_id_4` (`account_id`,`state`(10),`name`,`platform`,`client_group`,`from_date`,`clients`,`revenue`),
KEY `account_id` (`account_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Best Answer
I have a few suggestions that may help
SUGGESTION #1 : Use index with different column order
Note that
state
andaccount_id
are reversed. That way, there is no need to traverse all rows for a given account_id that would separate enabled from disabled. Only enabled entries for account_id are read.SUGGESTION #2 : Refactor the Query
Instead of
Try this experiment
First run this query
then run this query
If the performance of those two queries are fast, then JOIN them as subqueries and see
Give it a Try !!!