Простой константный выбор по первичному ключу в маленькой таблице памяти очень медленный - PullRequest
0 голосов
/ 25 октября 2011

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

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

выберите * из userek, где id = {CONST_ID} и kitiltva = 0 и kitiltva_meddig <"{CONST_DATETIME}" и инактив = 0 </p>

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

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

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

1 Ответ

0 голосов
/ 26 октября 2011

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

Поскольку это таблица 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, проанализируйте его и улучшите медленные запросы
  • если вы сталкиваетесь с необъяснимыми замедлениями, всегда проверяйте «перекрестные» запросы, которые замедляют ваш запрос, блокируя ту же таблицу
...