使用LIMIT MySQL时如何减少行查找
下表的索引位于使用LIMIT MySQL时如何减少行查找,mysql,Mysql,下表的索引位于id,外键位于activityID: 注释(id、活动id、文本) 以及以下查询: 从`comment`中选择,其中`comment`.`activityID`=1257按`id`顺序描述限制20; 我基本上只想获得该活动的前20条评论,共1165条,然而,这是一个描述的结果: id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE
id
,外键位于activityID
:
注释(id、活动id、文本)
以及以下查询:
从`comment`中选择,其中`comment`.`activityID`=1257按`id`顺序描述限制20;
我基本上只想获得该活动的前20条评论,共1165条,然而,这是一个描述的结果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE comment ref activityID activityID 4 const 1165 NULL
本质上,它是在决定限制此活动之前,先查看所有有关此活动的评论
我们在高负载下测试了这个查询,当一个活动有200000条注释时,查询需要5秒以上的时间,而在相同负载下,一个有30条注释的活动需要几毫秒的时间
PS:如果我删除WHERE
子句,解释说它只会查找一行(不知道是否真的是这样):
有可能以任何方式优化这种查询吗
谢谢。因为订货太慢了 查询使用
activityID
索引查找具有该ID的所有行。然后它必须读取所有200000条注释,并按ID
对它们进行排序,以查找最后20条注释
添加复合索引,以便可以使用索引进行排序:
ALTER TABLE comment ADD INDEX (activityID, id);
请注意,
activityID
上的索引本身将不再需要,因为它是这个新索引的前缀。排序导致了速度缓慢
查询使用activityID
索引查找具有该ID的所有行。然后它必须读取所有200000条注释,并按ID
对它们进行排序,以查找最后20条注释
添加复合索引,以便可以使用索引进行排序:
ALTER TABLE comment ADD INDEX (activityID, id);
请注意,activityID
上的索引本身将不再需要,因为它是这个新索引的前缀。使用偏移量
SELECT <cols> FROM `comment` WHERE `comment`.`activityID` = 1257 ORDER BY `id` DESC LIMIT 0,20;
从`comment`中选择,其中`comment`.`activityID`=1257按`id`DESC限制0,20排序;
在limit子句中,添加0
作为偏移量,以仅获取前20条注释使用偏移量
SELECT <cols> FROM `comment` WHERE `comment`.`activityID` = 1257 ORDER BY `id` DESC LIMIT 0,20;
从`comment`中选择,其中`comment`.`activityID`=1257按`id`DESC限制0,20排序;
在limit子句中,添加
0
作为偏移量,只需在activityID
和id
上添加两个单独的索引即可。这也将有助于您按排序。优化中没有硬性规定,但您需要尝试各种方法
这样做:
ALTER TABLE comment ADD INDEX (id);
ALTER TABLE comment ADD INDEX (activityID);
我想这会有帮助。只需在
activityID
和id
上添加两个单独的索引即可。这也将有助于您按排序。优化中没有硬性规定,但您需要尝试各种方法
这样做:
ALTER TABLE comment ADD INDEX (id);
ALTER TABLE comment ADD INDEX (activityID);
我想这会有帮助。如果添加一个
ORDER BY
子句,会发生什么?没有ORDER BY的LIMIT通常是一种代码味道,因为您不知道将得到哪个20。实际上,我们使用的查询有一个ORDER BY id DESC
子句。我会更新的。可能没什么大不了的,在选择的帮助下会更具体<代码>从中选择'text',而不是*
?实际的代码选择特定的列,我只是将其剥离以使其更易于阅读,并且不会产生任何差异。如果添加一个ORDER BY
子句,会发生什么?没有ORDER BY的LIMIT通常是一种代码味道,因为您不知道将得到哪个20。实际上,我们使用的查询有一个ORDER BY id DESC
子句。我会更新的。可能没什么大不了的,在选择的帮助下会更具体<代码>从中选择'text',而不是*?实际的代码选择特定的列,我只是将其剥离以使其更易于阅读,它不会有任何区别。它没有任何区别。尝试不进行任何排序,尝试使用您建议的索引按id排序,EXPLAIN
返回完全相同的结果。即使删除了旧索引,也可以使用外键。因为它是这个新键的前缀,所以它仍然可以用作外键。我的观点是,orderby
没有任何区别,我甚至尝试使用强制索引(
activityID\u id)
),它是一样的。它没有任何区别。尝试不进行任何排序,尝试使用您建议的索引按id排序,EXPLAIN
返回完全相同的结果。即使删除了旧索引,也可以使用外键。因为它是这个新键的前缀,所以它仍然可以用作外键。我的观点是,ORDER BY
没有任何区别,我甚至尝试使用强制索引(
activityID\u id)
),它是相同的。但是如果没有提供偏移,偏移的默认值是零,所以这似乎没有改变任何东西?哦,对不起,我弄错了,但是如果没有提供偏移量,偏移量的默认值是零,所以这似乎没有改变任何东西?哦,对不起,我的错误id
默认情况下总是有索引activityID
是外键。我不知道你为什么否决了我的答案,你没有在任何地方写下你的id
是问题的主键。这就是为什么我写信来确认这一点。无论如何,如果id
是主键,您仍然需要在activityID
上创建索引。因为外键不会在MyIsam引擎中自动索引,而只在InnoDB中。另外,这是SQL查询将遍历所有记录的一般经验法则,这些记录是满足索引条件的一部分。如果您想进一步减少结果,您需要使用一些组合键来减少行数。id
默认情况下始终有一个索引activityID
是外键。我不知道你为什么否决了我的答案,你没有在任何地方写下你的id
是问题的主键。这就是我为什么这么想的原因