2017-02-19 13 views
0

У меня есть следующий запрос, который всегда делает весь сайт вниз becuase он «ждет блокировки уровня таблицы»:производительность Mysql: Большой запрос, который всегда застрял/медленно

/*IPS\Patterns\_ActiveRecordIterator::count:246*/ SELECT SQL_CALC_FOUND_ROWS forums_posts . * , forums_topics . * 
FROM `forums_posts` 
LEFT JOIN `forums_topics` ON forums_posts.topic_id = forums_topics.tid 
LEFT JOIN `core_permission_index` ON core_permission_index.app = 'forums' 
AND core_permission_index.perm_type = 'forum' 
AND core_permission_index.perm_type_id = forums_topics.forum_id 
LEFT JOIN `forums_forums` ON forums_topics.forum_id = forums_forums.id 
WHERE (
NULLIF(forums_topics.moved_to, '') IS NULL 
) 
AND (
forums_forums.password IS NULL 
OR (
(
FIND_IN_SET(2, forums_forums.password_override) 
) 
) 
) 
AND (
forums_forums.can_view_others =1 
OR forums_topics.starter_id IS NULL 
) 
AND forums_forums.min_posts_view <=0 
AND queued =0 
AND forums_topics.approved =1 
AND (
(
(
FIND_IN_SET(2, perm_2) 
) 
) 
OR perm_2 = '*' 
) 
ORDER BY post_date DESC 
LIMIT 185725 , 25 

есть все, что я могу сделать для улучшения производительности этого запроса вместо того, чтобы убить процесс/подождать 10 минут, пока он не будет завершен?

+0

Thats из-за [SQL_CALC_FOUND_ROWS] (http://stackoverflow.com/questions/186588/which-is-fastest-select-sql-calc-found-rows-from-table-or-select-count) – Fal

ответ

0

Если это «искатель», который использует ваш веб-сайт, вам действительно нужно избавиться от этого использования OFFSET. Или получите некоторые фильтры, чтобы предотвратить то, что фактически является атакой DOS (отказ в обслуживании). По крайней мере, скажите поисковым роботам, чтобы избежать вашего сайта. (Это может быть простой ответ.)

Давайте вернемся. LIMIT 185725 , 25 - Это номер страницы 7429. Вы действительно прошли через многие страницы?

У вас есть так много строк, но у вас нет удобного способа «поиска» или «консолидации» данных?

Другие вопросы:

OR является дорогостоящим - это препятствует индексу использования

LEFT JOIN часто требует поиска в «правой» таблицы, но быть счастливым, когда ничего нет. Это может иметь худшую производительность, чем обычный JOIN. (Однако, возможно, это требует бизнес-логика.)

Из-за сложности запроса SQL_CALC_FOUND_ROWS, вероятно, займет почти столько же, сколько выборки всех строк без LIMIT. Обратите внимание, как поисковые системы говорили «около 180 000» результатов, а затем даже отбросили это. Возможно, ваше приложение должно поступать аналогичным образом.

Несомненно, существует более простой способ сделать NULLIF(forums_topics.moved_to, '') IS NULL.

Какой двигатель вы используете для таблиц? Если вы используете MyISAM, переключитесь на InnoDB; что, вероятно, избавится от «блокировки на уровне таблицы».

0

Проверьте, что тип таблицы - InnoDB. Если это MyISAM, конвертируйте его в InnoDB. MyISAM не может читать данные в таблице, а другой поток/запрос обновляет любые строки в этой таблице. Он использует блокировки на уровне таблицы.

InnoDB использует MVCC для включения SELECT, пока таблица обновляется с помощью UPDATE/INSERT/DELETE.