使用高偏移时查询速度相当慢

时间:2014-02-27 22:38:31

标签: mysql database left-join innodb

这是我的查询,当我使用高偏移时速度相当慢,为什么呢?这有什么办法吗?

   offset 15 =>  0.9747  seconds

    SELECT `users`.*, count(`user_bets`.`id`) as bets, count(`user_bet_details`.`id`) as wins
    FROM `users`
    LEFT JOIN `user_bets` ON `user_bets`.`user_id` = `users`.`id`
    LEFT JOIN `user_bet_details` ON `user_bet_details`.`user_id` = `users`.`id` and `user_bet_details`.`status` = 1 
    GROUP BY `users`.`id`
     LIMIT 15, 10 

  offset 2510 => 26.2188  seconds 

SELECT `users`.*, count(`user_bets`.`id`) as bets, count(`user_bet_details`.`id`) as wins
    FROM `users`
    LEFT JOIN `user_bets` ON `user_bets`.`user_id` = `users`.`id`
    LEFT JOIN `user_bet_details` ON `user_bet_details`.`user_id` = `users`.`id` and `user_bet_details`.`status` = 1 
    GROUP BY `users`.`id`
     LIMIT 2510, 10  

1 个答案:

答案 0 :(得分:3)

速度差异可能来自服务器为满足查询而必须生成的行数。对于第一种情况,它只需要生成25行结果集。对于第二个,它必须生成2520行。

由于订单显然不重要(基于查看指定的查询),也许您可​​以将其更改为执行"分页"使用用户id值(假设它以某种可预测的方式递增)。添加一个WHERE子句,指定感兴趣的用户ID范围并放弃LIMIT子句。例如,可能是这样的:

SELECT `users`.*, count(`user_bets`.`id`) as bets, count(`user_bet_details`.`id`) as wins
    FROM `users`
    LEFT JOIN `user_bets` ON `user_bets`.`user_id` = `users`.`id`
    LEFT JOIN `user_bet_details` ON `user_bet_details`.`user_id` = `users`.`id` 
               and `user_bet_details`.`status` = 1 
    WHERE `users`.`id` >= 1 and `users`.`id` <= 10
    GROUP BY `users`.`id`

这可能会更有效地运行,但如果id不增加1(这似乎很可能),则获得所需行数会更加棘手。您仍然可以每次使用LIMIT子句和稍大的范围,然后在下一次调用时适当地指定下限(我再次假设这是用于分页结果)。

但在此之前,您可能会check the optimization查询。例如,如果您没有在连接表上提供索引(特别是user_bets.user_iduser_bet_details.user_iduser_bet_details.status),那么这可能会产生巨大的差异。我没有真正考虑过最初指定的时间,但生成该查询的时间似乎非常长。听起来好像可能需要创建一些索引。