【问题标题】:MySQL Query Performance and CodeigniterMySQL 查询性能和 Codeigniter
【发布时间】:2014-03-06 15:20:08
【问题描述】:

我有这个 MySQL 查询,我正在加载到我的家庭控制器中,在运行 Codeigniter 的 $this->output->enable_profiler(TRUE); 后,我得到了 5.3044 的执行时间

我的模型中的查询:

class Post extends CI_Model {

    function stream($uid, $updated, $limit) {
        $now = microtime(true);
        $sql = "
            SELECT 
                * 
            FROM 
                vPAS_Posts_Users_Temp 
            WHERE 
                post_user_id = ? 
                AND post_type !=4 
                AND post_updated > ?
                AND post_updated < ? 
            UNION 

            SELECT 
                u.* 
            FROM 
                vPAS_Posts_Users_Temp u 
            JOIN 
                PAS_Follow f 
                ON f.folw_followed_user_id = u.post_dynamic_pid 
                WHERE u.post_updated > ?
                AND post_updated < ? 
                AND (( f.folw_follower_user_id = ? AND f.folw_deleted = 0 ) 
                OR ( u.post_passed_on_by = f.folw_follower_user_id OR u.post_passed_on_by = ? AND u.post_user_id != ? AND u.post_type =4 )) 
            ORDER BY 
                post_posted_date DESC 
            LIMIT ?
        "; 

        $query = $this->db->query($sql, array($uid, $updated, $now, $updated, $now, $uid, $uid, $uid, $limit));

        return $query->result();
    }

}

我可以在这里做些什么来缩短执行时间,从而增加我的页面负载?

编辑

解释结果

MySQL Workbench 可视化解释

【问题讨论】:

  • 你在f.folw_followed_user_id和u.post_dynamic_pid这两个字段上设置了索引吗?
  • 你看过查询EXPLAIN的输出了吗?
  • @jeff 我在f.folw_followed_user_id 上有,但另一个字段是在查询中动态创建的,所以我不确定如何执行此操作
  • @bmused 添加了我的Explain 结果
  • 使用mysql工作台检查查询执行的性能

标签: php mysql sql codeigniter


【解决方案1】:

也许你不会相信,但不要在你的 SQL 中检索 SELECT *。只需编写您要检索的字段,我认为它会加快很多。

我已经看到在执行查询时(从 0.4 秒到 0.02 秒)的速度提高了 20 多倍,只需更改必填字段的 *。

其他事情:如果您在表中的 INSERT 上有一个 auto_increment id,请不要使用 post_posted_date 作为 ORDER 字段。按 DATETIME 字段排序很慢,如果您可以使用 INT id(希望您将其作为索引),您将更快地获得相同的结果。

更新

根据问题要求,技术原因:

奖励:学习如何设置索引:http://ronaldbradford.com/blog/tag/covering-index/

【讨论】:

    【解决方案2】:

    我会在post_user_idpost_updatedfolw_follower_user_id 上添加索引。

    在这种情况下,最好不要使用union 并将查询分成两个单独的查询,然后使用PHP 组合成两个结果集。

    如果您切换到使用活动记录,您还可以查看caching,以获得更好的性能

    【讨论】:

      【解决方案3】:

      rows 列显示了需要检查的行数的估计值,据我了解,这意味着在您的情况下,它必须扫描 72 * 1 * 2627 * 1 * 2 行,这相当多。

      现在,诀窍是降低这个数字,一种方法是添加索引。在您的情况下,我建议添加一个包含以下内容的索引: post_user_id, post_type, post_updated, post_updated.
      这应该会减少第一个结果集,共 72 行。

      现在对于UNION,请尝试改用UNION ALL,因为它声称更快。
      如果这不能解决问题,我建议重写查询以完全不使用 UNION 调用。

      【讨论】:

      • 72 * 1 * 2627 * 1 * 2 = 378288
      【解决方案4】:

      尝试在同一张表上联合时尝试使用左连接查询

      "SELECT 
      u.* 
              FROM 
                  vPAS_Posts_Users_Temp u
                  LEFT JOIN PAS_Follow f ON f.folw_followed_user_id = u.post_dynamic_pid 
              WHERE (
              u.post_user_id = ? 
                      AND u.post_type !=4 
                      AND u.post_updated > ?
                      AND u.post_updated < ?
          ) 
          OR 
           (
          u.post_updated > ?
              AND post_updated < ? 
              AND (( f.folw_follower_user_id = ? AND f.folw_deleted = 0 ) 
                      OR ( u.post_passed_on_by = f.folw_follower_user_id OR u.post_passed_on_by = ? AND u.post_user_id != ? AND u.post_type =4 )) 
          )
              ORDER BY 
                  u.post_posted_date DESC 
                  LIMIT ?"
      

      【讨论】:

      • 我没有考虑你的所有情况,我只是展示了如何使用左连接来做到这一点
      【解决方案5】:

      我认为您可以从查询中删除 UNION 并改用左连接并避免不必要的条件:

      SELECT U.* 
      FROM vPAS_Posts_Users_Temp AS U 
      LEFT JOIN PAS_Follow AS F ON F.folw_followed_user_id = U.post_dynamic_pid 
      WHERE U.post_updated > ?
      AND U.post_updated < ?
      AND ( 
            ( 
              F.folw_follower_user_id = ? AND F.folw_deleted = 0 
            ) 
            OR 
            ( 
              U.post_passed_on_by = F.folw_follower_user_id OR U.post_passed_on_by = ? 
            )
          ) 
      ORDER BY 
      U.post_posted_date DESC 
      LIMIT ?
      

      同时在您的表格中识别并设置正确的indexes

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-09
        • 1970-01-01
        • 2012-07-18
        • 2015-06-06
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        • 2011-10-23
        相关资源
        最近更新 更多