yii2数据提供者查询需要很长时间

时间:2018-10-16 08:57:01

标签: php mysql yii2 query-optimization

我正在使用yii2数据提供程序从数据库中提取数据。原始查询如下所示

 SELECT `client_money_operation`.* FROM `client_money_operation` 
 LEFT JOIN `user` ON `client_money_operation`.`user_id` = `user`.`id` 
 LEFT JOIN `client` ON `client_money_operation`.`client_id` = `client`.`id` 
 LEFT JOIN `client_bonus_operation` ON `client_money_operation`.`id` = `client_bonus_operation`.`money_operation_id` 
 WHERE (`client_money_operation`.`status`=0) AND (`client_money_operation`.`created_at` BETWEEN 1 AND 1539723600) 
 GROUP BY `operation_code` ORDER BY `created_at` DESC LIMIT 10

此查询需要107秒才能执行。 表client_money operations包含132000行。我该怎么做才能优化此查询或正确设置数据库?

2 个答案:

答案 0 :(得分:0)

尝试分页。但是,如果您必须一次显示大量记录,则可以删除尽可能多的左联接。如果确实需要显示在一次性结果集中,则可以在client_money_operation表中复制一些数据。

答案 1 :(得分:0)

SELECT  mo.*
    FROM  `client_money_operation` AS mo
    LEFT JOIN  `user` AS u  ON mo.`user_id` = u.`id`
    LEFT JOIN  `client` AS c  ON mo.`client_id` = c.`id`
    LEFT JOIN  `client_bonus_operation` AS bo  ON mo.`id` = bo.`money_operation_id`
    WHERE  (mo.`status`=0)
      AND  (mo.`created_at` BETWEEN 1 AND 1539723600)
    GROUP BY  `operation_code`
    ORDER BY  `created_at` DESC
    LIMIT  10 

GROUP BY的相当混乱的用法。首先,在SELECT列表中有许多未聚合的列时,按一列分组是不合适的。并且created_at中使用ORDER BY是没有意义的,因为尚不清楚哪个日期将与每个operation_code相关联。也许您想要MIN(created_at)

优化...

将对mo和(希望)PRIMARY KEY查找到其他表进行全面扫描。请提供EXPLAIN SELECT ...,以便我们进行检查。

mo上唯一有用的索引是INDEX(status, created_at),它可能有用也可能没有用,具体取决于该日期范围的大小。

bo需要一些以money_operation_id开头的索引。

operation_codecreated_at在哪些表中?它与优化器有很大的不同。

但是有一种模式可以用来大大加快查询速度。 (我无法在不知道这些列所在的表的情况下,也无法使其工作的情况下为您提供详细信息。)

SELECT mo.*
    FROM ( SELECT mo.id FROM .. WHERE .. GROUP BY .. ORDER BY .. LIMIT .. ) AS x
    JOIN mo  ON x.id = mo.id
    ORDER BY ..   -- yes, repeated

也就是说,首先(在派生表中)完成 minimum 的工作,以查找所需的10行的id,然后然后使用JOIN (s)从那里获取其他所需的列。

(如果无法使yii2生成此类代码,那么就这样了。)

相关问题