Может, вы заметили, после переезда обратно в Канаду lleo.me стал иногда притормаживать — был выделенный сервер, теперь просто виртуалка. Беглое изучение вопроса показало, что притормаживает mysql MariaDB. А надо честно признаться, что оптимизацией запросов в движке я практически никогда и не занимался — так, более-менее интуитивно индексы создавал. Теперь впервые включил лог медленных запросов и хочу понять, что сделать для оптимизации нагрузки.
Но сразу конечно вопросы. Вот например, тормозит бывало такой запрос (лог цитирую полностью, потому что не понимаю половины):
# User@Host: root[root] @ localhost []
# Thread_id: 630 Schema: dnev QC_hit: No
# Query_time: 0.010746 Lock_time: 0.000058 Rows_sent: 1 Rows_examined: 25281
# Rows_affected: 0
# Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk: No
# Filesort: No Filesort_on_disk: No Merge_passes: 0 Priority_queue: No
SET timestamp=1572981828;
SELECT `id` FROM `socialmedias` WHERE `num`='4063' AND `net`='lj:lleo';
Почему, кстати «Query_time: 0.010746", когда я просил в настройках логгировать slow-запросы в 5 секунд, — загадка, ну да небось он сам выбирает, какие у него проблемные самые.
Суть в том, что индексы у таблицы `socialmedias` я когда-то сделал такими:
KEY `new` (`acn`,`num`,`net`(64)),
KEY `url` (`url`),
KEY `type` (`type`)
Правильно ли я понимаю, что запрос «WHERE `num`='' AND `net`=''» будет тормозить просто потому, что нет индекса «num+net», а есть только индекс «num+net+acn», но последний параметр не указан в запросе, поэтому индекса, считай, нету? И если я тупо добавлю в запросе « AND `acn`=0» (в однопользовательском движке он всегда 0), то всё начнёт летать? Мне почему-то раньше казалось, что MySQL сам разберется с недостающим параметром... Собственно, я так и сделал, и вроде правда эта строчка перестала вылезать в логах.
Или вот такое же:
`site` (
`name` varchar(128) NOT NULL default '',
`text` text NOT NULL default '',
`acn` int(10) unsigned NOT NULL default '0' COMMENT 'Номер журнала',
PRIMARY KEY (`acn`,`name`)
) ENGINE=MyISAM;
Мне добавить «WHERE `name`='redirect' AND `acn`=0», и всё начнет летать?
Или вот странное, тут-то вроде индекс есть ровно тот, что спрашивается, просто база распухла наверно за два года для такой сложной операции ORDER BY?
CREATE TABLE IF NOT EXISTS `bitcoin` (
`time` int(11) unsigned NOT NULL default '0',
`BTC` mediumint(8) unsigned NOT NULL default '0',
PRIMARY KEY (`time`)
) ENGINE=XtraDB DEFAULT CHARSET=cp1251;
В общем, если есть специалист по оптимизации MySQL, которому я иногда в Телеграме могу задавать подобные вопросы, отзовитесь.
UPD:Кирилл объяснил магию: оказывается, коллективный индекс (A,B,C) и впрямь может использоваться не только при запросе, содержащем A,B,C, но также A,B и просто A. Но не B,С, не B и не C! Потому что очень важен порядок.
Осознать эту мистику сложно, но я это вижу так: допустим, есть база с полями «страна», «город», температура»:
RU, Москва, +10
RU, Москва, +8
UK, Лондон, +10
UK, Манчестер, +10
RU, Новосибирск, -1
FR, Париж, +13
Видимо коллективный индекс mysql создает встык: «RUМосква+3», «UKЛондон+10»... и дальше он может найти все записи, чей индекс начинается с «RUМосква...» и даже с «RU...», но найти все города и страны с температурой «........+10» для него невозможно, так как не умеет сравнивать с конца.