使用多个表优化查询

时间:2015-09-21 11:58:14

标签: mysql sql

我有查询数据来自多个表。

SELECT iUserID,
       iUserID AS userID,
       (CASE vUSBG
            WHEN 1 THEN 'Yes'
            WHEN 0 THEN 'No'
        END) AS vUSBG,
       concat(vFirstname,' ',vLastname) AS Name,
       vEmail,
       eType,
       eStatus,
       tAddedDate,
       eExpert,
       eAdmin,

  (SELECT count(iUserID) AS total
   FROM tbl_friend
   WHERE iUserID = tbl_user.iUserID) AS count_f,

  (SELECT COUNT(*)
   FROM bar_followers
   WHERE bar_followers.iUserID = tbl_user.iUserID) AS bar_follows,

  (SELECT COUNT(b.iBrandID)
   FROM tbl_company_follow,
        tbl_brand b
   WHERE tbl_company_follow.iUserID = tbl_user.iUserID
     AND b.iCompanyID = tbl_company_follow.iCompanyID) AS brand_follows,

  (SELECT sum(points) AS totalpoints
   FROM tbl_points,
        tbl_post p
   WHERE iUserID = tbl_user.iUserID
     AND p.iPostID = tbl_points.post_id) AS countPoints
FROM tbl_user

此查询采用了8.3595 seconds

如何最大限度地缩短时间?

2 个答案:

答案 0 :(得分:3)

您的查询是合理的,除了缺少明确的join语法。

检查以确保您拥有以下索引:

  • tbl_friend(iUserId)
  • bar_followers(iUserID)
  • tbl_company_follow(iUserID, iCompanyID)
  • tbl_brand(iCompanyID)
  • tbl_post(iUserID, iPostID)
  • tbl_points(post_id, points)

但是,根据数据的大小,8-9秒可能是合理的。

答案 1 :(得分:1)

如果不知道您的桌子大小,很难判断十分之一秒的查询时间是否合理。它可能接近你能做到的最好。

话虽这么说,您可以重构此查询以使用LEFT JOIN操作代替您的从属子查询。这将是这样的大纲。

SELECT tu.field, tu.field, ...
       a.count_f,
       b.bar_follows,
       ...
  FROM tbl_user tu
  LEFT JOIN (
              SELECT count(*) AS count_f, iUserID
                FROM tbl_friend
               GROUP BY iUserID
       ) a ON tu.iUserID = a.iUserId
  LEFT JOIN (
              SELECT count(*) AS bar_follows, iUserID
               FROM bar_followers
              GROUP BY iUserId
       ) b ON tu.iUserID = b.iUserId
 ...

这里有两件相关的事情。首先,每个COUNT()项都是COUNT(*)。这允许在不查看每行的内容的情况下满足查询。

其次,列列表中的从属子查询将替换为子查询,从而计算出所需的聚合数据。这可能会有所帮助,因为查询规划器只能执行一次每个子查询。

戈登关于指数的权利。