有问题的表有数百万条记录。以下查询非常慢(最多需要四分钟),因为MySQL选择主键作为索引。
SELECT
*
FROM
`activities`
WHERE
`integration_id` = 11
ORDER BY `id` DESC
LIMIT 10 OFFSET 2
该表有多个索引,包括集成索引。强制使用时,使用此索引可将查询时间缩短到大约一秒:
SELECT
*
FROM
`activities`
USE INDEX (integration)
WHERE
`integration_id` = 11
ORDER BY `id` DESC
LIMIT 10 OFFSET 2
使用EXPLAIN,MySQL显示以下内容:
第一次查询:(慢一点)
第二次查询:(快速查询)
看到MySQL的解释,我理解为什么它选择主键。但是,实际上第一个查询中的行数应该是数百万;而且确实执行得非常缓慢。
不幸的是,我不能只在查询中强制索引,因为查询是动态的(可以包含一些其他子句),并且使用ORM。所以我正在寻找MySQL配置的解决方案,如果可能的话。
额外信息
我发现在某些情况下改变查询会导致MySQL选择正确的索引。例如。删除ORDER BY
子句,并将SELECT *
替换为SELECT <insert every table column here>
。我不知道为什么。删除订单对我来说是没有选择的,并且使用ORM手动选择每一列都很棘手(除此之外,我想知道为什么这会修复索引选择)。
EXPLAIN
显示创建表
'CREATE TABLE `activities` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`content` text COLLATE utf8_unicode_ci NOT NULL,
`parameters` text COLLATE utf8_unicode_ci,
`input` text COLLATE utf8_unicode_ci,
`output` text COLLATE utf8_unicode_ci,
`response` text COLLATE utf8_unicode_ci,
`integration_id` int(10) unsigned DEFAULT NULL,
`level` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`category` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `integration_category` (`integration_id`,`category`),
KEY `integration_level` (`integration_id`,`level`),
KEY `integration_category_level` (`integration_id`,`category`,`level`),
KEY `integration` (`integration_id`),
CONSTRAINT `activities_integration_id_foreign` FOREIGN KEY (`integration_id`) REFERENCES `integrations` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=11262471 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci'