Измените его на:
CREATE TABLE `country` (
`id` int(11) NOT NULL auto_increment,
`expiry_date` datetime NOT NULL,
`name` varchar(50) collate utf8_unicode_ci NOT NULL,
`symbol` varchar(5) collate utf8_unicode_ci NOT NULL,
`exchange_rate` decimal(11,5) NOT NULL default '1.00000',
`code` char(3) collate utf8_unicode_ci NOT NULL,
`currency_code` varchar(3) collate utf8_unicode_ci NOT NULL,
`display_order` smallint(6) unsigned NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `code` (`code`),
KEY `currency_code` (`currency_code`),
KEY `expiry` (`expiry_date`,`name`,`display_order`) <<- renamed key for clarity
/* always name compound keys for their left-most parts*/
KEY `name` (`name`) <<-- new key here
KEY `display` (`display_order`) <<--new key here
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
-- the query
SELECT `country`.*
FROM `country`
WHERE `country`.`expiry_date` = 0
ORDER BY `country`.`display_order` ASC, `country`.`name` ASC;
Сложные индексы хитрые
MySQL не использовал индекс для name
в составном индексе, потому что name
был посередине, а MySQL использует только части индекса, если эта часть является самой левой частью составного индекса .
То же самое относится к индексу порядка отображения полей. Составной индекс, в котором есть display_order, использует это поле как крайнюю правую часть и, следовательно, не будет сортировать.
Решение
Сделайте отдельный индекс для поля name
,
и отдельный индекс для поля display_order
.
Иногда MySQL не использует индекс, даже если он доступен. Одно из обстоятельств, при которых это происходит, - это когда оптимизатор оценивает, что использование индекса потребовало бы от MySQL доступа к очень большому проценту строк в таблице. (В этом случае сканирование таблицы, вероятно, будет намного быстрее, поскольку требует меньше запросов.) Однако, если такой запрос использует LIMIT для извлечения только некоторых строк, MySQL в любом случае использует индекс, потому что он может гораздо быстрее найти несколько строк для возврата в результате.
Также, если большой процент строк имеет одинаковое значение для поля (> 40% (IIRC)) , MySQL не будет использовать индекс.
См .: http://dev.mysql.com/doc/refman/5.1/en/mysql-indexes.html
См .: http://dev.mysql.com/doc/refman/5.1/en/index-hints.html
О том, как форсировать индексы согласно предложению FractalizeR.
Убедитесь, что ваш выбор времени после форсирования индекса
В таком простом запросе MySQL вряд ли будет неправильным, а время выбора 0,0013 секунды говорит о том, что в таблице несколько строк.
Индексы не работают так, как вы ожидаете, когда в таблице несколько строк из-за правила процентного соотношения, указанного выше.
Обратите внимание, что в этом случае форсирование индекса не сработало бы, потому что вы не можете заставить MySQL использовать самую правую часть составного индекса. Он просто не может этого сделать.