2013-07-02 3 views
3

Я пытаюсь улучшить производительность забитого Wordpress DB, добавив индексы к запросам, которые появляются в журнале медленных запросов.Как заставить запрос в MySQL использовать индекс?

В MS SQL можно использовать запрос подсказок, чтобы заставить запрос использовать индекс, но это, как правило, довольно легко получить запрос использовать индекс, если вы покрываете столбцы правильно и т.д.

У меня есть этот запрос который появляется в медленном запросе войти намного

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID 
FROM wp_posts 
WHERE 1=1 
    AND wp_posts.post_type = 'post' 
    AND (wp_posts.post_status = 'publish') 
ORDER BY wp_posts.post_date DESC 
    LIMIT 18310, 5; 

Я создал охватывающую уникальный индекс wp_posts на post_date, post_status, post_type and post_id и перезапустить MySQL, однако, когда я бегу объяснить индекс используется

status_password_id 

и возможных ключей мой новый индекс даже не появляется, хотя это индекс покрытия, например, я просто получить

type_status_date,status_password_id 

Поэтому ни использовали индекс или возможные варианты «оптимизатора», если MySQL имеет один даже учитывая мой индекс, который имеет post_date в качестве первого столбца. Я бы подумал, запрос, который в основном делает верхний и упорядочивание по дате с

ORDER BY wp_posts.post_date DESC LIMIT 18310, 5; 

Хочет ли использовать индекс, отсортированный по дате скорости, особенно тот, который имел все другие поля, необходимые для выполнения запроса в это также?

Имеет ли MySQL подсказки для запроса, чтобы использовать индекс для тестов скорости/производительности или есть что-то еще, что мне нужно сделать, чтобы понять, почему этот индекс игнорируется.

Мне очень понравилось бы, если Navicat имел план выполнения Visual Query, такой как MS SQL, но кажется, что EXPLAIN - лучшее, что он может предложить.

Любой, у кого есть какие-либо намеки на то, как я могу заставить индекс использовать или работать, почему его игнорирование будет очень полезно!

Благодаря

+1

вы можете попробовать изменить порядок указателя def wp_posts на 'post_type, post_status, post_date, post_id' –

+0

@IanKenney, вы должны разместить это как ответ. Этот индекс будет использоваться (никаких подсказок не требуется), и запрос будет таким же эффективным, как он может получить (с учетом довольно большого смещения). –

ответ

1

Попробуйте изменить порядок вашего определения индекса к

post_type, post_status, post_date, post_id 

или

post_date desc, post_type, post_status, post_id 
+0

У меня уже есть указатель этого порядка ключей. –

+0

Можете ли вы объяснить мне (если возможно), как я могу видеть в Navicat (или любом другом инструменте) нечто похожее на MS SQL Query Optimiser, поэтому я могу видеть более подробную информацию о том, почему один индекс выбирается над другим. Я бы подумал, что порядок моего индекса был бы более подходящим из-за упорядочения большого количества строк и ограничения по дате. Является ли MySQL очень старыми версиями MS SQL, в которых нет оптимизатора запросов, и вам нужно заказывать свои предложения в порядке большей избирательности? Или есть оптимизатор? –

+0

даже запрос, который не имеет избирательности в столбцах, отличных от даты, например, они просто появляются в select, не использует запрос и вместо этого использует базовый индекс post_date, например, объясняет select id, post_type, post_status из порядка wp_posts по post_date desc limit 20, 5 Я бы подумал, что индекс покрытия с post_date, поскольку первый ключ был бы идеальным для этого, чтобы упорядочить результаты, а затем остальные клавиши удерживают значения для выбора –

9

ли MySQL запрос намеки, чтобы заставить индекс будет использоваться для контроля скорости/или есть что-то еще, что мне нужно сделать, чтобы понять, почему этот индекс игнорируется.

The documentation отвечает на этот вопрос в деталях:

Указав USE INDEX(index_list), вы можете сказать, MySQL использовать только один из названных показателей, чтобы найти строки в таблице. Альтернативный синтаксис IGNORE INDEX(index_list) может использоваться для указания MySQL не использовать какой-либо определенный индекс или индексы.Эти подсказки полезны, если EXPLAIN показывает, что MySQL использует неверный индекс из списка возможных индексов.

