我有大约 2500 万行,其中包含 0.183463545、0.183423545、0.183443545、0.183443445、0.183447545 等。
我需要订购这些,但目前大约需要 20 秒。有什么办法可以加快速度吗? AFAIK,我的索引已正确放置。
谢谢!
SELECT `a`.`float_val`,
`a`.`num_id`,
`b`.`userID`,
`c`.`img`,
`c`.`username`,
`b`.`img`,
`d`.`exterior`
FROM `a`
INNER JOIN `b` ON `b`.`num_id` = `a`.`num_id`
INNER JOIN `d` ON `d`.`id` = `b`.`item`
INNER JOIN `c` ON `c`.`userID` = `b`.`userID`
WHERE `float_val` IS NOT NULL
AND `float_val` BETWEEN 0 AND 1
AND `username` = 'ABC'
ORDER BY `float_val` LIMIT 100
索引位于float_val
、num_id
、userID
CREATE TABLE `float` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`num_id` bigint(11) DEFAULT NULL,
`float_val` decimal(10,10) DEFAULT NULL,
`userID` char(17) DEFAULT NULL,
`last_checked` datetime DEFAULT NULL,
`index10` smallint(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `floatID` (`num_id`),
UNIQUE KEY `num_id` (`num_id`,`userID`),
KEY `userID` (`userID`),
KEY `float_val` (`float_val`),
KEY `last_checked` (`last_checked`),
KEY `index10` (`index10`)
) ENGINE=InnoDB AUTO_INCREMENT=25750916 DEFAULT CHARSET=latin1;
最佳答案
编辑以反射(reflect)显示的表定义。
首先执行查询以获取表 a
中最低的 float_val
行。
SELECT a.id
FROM a
INNER JOIN b ON b.num_id = a.num_id
INNER JOIN d ON d.id = b.item
INNER JOIN c ON c.userID = b.userID
WHERE c.username = 'ABC'
AND a.float_val BETWEEN 0.0 AND 1.0
ORDER BY a.float_val
LIMIT 100
如果您在 a(float_val,num_id)
上有一个索引,并且在 c.username
上有另一个索引,那么速度会相当快。它会吐出作为查询候选的 a
行的 id
值。 (如果您使用 MyISAM,则需要在 a(float_val, num_id, id)
上建立索引。顺便说一句,BETWEEN 子句还暗示 IS NOT NULL。
然后将其用作子查询来完成查询,如下所示。
SELECT a.float_val,
a.num_id,
b.userID,
c.img,
c.username,
b.img,
d.exterior
FROM a
INNER JOIN (
SELECT a.id
FROM a
INNER JOIN b ON b.num_id = a.num_id
INNER JOIN d ON d.id = b.item
INNER JOIN c ON c.userID = b.userID
WHERE c.username = 'ABC'
AND a.float_val BETWEEN 0.0 AND 1.0
ORDER BY a.float_val
LIMIT 100
) q ON a.ID = q.id
INNER JOIN b ON b.num_id = a.num_id
INNER JOIN d ON d.id = b.item
INNER JOIN c ON c.userID = b.userID
WHERE c.username = 'ABC'
AND a.float_val BETWEEN 0.0 AND 1.0
ORDER BY a.float_val LIMIT 100
这种查询包含一个延迟联接。这极大地减少了完整查询中需要遵守ORDER BY ... LIMIT
的行数。如果没有延迟连接,您的原始查询会对一大堆相当长的行进行排序,只是为了丢弃除前一百条之外的所有行。这就是为什么需要这么长时间。
这应该有帮助。下一个优化步骤是查看此查询的 EXPLAIN
输出以及表的确切定义。
专业提示:在这种复杂的查询中,始终使用表名或别名来限定列名。也就是说,始终使用 a.float_val
,而不仅仅是 float_val
。这是对下一个人查看查询的善意。
关于MYSQL按十进制10,10排序大型数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33084587/