На днях звонят мне наши веб-разработчики и говорят, мол MySQL тормозит адово, сил нет никаких терпеть, а при нескольких одновременных запросах и вовсе транзакции валятся по таймауту.
Привычный осмотр processlist'a показал вполне ожидаемую картину. В таблице чуть более 11 миллионов строк, и уже где-то полминуты висит простенький запрос типа UPDATE some_table SET act_status = 1 WHERE grp_id = 10885882802223, останавливаться он при этом не собирается, а в State красуется "Queried about 5120000 rows".
«Опять индекс не поставили!», - подумал Штирлиц и отправил разработчиков расставлять индексы, попросив попутно не отвлекать более подобными пустяками.
Однако, индекс был. Но всё равно фуллскан. Как так? А очень просто, как оказалось в итоге. В вышеуказанном запросе поле grp_id, если положиться на здравый смысл, должно иметь какой-нибудь целочисленный тип. Но здравый смысл - это для кого-то другого. Тот, кто делал эту прекрасную таблицу, решил что лучше будет, если это поле сделать VARCHAR.
Ну а вишенкой на торте стал самописный недо-ORM, который был написан или тем человеком, который сделал ту прекрасную таблицу, или его сообщником (сообщниками?), ну или сразу группой лиц с особой жестокостью.
Этот самый недо-ORM строил запросы следующим образом: если запрашиваемое значение включало только цифры, то кавычек в запросе не было. Ну а если цифры и буквы, то кавычки заботливо подставлялись.
В результате мы имели то, что имели (проблему с фуллсканом и адовые тормоза).
Смотрим внимательно. Что получалось и как быть не должно, если уж мы имеем дело с VARCHAR:
А вот как надо было:
Ситуация на самом деле идиотская донельзя и руки бы отрывать за такие изыски. Какие-нибудь еще выводы оставляю право читателю сделать самостоятельно.
Привычный осмотр processlist'a показал вполне ожидаемую картину. В таблице чуть более 11 миллионов строк, и уже где-то полминуты висит простенький запрос типа UPDATE some_table SET act_status = 1 WHERE grp_id = 10885882802223, останавливаться он при этом не собирается, а в State красуется "Queried about 5120000 rows".
«Опять индекс не поставили!», - подумал Штирлиц и отправил разработчиков расставлять индексы, попросив попутно не отвлекать более подобными пустяками.
Однако, индекс был. Но всё равно фуллскан. Как так? А очень просто, как оказалось в итоге. В вышеуказанном запросе поле grp_id, если положиться на здравый смысл, должно иметь какой-нибудь целочисленный тип. Но здравый смысл - это для кого-то другого. Тот, кто делал эту прекрасную таблицу, решил что лучше будет, если это поле сделать VARCHAR.
Ну а вишенкой на торте стал самописный недо-ORM, который был написан или тем человеком, который сделал ту прекрасную таблицу, или его сообщником (сообщниками?), ну или сразу группой лиц с особой жестокостью.
Этот самый недо-ORM строил запросы следующим образом: если запрашиваемое значение включало только цифры, то кавычек в запросе не было. Ну а если цифры и буквы, то кавычки заботливо подставлялись.
В результате мы имели то, что имели (проблему с фуллсканом и адовые тормоза).
Смотрим внимательно. Что получалось и как быть не должно, если уж мы имеем дело с VARCHAR:
EXPLAIN select * from some_table where grp_id = 10885882802223 LIMIT 1;
+------+-------------+------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+------------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | some_table | ALL | grp | NULL | NULL | NULL | 7747809 | Using where |
+------+-------------+------------+------+---------------+------+---------+------+---------+-------------+
А вот как надо было:
EXPLAIN select * from some_table where grp_id = '10885882802223' LIMIT 1;
+------+-------------+------------+------+---------------+-------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+------------+------+---------------+-------+---------+-------+------+-------------+
| 1 | SIMPLE | some_table | ref | grp | grp | 99 | const | 1 | Using where |
+------+-------------+------------+------+---------------+-------+---------+-------+------+-------------+
Ситуация на самом деле идиотская донельзя и руки бы отрывать за такие изыски. Какие-нибудь еще выводы оставляю право читателю сделать самостоятельно.