Можно также использовать FORCE INDEX, который действует как USE INDEX(index_list) , но с добавлением, что сканирование таблицы считается очень дорогим . Другими словами, сканирование таблицы используется только в том случае, если нет способа использовать один из заданных индексов для поиска строк в таблице .

Для каждого намека требуются имена индексов, а не имена столбцов. имя PRIMARY KEY: PRIMARY. Чтобы увидеть имена индексов для таблицы , используйте SHOW INDEX.

Если USE INDEX не работает, попробуйте использовать IGNORE INDEX, чтобы увидеть, что второй выбор оптимизатора является (или третьего, и так далее).

Простой пример синтаксиса будет:

SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX (i2) WHERE ... 

Есть еще много где, что пришли, в связанных документации. Я привязан к страницам версии 5.0, но вы можете легко перейти к соответствующей версии с помощью левой боковой панели; некоторые дополнительные возможности синтаксиса доступны с версии 5.1.

6

MySQL 5.6 поддерживает новый формат EXPLAIN, который графический интерфейс MySQL Workbench может визуализировать более привлекательным образом. Но это не поможет вам, если вы застряли в MySQL 5.5 или ранее.

У MySQL есть подсказки, поскольку @AirThomas упоминает, но вы действительно должны использовать их экономно. В простом запросе, таком как тот, который вы показываете, никогда не нужно использовать подсказки индекса - если у вас есть нужный индекс. И используя подсказки индекса, вы имеете жестко закодированные имена индексов в своем приложении, поэтому, если вы добавляете или отбрасываете индексы, вам необходимо обновить свой код.

В вашем запросе индекс на (post_date, post_status, post_type, post_id) не поможет.

Вам нужен самый левый столбец в индексе, который будет использоваться для ограничения строки. Поэтому сначала поставьте post_status, post_type. Лучше, если вначале будет более избирательный столбец. То есть, если post_type = 'post' соответствует 3% таблицы, а post_status = 'publish' соответствует 1% от таблицы, то сначала ставьте post_status перед post_type.

Поскольку вы использовали = для обоих условий и для оператора AND, вы знаете, что все соответствующие строки в основном связаны относительно этих двух столбцов. Поэтому, если вы используете post_date в качестве третьего столбца в индексе, тогда оптимизатор знает, что он может извлекать строки в том порядке, в котором они хранятся в индексе, и он может пропустить любую другую работу для ORDER BY. Вы можете увидеть, что это работает, если «Использование filesort» исчезает с вашего EXPLAIN вывода.

Таким образом, ваш индекс, вероятно, должно быть:

ALTER TABLE wp_posts ADD INDEX (post_status, post_type, post_date); 

Вы также можете наслаждаться моей презентации How to Design Indexes, Really.

В этом случае вам не нужно добавлять идентификатор к индексу, потому что индексы InnoDB автоматически содержат столбцы первичного ключа.

LIMIT 18310, 5 обязан быть дорогостоящим. MySQL должен сгенерировать весь набор результатов на стороне сервера, до 18315 строк, только чтобы отбросить большинство из них. Кто в мире должен пропустить страницу 3662 и страницу, во всяком случае ?!

SQL_CALC_FOUND_ROWS является основной причиной смерти производительности при наличии больших наборов результатов, которые вы ЛИСТАНИЕ, потому что MySQL должен генерировать результирующий набор всего как до, так и после того, как страницы, которую вы просили. Лучше всего избавиться от этого модификатора запроса, если вам действительно не нужно FOUND_ROWS(), и даже если вам нужно количество строк, иногда может быть быстрее запускать два запроса, один из которых - SELECT COUNT(*).
(* Проверьте обе стороны, чтобы убедиться.)

Вот еще несколько советов по оптимизации LIMIT:

+1

Я думаю, что (старые?) Установки Wordpress имели MyISAM в качестве двигателя по умолчанию. –

0

Просто, чтобы вы знаю, что я на другом ПК, поэтому мое имя пользователя изменилось, но я написал оригинальный вопрос.

Что я думаю было бы очень полезно, это руководство по конверсии, помогающее людям от MS SQL-фонов скрывать до MySQL, поскольку, похоже, есть какая-то разница в настройке индекса, которую я не понимал, особенно, что разные механизмы хранения автоматически добавляют в первичные ключи , а также как справиться с отсутствием инструментов для настройки производительности.

