У меня есть запрос, который выглядит очень простым. Однако, если я объединю ORDER BY и LIMIT, производительность снизится по шкале. Я нашел несколько вопросов об ограниченной производительности MySQL в больших таблицах, но я не думаю, что здесь дело обстоит именно так, потому что без LIMIT запрос работает find.
Вот запросы с возрастающей "сложностью" "
SELECT * FROM `mydata`.`mytable` WHERE ((token='XFRA1NMDU9XY') AND (section=210874));
/* Rows: 0 Time: 0,094 sec. */
SELECT * FROM `mydata`.`mytable` WHERE ((token='XFRA1NMDU9XY') AND (section=210874)) LIMIT 1;
/* Rows: 0 Time: 0,063 sec. */
SELECT * FROM `mydata`.`mytable` WHERE ((token='XFRA1NMDU9XY') AND (section=210874)) ORDER BY mailing;
/* Rows: 0 Time: 0,125 sec. */
SELECT * FROM `mydata`.`mytable` WHERE ((token='XFRA1NMDU9XY') AND (section=210874)) ORDER BY mailing LIMIT 1;
/* Rows: 0 Time: 45,500 sec. */
Обратите внимание на значительное увеличение времени запроса в последней строке. Это не исключение, но повторялось несколько раз. На самом деле у меня было время запроса 3 минуты и более для этого запроса, в то время как все остальное работало нормально.
Вот некоторые данные:
- В таблице ~ 2.000.000 записей
- Есть ~ 5.000 записей WHERE (section = 210874)
- База данных работает на MySQL 8.0.20 и Ubuntu 20.04
- Это таблица InnoDB, есть индекс для
section
(и других), но не для token
Вот структура таблицы:
CREATE TABLE `mytable` (
`data` VARCHAR(32) NOT NULL COLLATE 'ascii_bin',
`mailing` INT(10,0) NOT NULL,
`token` VARCHAR(64) NULL DEFAULT NULL COLLATE 'ascii_bin',
`section` INT(10,0) NOT NULL,
`expiry` INT(10,0) NULL DEFAULT NULL,
PRIMARY KEY (`data`) USING BTREE,
INDEX `mailing_CS` (`mailing`) USING BTREE,
INDEX `section_CS` (`section`) USING BTREE,
CONSTRAINT `mailing_CS` FOREIGN KEY (`mailing`) REFERENCES `mydata`.`mailings` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT `section_CS` FOREIGN KEY (`section`) REFERENCES `mydata`.`sections` (`id`) ON UPDATE NO ACTION ON DELETE CASCADE
)
COLLATE='ascii_bin'
ENGINE=InnoDB
;
Любая идея, почему комбинация ORDER BY и LIMIT 1 имеет этот эффект? EXPPLAIN
сообщает мне, что для первого (section_CS
) и последнего запроса (mailing_CS
) используются разные ключи (индексы).
Я могу, конечно, просто оставить LIMIT 1
, потому что на token
не будет одной или нескольких строк. Но я хотел бы разобраться в основной проблеме.