Периодически медленный Mysql стол - почему? - PullRequest
3 голосов
/ 10 августа 2009

У нас недавно была проблема, которую я никогда раньше не видел, когда в течение примерно 3 часов одна из наших таблиц Mysql работала очень медленно. Эта таблица содержит сообщения на форуме, и в настоящее время в ней около миллиона строк. Запрос, который стал медленным, был очень распространенным в нашем приложении:

SELECT * FROM `posts` WHERE (`posts`.forum_id = 1)  ORDER BY posts.created_at DESC LIMIT 1;

У нас есть индекс таблицы сообщений (forum_id, creation_at), который обычно позволяет выполнять этот запрос и сортировку в памяти. Но, в течение этих трех часов, не очень. То, что обычно является мгновенным запросом, варьировалось от 2 до 45 секунд в течение этого периода времени. Затем все вернулось к норме.

Я просматривал наш медленный журнал запросов, и больше ничего не выглядит необычным. Я посмотрел на New Relic (это приложение Rails), и все остальные действия выполнялись с той же скоростью, что и обычно. У нас не было необычного количества сообщений сегодня. Я не могу найти ничего более странного в наших журналах. И база данных не менялась, когда у нее все еще оставались гигабайты памяти для использования.

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

Кто-нибудь еще сталкивался с периодически медленным запросом, который игнорировал причину? Или у вас есть творческие идеи о том, как можно решить проблему, подобную этой?

Ответы [ 2 ]

2 голосов
/ 10 августа 2009

На сайте, над которым я работаю, мы недавно переключились на InnoDB из MyISAM, и мы обнаружили, что некоторые простые запросы на выборку, которые содержали предложения WHERE и ORDER BY, использовали индекс для предложения ORDER BY , в результате сканирования таблицы, чтобы найти несколько нужных строк (но, черт возьми, их не нужно было сортировать, когда он наконец нашел их все!)

Как отмечено в связанной статье, если у вас есть небольшое значение LIMIT, ваше предложение ORDER BY является первым членом первичного ключа (поэтому данные в файле упорядочены им), и есть много результатов, которые соответствуют вашему Предложение WHERE, использование этого индекса ORDER BY - неплохая идея для MySQL. Однако я полагаю, что create_at не является первым членом вашего первичного ключа, поэтому в данном случае это не особо разумная идея.

Я не знаю, почему MySQL переключал бы индексы, если вы ничего не меняли, но я бы посоветовал вам запустить ANALYZE TABLE для соответствующей таблицы. Вы также можете изменить запрос, чтобы удалить предложения LIMIT и ORDER BY и выполнить сортировку на уровне приложения, если набор результатов достаточно мал; или вы можете добавить подсказку USE INDEX , чтобы он никогда не угадал.

Вы также можете изменить значение wait_timeout на что-то меньшее , чтобы эти запросы, использующие неверный индекс, просто никогда не завершались (но не отставали и от всех допустимых запросов). Вы по-прежнему сможете выполнять длинные запросы в интерактивном режиме, даже с небольшим временем ожидания, так как для этого есть отдельный параметр конфигурации.

2 голосов
/ 10 августа 2009

Я бы попробовал оператор MySQL EXPLAIN ...

EXPLAIN SELECT * FROM `posts` WHERE (`posts`.forum_id = 1)  ORDER BY posts.created_at DESC LIMIT 1;

Возможно, стоит проверить время отклика MySQL в вашем коде Rails, и если оно превышает пороговое значение, тогда запустите EXPLAIN и запишите где-нибудь подробности.

Блокировка таблицы также приходит на ум - обновляется ли таблица posts с помощью cronjob или здоровенного запроса во время SELECTs?

Надеюсь, это немного поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...