Я использовал для создания моего основной кластерного индекса, первичный ключа и других уникальных ограничений и индексов, то некластерные индексов с включенными ключами, некоторые покрывающие индексами и т.д.

Я затем запустить синхронизированную работу войти отсутствующий индексный DMV-отчет в таблицу для предотвращения потери данных во время любого перезапуска. Затем я могу запускать отчеты для проверки индексов, которые оптимизатор SQL считает «должен» использоваться, или те, которые он «не использует». Затем я могу использовать эту информацию, счетчики неправильных обращений и потенциальную процентную эффективность, если отсутствующий индекс был использован, в качестве руководства, помогающего точно настроить индексирование производительности.

Насколько я могу судить, у MySQL нет ничего похожего на DMS MsSQL?

Хороший графический план выполнения, встроенный в MS SQL Studio от эонов назад, помогает с настройкой многого, а болотный стандарт MySQL объясняет плохой в сравнении. Я рассмотрю этот инструмент, о котором вы говорили, хотя запуск select @@ версии возвращает 5.0.51a-24 + lenny5-log, поэтому я сомневаюсь, что это мне поможет.

Несколько вещей, хотя в отношении должностей: требовался

  1. Цель состояла в том, чтобы иметь индекс покрытия, так что никаких закладок просмотров (если вы их называете, что в MySQL), и данные может поступать прямо из индекс.

  2. Как почти все мои сообщения опубликованы (99.99%), а post_type - это почти все «пост» (99.99%) с небольшим процентом «страниц». В этих двух столбцах нет избирательности, и они находятся в индексе для обложки. Я отключил авто-черновики, чтобы предотвратить создание изменений и т. Д., А количество черновиков очень мало.

  3. Поэтому я бы подумал, что наличие post_date в качестве первого ключа в индексе было бы более полезным, так как LIMIT (как вы говорите, дорого, и я не контролирую код Wordpress), поэтому, безусловно, ORDER BY и LIMIT (который в основном является TOP) были бы самой дорогостоящей и выборочной частью запроса и более полезными для индекса по сравнению с другими ключами (которые вообще не являются выборочными). Вот почему я положил это первым.

  4. Я использую Wordpress, а таблица wp_posts и его механизм хранения - это MyISAM, который, я считаю, я не могу изменить из-за необходимости полного поиска текста.

  5. Как я сказал кому-то у меня уже есть индекс с порядка post_type, post_status и POST_DATE но EXPLAIN показывает только его возможных ключей, а затем игнорирует его использовать индекс на основе вокруг этих столбцов: post_status , пароль и идентификатор.

  6. Как пароль не используется в запросе и post_status полностью неизбирательного (как и все мои post_types являются «пост») Я урон почему «умный» Оптимизатор в MySQL считает этот показатель должен быть выше выбран либо те, которые были предоставлены ИЛИ мои собственные?

Таким образом, я все еще застрял, поскольку никакое предложение не работает.

Я попытался изменить порядок заказа несколько раз, и хотя у меня всего 20 тыс. Строк, это занимает полчаса или больше каждый раз! Я не знаю, нормально ли это в MySQL или нет, но в MSSQL требуется несколько минут для добавления индексов/индексов в таблицы с миллионами строк.

Так как ничего не сработало до сих пор, я хочу знать (почему?) И, очевидно, о подсказках запроса, чтобы узнать, действительно ли это хорошо.

Я повторно запустил БД после повторной индексации (и даже перезапустил веб-сервер).

Благодарим за помощь.

+0

Извините, но я бы не сказал, что на этот вопрос был дан ответ. Поэтому я не знаю, почему это было отмечено как ответ. Индексы, предлагаемые как решения, не используются. Единственная полезная часть ответов заключалась в том, как добавить подсказки запросов. Не существует объяснения того, почему 2 неселективных ключа должны быть перед самым важным ключом для оператора LIMIT, т.е. post_date или почему используется индекс с паролем и идентификатором и неселективный post_status вместо любых альтернатив предоставлена. – user2334626

+0

Кто-нибудь еще получил ответ о том, почему вместо него используется неселективный индекс? –

Смежные вопросы