2011-10-25 10 views
0

У меня есть таблица MEMORY с примерно 650 строками, длиной данных 5 МБ, длиной индекса 60 кБ (так что это довольно мало). Он имеет один основной (хэш) ключ SMALLINT и около 90 других столбцов (ints, varchars, datetimes, no blobs или text). (EDIT: есть также хэш-ключ на колонке BIGINT.)Простой константный выбор на первичном ключе в маленькой таблице MEMORY очень медленный

Я бегу этот запрос (с PHP) довольно часто (около 10 раз в секунду):

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

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

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

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

+0

Нет других указателей на столе, кроме ПК? –

+0

О, есть еще один хэш-индекс в столбце BIGINT. Вот и все. – Cucu

+0

Индекс BTREE на '(id, kitiltva, inaktiv, kitiltva_meddig)' будет наиболее подходящим для этого запроса. Но я не работал с таблицами MEMORY, поэтому кто-то, у кого больше опыта, может посоветовать, если это (добавление индекса) было бы уместным в этом случае. –

ответ

0

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

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

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

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

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

Это прекрасно, чтобы ответить на ваш собственный вопрос, поскольку это может помочь другим в будущем. Также хорошо и полезно отметить это как «принятый ответ», щелкнув галочку рядом с ней. Это сразу же предупреждает других о том, что этот ответ сработал. – PengOne

+0

Спасибо за отзыв. Я не был уверен в принятии моего собственного ответа ... Я получил сообщение «Вы можете принять свой собственный ответ через 2 дня ", поэтому я подожду немного ... – Cucu