MySQL « Оптимизация запроса c ORDER BY и множеством условий WHERE
Помогите, пожалуйста разобраться, как правильно составить запрос.
Есть таблица
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .mysql.geshi_code {font-family:monospace;} .mysql.geshi_code .imp {font-weight: bold; color: red;} .mysql.geshi_code .kw1 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw2 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw3 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw4 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw5 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw6 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw7 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw8 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw9 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw10 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw11 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw12 {color: #009900;} .mysql.geshi_code .kw13 {color: #000099;} .mysql.geshi_code .kw14 {color: #000099;} .mysql.geshi_code .kw15 {color: #000099;} .mysql.geshi_code .kw16 {color: #000099;} .mysql.geshi_code .kw17 {color: #000099;} .mysql.geshi_code .kw18 {color: #000099;} .mysql.geshi_code .kw19 {color: #000099;} .mysql.geshi_code .kw20 {color: #000099;} .mysql.geshi_code .kw21 {color: #000099;} .mysql.geshi_code .kw22 {color: #000099;} .mysql.geshi_code .kw23 {color: #000099;} .mysql.geshi_code .kw24 {color: #000099;} .mysql.geshi_code .kw25 {color: #000099;} .mysql.geshi_code .kw26 {color: #000099;} .mysql.geshi_code .kw27 {color: #00CC00;} .mysql.geshi_code .coMULTI {color: #808000; font-style: italic;} .mysql.geshi_code .co1 {color: #808080; font-style: italic;} .mysql.geshi_code .co2 {color: #808080; font-style: italic;} .mysql.geshi_code .es0 {color: #004000; font-weight: bold;} .mysql.geshi_code .es1 {color: #008080; font-weight: bold;} .mysql.geshi_code .br0 {color: #FF00FF;} .mysql.geshi_code .sy1 {color: #CC0099;} .mysql.geshi_code .sy2 {color: #000033;} .mysql.geshi_code .st0 {color: #008000;} .mysql.geshi_code .nu0 {color: #008080;} .mysql.geshi_code span.xtra { display:block; }
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fld1` mediumint(8) unsigned NOT NULL,
`fld2` int(10) unsigned NOT NULL,
`fld3` int(10) unsigned NOT NULL,
`price` mediumint(8) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `item` (`fld1`,`fld2`,`fld3`,`price`),
KEY `price` (`price`)
)
Запрос следующего вида:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .mysql.geshi_code {font-family:monospace;} .mysql.geshi_code .imp {font-weight: bold; color: red;} .mysql.geshi_code .kw1 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw2 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw3 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw4 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw5 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw6 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw7 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw8 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw9 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw10 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw11 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw12 {color: #009900;} .mysql.geshi_code .kw13 {color: #000099;} .mysql.geshi_code .kw14 {color: #000099;} .mysql.geshi_code .kw15 {color: #000099;} .mysql.geshi_code .kw16 {color: #000099;} .mysql.geshi_code .kw17 {color: #000099;} .mysql.geshi_code .kw18 {color: #000099;} .mysql.geshi_code .kw19 {color: #000099;} .mysql.geshi_code .kw20 {color: #000099;} .mysql.geshi_code .kw21 {color: #000099;} .mysql.geshi_code .kw22 {color: #000099;} .mysql.geshi_code .kw23 {color: #000099;} .mysql.geshi_code .kw24 {color: #000099;} .mysql.geshi_code .kw25 {color: #000099;} .mysql.geshi_code .kw26 {color: #000099;} .mysql.geshi_code .kw27 {color: #00CC00;} .mysql.geshi_code .coMULTI {color: #808000; font-style: italic;} .mysql.geshi_code .co1 {color: #808080; font-style: italic;} .mysql.geshi_code .co2 {color: #808080; font-style: italic;} .mysql.geshi_code .es0 {color: #004000; font-weight: bold;} .mysql.geshi_code .es1 {color: #008080; font-weight: bold;} .mysql.geshi_code .br0 {color: #FF00FF;} .mysql.geshi_code .sy1 {color: #CC0099;} .mysql.geshi_code .sy2 {color: #000033;} .mysql.geshi_code .st0 {color: #008000;} .mysql.geshi_code .nu0 {color: #008080;} .mysql.geshi_code span.xtra { display:block; }
WHERE `fld1` IN (445,667,334,....) AND `fld2` IN (455,66778,....) AND `fld3` > 100 AND `fld3` < 5000
ORDER BY `price` LIMIT 100
EXPLAIN:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .mysql.geshi_code {font-family:monospace;} .mysql.geshi_code .imp {font-weight: bold; color: red;} .mysql.geshi_code .kw1 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw2 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw3 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw4 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw5 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw6 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw7 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw8 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw9 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw10 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw11 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw12 {color: #009900;} .mysql.geshi_code .kw13 {color: #000099;} .mysql.geshi_code .kw14 {color: #000099;} .mysql.geshi_code .kw15 {color: #000099;} .mysql.geshi_code .kw16 {color: #000099;} .mysql.geshi_code .kw17 {color: #000099;} .mysql.geshi_code .kw18 {color: #000099;} .mysql.geshi_code .kw19 {color: #000099;} .mysql.geshi_code .kw20 {color: #000099;} .mysql.geshi_code .kw21 {color: #000099;} .mysql.geshi_code .kw22 {color: #000099;} .mysql.geshi_code .kw23 {color: #000099;} .mysql.geshi_code .kw24 {color: #000099;} .mysql.geshi_code .kw25 {color: #000099;} .mysql.geshi_code .kw26 {color: #000099;} .mysql.geshi_code .kw27 {color: #00CC00;} .mysql.geshi_code .coMULTI {color: #808000; font-style: italic;} .mysql.geshi_code .co1 {color: #808080; font-style: italic;} .mysql.geshi_code .co2 {color: #808080; font-style: italic;} .mysql.geshi_code .es0 {color: #004000; font-weight: bold;} .mysql.geshi_code .es1 {color: #008080; font-weight: bold;} .mysql.geshi_code .br0 {color: #FF00FF;} .mysql.geshi_code .sy1 {color: #CC0099;} .mysql.geshi_code .sy2 {color: #000033;} .mysql.geshi_code .st0 {color: #008000;} .mysql.geshi_code .nu0 {color: #008080;} .mysql.geshi_code span.xtra { display:block; }
Сочетание ORDER BY с LIMIT заставляет mysql использовать индекс `price` для ORDER BY и не использовать для WHERE!
Это хорошо, если условия в WHERE не очень строгие(много строк подходит под запрос), то поиск происходит очень быстро, но стоит указать более строгие условия, когда подходящих строк не много, или подходящие строки находятся в конце таблицы, запрос выполняется очень долго, так как чтобы найти нужные записи приходится сортировать почти всю таблицу в 1млн. записей
Вопрос: как заставить mysql использовать индексы и для WHERE и для ORDER BY?
Заранее спасибо всем за потраченное время!
1 ответов
Чтобы order by работал через индекс совместно с where индекс долден быть составным key1, key2, ... keyN, keyOrder
где key1- keyn ключи на where а keyOrder - сортировка. Именно в таком порядке. Ну и конечно никаких OR в where.
WHERE `fld1` IN (445,667,334,....) AND `fld2` IN (455,66778,....) AND `fld3` > 100 AND `fld3` < 5000
ORDER BY `price` LIMIT 100
Вы создаете индекс, который включает почти все поля (кроме ПК) - KEY `item` (`fld1`,`fld2`,`fld3`,`price`)). Эффективность такого индекса практически равна 0 - что перебирать индекс, что данные - примерно одна и та же нагрузка для сервера (хотя нет, затраты по поддержке индекса будут выше - его надо сортировать при любых изменениях данных). В запросе Вы выбираете все поля (что вообще-то не считается хорошим тоном) - т.е. скорей всего full scan будет оптимальным планом (при использовании индекса сервер должен еще будет сделать lookup к ПК). Вы используете IN - что в принципе есть эквивалентом к множеству OR, и если selectivity индекса небольшое, то индекс использоваться не будет