Reputation: 573
Can somebody tell me why mysql is not using the correct index in the following query
SELECT `Slugs`.`slug` FROM `slugs` AS `Slugs`
WHERE `Slugs`.`country_id` = 1 AND `Slugs`.`expired` = 0
LIMIT 308400,300
I have created a cmposite index for the two columns refered in the where clause
Table Structure for table slugs
CREATE TABLE IF NOT EXISTS `slugs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`slug` varchar(255) NOT NULL,
`post_fields` text NOT NULL,
`slugdata` text NOT NULL,
`updated_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`country_id` int(11) NOT NULL DEFAULT '1',
`expired` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `slug_2` (`slug`,`country_id`),
KEY `updated_date` (`updated_date`),
KEY `country_id` (`country_id`),
KEY `slug` (`slug`),
KEY `expired` (`expired`),
KEY `country_id_2` (`country_id`,`expired`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1612485 ;
Indexes:
Keyname Type Unique Packed Field Cardinality Collation Null Comment
PRIMARY BTREE Yes No id 1406994 A
slug_2 BTREE Yes No slug 1406994 A
country_id 1406994 A
updated_date BTREE No No updated_date 21 A
country_id BTREE No No country_id 21 A
slug BTREE No No slug 1406994 A
expired BTREE No No expired 21 A
country_id_2 BTREE No No country_id 21 A
expired 21 A
Output from Explain
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Slugs ref country_id,expired,country_id_2 country_id 4 const 670284 Using where
Upvotes: 0
Views: 401
Reputation: 48357
What do you mean it's not using the correct index?
The cardinality for both country_id and country_id_2 is very low, and is in fact the same for both indexes - so there's no benefit in using the index based on 2 columns. Which implies that there are very few records with expired<>0.
But then why does the expired index have a cardinality of 21 too?
What's the output from:
SELECT 'expired' AS fld
, COUNT(*) AS distinct_values
, AVG(n) AS rows
FROM
(SELECT expired AS v
, COUNT(*) AS n
FROM slugs
GROUP BY expired) ilv1
UNION
SELECT 'country_id',
, COUNT(*) AS distinct_values
, AVG(n) AS rows
FROM
(SELECT country_id AS v
, COUNT(*) AS n
FROM slugs
GROUP BY country_id) ilv2
SELECT 'expired:country_id',
, COUNT(*) AS distinct_values
, AVG(n) AS rows
FROM
(SELECT CONCAT(expired, country_id) AS v
, COUNT(*) AS n
FROM slugs
GROUP BY CONCAT(expired, country_id)) ilv3;
Upvotes: 1