Запрос MySQL на вставку случайным образом занимает много времени

Я использую MySQL для управления данными сеанса для моего приложения PHP. При тестировании приложение обычно очень быстрое и отзывчивое. Однако, казалось бы, случайным образом ответ останавливается, прежде чем окончательно завершиться через несколько секунд. Я сузил проблему до запроса записи сеанса, который выглядит примерно так:

INSERT INTO Session VALUES('lvg0p9peb1vd55tue9nvh460a7', '1275704013', '') ON DUPLICATE KEY UPDATE sessAccess='1275704013',sessData='';

Журнал медленных запросов содержит следующую информацию:

Query_time: 0.524446  Lock_time: 0.000046 Rows_sent: 0  Rows_examined: 0

Это происходит примерно в 1 из каждых 10 раз. Запрос обычно занимает всего ~ 0,0044 секунды.

Таблица представляет собой InnoDB с примерно 60 строками. sessId — это первичный ключ с индексом BTREE.

Поскольку к нему обращаются при каждом просмотре страницы, это явно неприемлемое время выполнения. Почему это происходит?

Обновление: схема таблицы: sessId:varchar(32), sessAccess:int(10), sessData:text


person CrossProduct    schedule 05.06.2010    source источник
comment
Какой тип столбца sessData? Пожалуйста, предоставьте полную схему для вашей таблицы.   -  person Marcus Adams    schedule 05.06.2010
comment
Опишите вашу тестовую среду (процессор, ОЗУ, диск, свободное место на диске, что еще работает на машине, что может конкурировать за процессор/ОЗУ/диск). Иногда случайные проблемы с производительностью связаны с окружающей средой.   -  person Dave W. Smith    schedule 05.06.2010
comment
Приложение находится на тарифном плане хостинга VPS с примерно 300 МБ ОЗУ. Это сервер CentOS, на котором обычно работает минимальное веб-программное обеспечение.   -  person CrossProduct    schedule 05.06.2010


Ответы (3)


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

Если данные строки большие, это займет некоторое время.

В вашем случае может быть лучше использовать первичный ключ автоинкремента и просто использовать уникальный индекс для sessId, чтобы вы не вставляли записи в середину кластеризованного индекса.

person Marcus Adams    schedule 05.06.2010

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

По моему опыту, виртуальные машины, особенно те, которыми пользуются произвольные третьи лица, имеют поведение, на которое нельзя положиться.

По всей вероятности, innoDB пытается выполнить fdatasync(). Для этого необходимо выполнить некоторый фактический физический ввод-вывод, который заблокирован другой задачей на хосте (возможно, другой виртуальной машиной), которая что-то делает. Если вы не контролируете их, вы не можете предсказать, каким будет их поведение.

Если таблица сеансов не должна сохраняться при выключении базы данных, рассмотрите вариант ENGINE=Memory.

Если у вас нет жестких требований к надежности данных, уменьшите настройки устойчивости innodb (но это повлияет на весь сервер, а не только на таблицу)

person MarkR    schedule 05.06.2010
comment
Я понимаю вашу точку зрения о возможном конфликте виртуальных машин. Даже если ресурсы гарантированы, на каждую машину приходится только одна головка жесткого диска. Я рассматривал возможность использования механизма MEMORY, но согласно документации MySQL; Таблицы MEMORY используют формат хранения строк фиксированной длины. Таким образом, это, вероятно, не лучший способ хранения двоичных данных, которые различаются по размеру, особенно если большинство записей будут пустыми. - person CrossProduct; 06.06.2010
comment
Вы пытались воспроизвести проблему на не виртуальной машине? Если вы можете, то необходимо провести дополнительное расследование. В общем, производительность, задержка и т. д. на виртуальной машине не так хороши, как на реальном оборудовании, и гораздо менее предсказуемы. - person MarkR; 07.06.2010

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

Решение состояло в том, чтобы переключить движок таблицы на MyISAM, который делает вставки быстрее.

person CrossProduct    schedule 05.06.2010
comment
Почему таблица MYISAM вставляется быстрее, чем таблица INNODB? Механизм MyISAM лучше всего подходит для чтения, а не для записи. - person Hắc Huyền Minh; 27.08.2013