【问题标题】:yii2 data provider query takes very long timeyii2 数据提供者查询需要很长时间
【发布时间】:2018-10-16 08:57:01
【问题描述】:

我正在使用 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 行。我需要做些什么来优化此查询或正确设置我的数据库?

【问题讨论】:

  • 这些表中有索引吗?

标签: php mysql yii2 query-optimization


【解决方案1】:

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

【讨论】:

    【解决方案2】:
    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 列表中有许多非聚合列时按一列分组是不合适的。并且在ORDER BY 中使用created_at 没有意义,因为不清楚哪个日期将与每个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
    

    也就是说,首先(在派生表中)最少工作以找到所需 10 行的 id,然后使用 JOIN (s) 获取其他所需的列。

    (如果 yii2 不能生成这样的,那就是碍事了。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-02
      • 2018-01-09
      • 2015-05-17
      • 1970-01-01
      相关资源
      最近更新 更多