Простой константный выбор по первичному ключу в маленькой таблице MEMORY очень медленный

У меня есть таблица MEMORY с примерно 650 строками, длиной 5 МБ и длиной индекса 60 КБ (так что она довольно мала). Он имеет один SMALLINT первичный (хэш) ключ и около 90 других столбцов (целые, varchars, datetime, без BLOB-объектов или текстов). (РЕДАКТИРОВАТЬ: есть также ключ хеша в столбце BIGINT.)

Я выполняю этот запрос (из PHP) довольно часто (около 10 раз в секунду):

выберите * из userek, где id={CONST_ID} и kitiltva=0 и kitiltva_meddig<"{CONST_DATETIME}" и inaktiv = 0

Замечания: id является первичным ключом. мне нужно * потому что результат используется во многих разных местах, и в основном все столбцы используются здесь или там.

Моя проблема: запрос становится ненормально медленным на регулярной основе. Около 0.5s в среднем, 8s Максимум. В большинстве случаев это очень быстро: 75% работает быстрее, чем 3ms, 85% быстрее, чем в среднем. Но 15% это медленнее, чем в среднем, 13% медленнее чем 1s, Так что у него длинный хвост.

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

1 ответ

Решение

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

Так как это таблица MEMORY, я исключил проблемы ввода-вывода.

Далее, запрос является простым (постоянным) выбором по первичному ключу, поэтому он также не может быть проблемой индексации.

Следующее предположение было блокировкой. В моей заявке на эту таблицу есть / были очень медленные выборки. И это может быть проблемой: медленные выборки задерживают обновления, которые задерживают другие выборки, так что в итоге этот очень простой и быстрый выбор может быть отложен.

Я проверил slow query log и нашел два частых и медленных выбора, которые использовали эту конкретную таблицу (и другие тоже). Причиной было плохо сформированное соединение по делу:

A left join B on case
when A.x=1 then B.id=A.id2
when A.x=2 then B.id=A.id3
else B.id=0
end

вместо

A left join B on B.id = case
when A.x=1 then A.id2
when A.x=2 then A.id3
else 0
end

Оба дают одинаковый результат, но последний может использовать индекс B.idБывший не может.

После того как я исправил эти запросы, производительность исходного запроса значительно возросла: 5ms вместо 500ms в среднем. А также 98% быстрее, чем в среднем.

Мораль:

  • использование slow query log, проанализируйте его и улучшите медленные запросы
  • если вы сталкиваетесь с необъяснимым замедлением, всегда проверяйте "перекрестные" запросы, которые замедляют ваш запрос, блокируя ту же таблицу
Другие вопросы по тегам