如何在没有任何连接的情况下优化大型MySQL表中的查询?
如何从单个大型ish表(约75M行)优化此查询 我为一组特定的类提取最近的10k记录,以便在更大的导入脚本中快速知道它们是否已经存在 我想我已经建立了适当的索引,但是这个查询会持续5-50秒 如果你还需要什么,请告诉我如何在没有任何连接的情况下优化大型MySQL表中的查询?,mysql,sql,query-optimization,Mysql,Sql,Query Optimization,如何从单个大型ish表(约75M行)优化此查询 我为一组特定的类提取最近的10k记录,以便在更大的导入脚本中快速知道它们是否已经存在 我想我已经建立了适当的索引,但是这个查询会持续5-50秒 如果你还需要什么,请告诉我 EXPLAIN SELECT log_id FROM score WHERE class_id IN (17,395) ORDER BY date_reverse LIMIT 10000;
EXPLAIN
SELECT
log_id
FROM
score
WHERE
class_id IN (17,395)
ORDER BY date_reverse
LIMIT 10000;
*** row 1 ***
table: score
type: range
possible_keys: class_id,score_multi_2,class_id_date_reverse,score_multi_5
key: class_id_date_reverse
key_len: 4
ref: NULL
rows: 1287726
Extra: Using where; Using index; Using filesort
CREATE TABLE `score` (
`log_id` bigint(20) NOT NULL,
`profile_id` bigint(20) DEFAULT NULL,
`date` datetime DEFAULT NULL,
`class_id` int(11) NOT NULL,
`score` float(10,6) DEFAULT NULL,
`score_date` datetime DEFAULT NULL,
`process_date` datetime DEFAULT NULL,
`status_type_id` int(3) NOT NULL DEFAULT '0',
`date_reverse` int(11) DEFAULT NULL,
UNIQUE KEY `unique_key` (`log_id`,`class_id`),
KEY `class_id` (`class_id`),
KEY `profile_id` (`profile_id`),
KEY `date` (`date`),
KEY `score` (`score`),
KEY `status_type_id` (`status_type_id `),
KEY `status_type_id_date` (`status_type_id`,`date`),
KEY `class_status_type_id_date_log_id` (`class_id`,`status_type_id`,`date`,`log_id`),
KEY `date_reverse` (`date_reverse`),
KEY `class_id_date_reverse` (`class_id`,`date_reverse`),
KEY `date` (`date`),
KEY `class_id_date_reverse_log_id` (`class_id`,`date_reverse`,`log_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
我猜运行此查询的最快方法是咬紧牙关,允许对20000行进行排序。我想提出的问题是:
SELECT *
FROM ((SELECT log_id
FROM score
WHERE class_id = 17
ORDER BY date_reverse
LIMIT 10000
) UNION ALL
(SELECT log_id
FROM score
WHERE class_id = 395
ORDER BY date_reverse
LIMIT 10000
)
) s
ORDER BY date_reverse
LIMIT 10000;
对于这个查询,您需要在
分数(class\u id,date\u reverse,log\u id)
上的复合索引。每个子查询都应该非常有效地使用这个索引。但是,最后的排序需要使用文件排序。我怀疑Gordon是对的,但我可能也会尝试其他方法。将您的唯一密钥更改为主键,并将顺序颠倒为(class\u id
,log\u id`)。然后尝试像以前一样运行查询。假设这是在Innodb存储引擎上,MySQL将在每个二级索引中包含主键值,使您的日期反向索引有效(class\u id,log\u id)+日期反向。我不确定这是否会对优化器产生影响,但也有可能。我至少会好奇地试一试。谢谢@evanv,你的意思是:altertablescore-DROP-UNIQUE-KEY,ADD-PRIMARY-KEY(class\u-id,log\u-id)代码>@Ryan,是的。同样,我不确定这是否会有帮助。但我愿意试一试。另外,如果你尝试一下的话,把你的class_id键改为log_id。一天结束时,Gordon和evan提出的解决方案对结果时间几乎没有影响。我接受Gordon的答案,因为我最终归档了这个表的很大一部分,以使其工作,并且不再有能力测试其他解决方案。
SELECT *
FROM ((SELECT log_id
FROM score
WHERE class_id = 17
ORDER BY date_reverse
LIMIT 10000
) UNION ALL
(SELECT log_id
FROM score
WHERE class_id = 395
ORDER BY date_reverse
LIMIT 10000
)
) s
ORDER BY date_reverse
LIMIT 10000;