#mysql #performance #memory-table
#mysql #Производительность #таблица памяти
Вопрос:
У меня есть таблица ПАМЯТИ с примерно 650 строками, длиной данных 5 МБ, длиной индекса 60 КБ (так что она довольно маленькая). Он имеет один первичный (хэш-ключ SMALLINT и около 90 других столбцов (целые числа, переменные, даты и времени, без больших двоичных объектов или текстов). (РЕДАКТИРОВАТЬ: в столбце BIGINT также есть хэш-ключ.)
Я выполняю этот запрос (из PHP) довольно часто (около 10 раз в секунду):
выберите * из userek, где id={CONST_ID} и kitiltva=0 и kitiltva_meddig<«{CONST_DATETIME}» и inaktiv=0
Примечание: id
является первичным ключом. Мне нужно *
, потому что результат используется во многих разных местах, и в основном все столбцы используются здесь или там.
Моя проблема в том, что запрос регулярно становится ненормально медленным. Примерно 0.5s
в среднем, 8s
макс. В большинстве случаев это происходит очень быстро: 75%
of выполняется быстрее 3ms
, 85%
быстрее, чем в среднем. Но 15%
это медленнее, чем в среднем, 13%
медленнее, чем 1s
. Так что у него длинный хвост.
И я абсолютно не представляю, что может вызвать это. Какие-нибудь мысли у кого-нибудь?
Комментарии:
1. В таблице нет других индексов, кроме PK ?
2. О, в столбце BIGINT есть еще один хэш-индекс. Вот и все.
3. Индекс BTREE on
(id,kitiltva,inaktiv,kitiltva_meddig)
был бы наиболее подходящим для этого запроса. Но я не работал с таблицами ПАМЯТИ, поэтому кто-то с большим опытом может посоветовать, будет ли это (добавление индекса) уместно в данном случае.4. Или, если есть другие более вероятные проблемы с таблицами памяти.
5. ОБЪЯСНЕНИЕ показывает, что запрос использует первичный индекс с const , что, насколько я знаю, является самым быстрым возможным решением. Но вы дали мне идею: я попытаюсь извлечь другие условия из запроса (и в PHP), и мы увидим…
Ответ №1:
Извините, что отвечаю на мой собственный вопрос, но, по крайней мере, у меня есть ответ. Я пытаюсь написать это таким образом, чтобы это было полезно для других.
Поскольку это таблица ПАМЯТИ, я исключил проблемы ввода-вывода.
Далее, запрос представляет собой простой (постоянный) выбор по первичному ключу, поэтому он также не может быть проблемой индексации.
Следующим предположением была блокировка. В моем приложении есть / были некоторые очень медленные выборки в этой таблице. И это может быть проблемой: медленные выборки задерживают обновления, которые задерживают другие выборки, так что в конце концов этот очень простой и быстрый выбор может быть отложен.
Я проверил 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
, анализируйте и улучшайте медленные запросы - если вы сталкиваетесь с необъяснимыми замедлениями, всегда проверяйте «пересекающиеся» запросы, которые замедляют ваш запрос, блокируя одну и ту же таблицу
Комментарии:
1. Прекрасно ответить на ваш собственный вопрос, поскольку это может помочь другим в будущем. Также хорошо и полезно пометить это как «принятый ответ», щелкнув галочку рядом с ним. Это сразу предупреждает других о том, что этот ответ сработал.
2. Спасибо за отзыв. Я не был уверен в принятии моего собственного ответа… Я получил сообщение «Вы можете принять свой собственный ответ через 2 дня», поэтому я немного подожду…