Оптимизация WordPress SQL-запроса для списка старых постов - PullRequest
2 голосов
/ 21 февраля 2010

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

SELECT SQL_CALC_FOUND_ROWS wp_posts.*
FROM wp_posts
WHERE 1=1
  AND wp_posts.post_type = 'post'
  AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
ORDER BY wp_posts.post_date DESC
LIMIT 846, 47

В таблице около 160 тыс. Строк. Вот упрощенная версия схемы:

CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL auto_increment,
  `post_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_status` varchar(20) NOT NULL default 'publish',
  `post_type` varchar(20) NOT NULL default 'post',
  PRIMARY KEY  (`ID`),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Это EXPLAIN результат запроса:

id  select_type table   type    possible_keys   key key_len ref rows    Extra   
1   SIMPLE  wp_posts    ref type_status_date        type_status_date        62  const   41519   Using where; Using filesort

В идеале я бы хотел избавиться от сортировки файлов. Любые советы?

Ответы [ 5 ]

1 голос
/ 22 февраля 2010

Вы должны создать индекс для столбца заказа (post_date), без индекса все 160 тыс. Строк будут извлечены, отсортированы и затем большинство из них отброшены.

Возможно, вы захотите посмотреть на более агрессивное кэширование, сохраняя окна результатов в memcache или аналогичном механизме кэширования.

Дополнительные советы по оптимизации разбивки на страницы в http://www.mysqlperformanceblog.com/2008/09/24/four-ways-to-optimize-paginated-displays/

1 голос
/ 21 февраля 2010

Убедитесь, что у вас есть индекс для post_type, post_status и post_date.

160 тыс. Строк не должно быть проблемой.

0 голосов
/ 21 февраля 2010

Посмотрите на http://www.slideshare.net/Eweaver/efficient-pagination-using-mysql. Рекомендации там в основном сводятся к

  • Иметь подходящий индекс, который можно использовать как в порядке где , так и по предложению.
  • Избегайте использования COUNT() (или его двоюродного брата SQL_CALC_FOUND ROWS) для отображения строки (слайды перечисляют пару изменений пользовательского интерфейса или агрегирование в отдельном поле, если это необходимо для достижения этого).
  • Не используйте LIMIT M, N используйте LIMIT N (способ достижения этого довольно умный: если, например, у вас есть сообщения, отсортированные по первичному ключу DESC, то вы можете получить следующее добавьте первичный ключ * (1020 * меньше, чем последний элемент вашей текущей страницы).

РЕДАКТИРОВАТЬ: Первый пункт рассматривается в ответе Питера Ланга, но, пожалуйста, обратите внимание, что если пейджер позволяет сортировать по другим столбцам, то индекс может быть недостаточным.

0 голосов
/ 21 февраля 2010

При использовании OR убедитесь, что индексы используются с обеих сторон.

SELECT SQL_CALC_FOUND_ROWS wp_posts.* # change this to select only columns you need
FROM wp_posts 
WHERE (wp_posts.post_type = 'post' AND wp_posts.post_status = 'publish') or (wp_posts.post_type = 'post' OR wp_posts.post_status = 'private') 
ORDER BY wp_posts.post_date DESC LIMIT 846, 47

Я бы также сделал перечисления post_status и post_type. Также добавьте отдельный индекс для столбца заказа (post_date), так как в мультииндексах только первый столбец слева может использоваться как отдельный индекс.

0 голосов
/ 21 февраля 2010

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

...