Произволното вмъкване на заявка в 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
Опишете вашата тестова среда (процесор, RAM, диск, свободно място на диска, какво друго работи в кутията, което може да се конкурира за CPU/RAM/диск). Понякога произволните проблеми с производителността са екологични.   -  person Dave W. Smith    schedule 05.06.2010
comment
Приложението е на VPS хостинг план с приблизително 300 MB RAM. Това е CentOS сървър, работещ с обикновено минимален уеб софтуер.   -  person CrossProduct    schedule 05.06.2010


Отговори (3)


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

Ако данните в реда са големи, това ще отнеме известно време.

За вашия случай може да е най-добре да използвате първичен ключ за автоматично нарастване и просто да използвате уникален индекс на sessId, така че да не вмъквате записи в средата на клъстерен индекс.

person Marcus Adams    schedule 05.06.2010

Възпроизведете проблема на нещо, което не е VM, след което можете да се оплачете.

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

По всяка вероятност innoDB се опитва да направи fdatasync(). Това трябва да направи някакъв действителен физически IO, който е блокиран от друга задача на хост кутията (може би друга виртуална машина), която прави нещо. Ако не ги контролирате, не можете да предвидите какво ще бъде поведението му.

Ако таблицата на сесиите не трябва да бъде постоянна при спиране на база данни, помислете за ENGINE=Memory.

Ако нямате строго изискване за издръжливост на данните, намалете настройките за издръжливост на innodb (но това ще засегне целия сървър, а не само таблицата)

person MarkR    schedule 05.06.2010
comment
Виждам мнението ви за евентуален спор за VM. Дори ако ресурсите са гарантирани, има само една глава на твърд диск на машина. Обмислях използването на MEMORY двигателя, но според документацията на MySQL; Таблиците MEMORY използват формат за съхранение на редове с фиксирана дължина. Така че това вероятно не е най-добрият начин за съхраняване на двоични данни, които варират по размер, особено ако по-голямата част от записите ще бъдат празни. - person CrossProduct; 06.06.2010
comment
Опитвали ли сте да възпроизведете проблема на не-VM? Ако можете, тогава трябва да се направи повече разследване. Като цяло производителността, латентността и т.н. не са толкова добри на VM, колкото на реалния хардуер, и са много по-малко предвидими. - 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