当数据以GB / TB为单位时,我的查询是否会成为性能的瓶颈

时间:2015-08-10 13:45:52

标签: mysql sql query-optimization

您好,在我们的应用中,我们必须在一个长查询中为分析页面i查询数据库的所有详细信息提供分析。

  

这是我的查询,我删除了一些字段,因为内容超出了描述限制。在我的查询中,它充满了子查询。这里将   在select语句中超过20-30个子查询。这是对的   像这样创建查询。或者我使用它的一些替代品。是的数据   将会日益增加。

     

这样的选择语句中的子查询是否正确[以此数量]?

我的查询[更新于2015年8月13日]

SELECT COUNT(users.user_id),
   cards.card_id,
   GROUP_CONCAT(users.user_id),
   GROUP_CONCAT(redeem_code.redeem_id),
   CASE
      WHEN cards.what_to_broadcast = "0"
      THEN
         "Information Card"
      WHEN cards.what_to_broadcast = "1"
      THEN
         "Rating Card"
      WHEN cards.what_to_broadcast = "2"
      THEN
         CASE
            WHEN cards.discount_type = "2"
            THEN
               "Price Cut Discount Card"
            WHEN cards.discount_type = "1"
            THEN
               "Buy X Get Y Discount Card"
            WHEN cards.discount_type = "0"
            THEN
               "Fixed Discount Card"
            ELSE
               "Fixed Discount Card"
         END
      WHEN cards.what_to_broadcast = "4"
      THEN
         CASE
            WHEN cards.question_type = "1"
            THEN
               "Multiple Choice Question Card"
            WHEN cards.question_type = "2"
            THEN
               "Single Choice Question Card"
            WHEN cards.question_type = "3"
            THEN
               "Discriptive Question Card"
            ELSE
               "Multiple Choice Question Card"
         END
      ELSE
         "Information Card x"
   END
      AS cardType,
   cards.name AS cardTitle,
   cards.what_to_broadcast,
   cards.card_id,
   COUNT(saved_card.saved_card_id) AS cardReach,
   COUNT(DISTINCT saved_card.redeem_id) AS cardReachCoupons,
   SUM((CASE WHEN saved_card.status = "1" THEN 1 ELSE 0 END))
      AS sumOfSavedCard,
   SUM((CASE WHEN users.gender = "1" THEN 1 ELSE 0 END)) AS maleRecipient,
   SUM((CASE WHEN users.gender = "2" THEN 1 ELSE 0 END))
      AS femaleRecipient,
   SUM(
      (CASE
          WHEN saved_card.status = "1"
          THEN
             CASE WHEN users.gender = "1" THEN 1 ELSE 0 END
          ELSE
             0
       END))
      AS sumOfSavedCardMaleRecipient,
   SUM(
      (CASE
          WHEN saved_card.status = "1"
          THEN
             CASE WHEN users.gender = "2" THEN 1 ELSE 0 END
          ELSE
             0
       END))
      AS sumOfSavedCardFemaleRecipient,
   IFNULL(
      (SELECT COUNT(*)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.is_like = "1"
              AND rating_like.card_id = cards.card_id),
      0)
      AS likers,
   IFNULL(
      (SELECT COUNT(*)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.is_like = "1"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS maleLikersMain,
   IFNULL(
      (SELECT COUNT(*)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.is_like = "1"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS femaleLikersMain,
   IFNULL(
      (SELECT COUNT(*)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.see_extra_info = "1"
              AND rating_like.card_id = cards.card_id),
      0)
      AS seenExtraInfo,
   IFNULL(
      (SELECT COUNT(*)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.see_extra_info = "1"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS maleSeenExtraInfo,
   IFNULL(
      (SELECT COUNT(*)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.see_extra_info = "1"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS femaleSeenExtraInfo,
   IFNULL(
      (SELECT SUM(card_share.count) AS card_share
         FROM card_share
              INNER JOIN users ON card_share.user_id = users.user_id
        WHERE     users.status = "1"
              AND card_share.status = "1"
              AND card_share.card_id = cards.card_id),
      0)
      AS card_share_main,
   IFNULL(
      (SELECT SUM(card_share.count) AS card_share
         FROM card_share
              INNER JOIN users ON card_share.user_id = users.user_id
        WHERE     users.status = "1"
              AND card_share.status = "1"
              AND card_share.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS card_share_by_male,
   IFNULL(
      (SELECT SUM(card_share.count) AS card_share
         FROM card_share
              INNER JOIN users ON card_share.user_id = users.user_id
        WHERE     users.status = "1"
              AND card_share.status = "1"
              AND card_share.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS card_share_by_female,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "1"
              AND rating_like.card_id = cards.card_id),
      0)
      AS rate1,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "1"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS rate1_by_male,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "1"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS rate1_by_female,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "2"
              AND rating_like.card_id = cards.card_id),
      0)
      AS rate2,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "2"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS rate2_by_male,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "2"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS rate2_by_female,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "3"
              AND rating_like.card_id = cards.card_id),
      0)
      AS rate3,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "3"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS rate3_by_male,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "3"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS rate3_by_female,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "4"
              AND rating_like.card_id = cards.card_id),
      0)
      AS rate4,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "4"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS rate4_by_male,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "4"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS rate4_by_female,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "5"
              AND rating_like.card_id = cards.card_id),
      0)
      AS rate5,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "5"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "1"),
      0)
      AS rate5_by_male,
   IFNULL(
      (SELECT COUNT(rating_like.rating_like_id)
         FROM rating_like
              INNER JOIN users ON rating_like.user_id = users.user_id
        WHERE     users.status = "1"
              AND rating_like.status = "1"
              AND rating_like.has_rated = "1"
              AND rating_like.rate = "5"
              AND rating_like.card_id = cards.card_id
              AND users.gender = "2"),
      0)
      AS rate5_by_female,
   IFNULL(
      (SELECT COUNT(redeem_code.redeem_id)
         FROM redeem_code
        WHERE     redeem_code.card_id = cards.card_id
              AND redeem_code.status = "1"),
      0)
      AS totalCoupons,
   IFNULL(
      (SELECT COUNT(DISTINCT redeem_code.redeem_id)
         FROM redeem_code
              INNER JOIN saved_card
                 ON saved_card.redeem_id = redeem_code.redeem_id
        WHERE     redeem_code.card_id = cards.card_id
              AND redeem_code.status = "1"
              AND redeem_code.used_coupon = "2"),
      0)
      AS totalRedeemCoupons,
   IFNULL(
      (SELECT COUNT(DISTINCT redeem_code.redeem_id)
         FROM redeem_code
              INNER JOIN saved_card
                 ON saved_card.redeem_id = redeem_code.redeem_id
              INNER JOIN users ON saved_card.user_id = users.user_id
        WHERE     redeem_code.card_id = cards.card_id
              AND redeem_code.status = "1"
              AND redeem_code.used_coupon = "2"
              AND users.user_id = "1"),
      0)
      AS maleRedeemCoupons,
   IFNULL(
      (SELECT COUNT(DISTINCT redeem_code.redeem_id)
         FROM redeem_code
              INNER JOIN saved_card
                 ON saved_card.redeem_id = redeem_code.redeem_id
              INNER JOIN users ON saved_card.user_id = users.user_id
        WHERE     redeem_code.card_id = cards.card_id
              AND redeem_code.status = "1"
              AND redeem_code.used_coupon = "2"
              AND users.user_id = "2"),
      0)
      AS femaleRedeemCoupons,
   (SELECT GROUP_CONCAT(options, "/~", cNum)
      FROM (SELECT GROUP_CONCAT(
                      DISTINCT COALESCE(card_question_options.value, ""))
                      AS options,
                   SUM(
                      CASE
                         WHEN saved_card_feedbacks.card_question_option_id =
                                 card_question_options.card_question_option_id
                         THEN
                            1
                         ELSE
                            0
                      END)
                      AS cNum,
                   c2.card_id
              FROM card_question_options
                   INNER JOIN cards c2
                      ON c2.card_id = card_question_options.card_id
                   INNER JOIN saved_card
                      ON     c2.card_id = saved_card.card_id
                         AND saved_card.status IN ("1", "2")
                   LEFT JOIN saved_card_feedbacks
                      ON     saved_card_feedbacks.saved_card_id =
                                saved_card.saved_card_id
                         AND saved_card_feedbacks.status = "1"
                   INNER JOIN users
                      ON     saved_card.user_id = users.user_id
                         AND users.status = "1"
             WHERE 1  AND card_question_options.status = "1"
            GROUP BY card_question_options.card_question_option_id)
           AS table1
     WHERE table1.card_id = cards.card_id)
      AS cardOptionsMain,
   (SELECT GROUP_CONCAT(options, "/~", cNum)
      FROM (SELECT GROUP_CONCAT(
                      DISTINCT COALESCE(card_question_options.value, ""))
                      AS options,
                   SUM(
                      CASE
                         WHEN saved_card_feedbacks.card_question_option_id =
                                 card_question_options.card_question_option_id
                         THEN
                            1
                         ELSE
                            0
                      END)
                      AS cNum,
                   c2.card_id
              FROM card_question_options
                   INNER JOIN cards c2
                      ON c2.card_id = card_question_options.card_id
                   INNER JOIN saved_card
                      ON     c2.card_id = saved_card.card_id
                         AND saved_card.status IN ("1", "2")
                   LEFT JOIN saved_card_feedbacks
                      ON     saved_card_feedbacks.saved_card_id =
                                saved_card.saved_card_id
                         AND saved_card_feedbacks.status = "1"
                   INNER JOIN users
                      ON     saved_card.user_id = users.user_id
                         AND users.status = "1"
                         AND users.gender = "1"
             WHERE 1  AND card_question_options.status = "1"
            GROUP BY card_question_options.card_question_option_id)
           AS table1
     WHERE table1.card_id = cards.card_id)
      AS cardOptionsMainMale,
   (SELECT GROUP_CONCAT(options, "/~", cNum)
      FROM (SELECT GROUP_CONCAT(
                      DISTINCT COALESCE(card_question_options.value, ""))
                      AS options,
                   SUM(
                      CASE
                         WHEN saved_card_feedbacks.card_question_option_id =
                                 card_question_options.card_question_option_id
                         THEN
                            1
                         ELSE
                            0
                      END)
                      AS cNum,
                   c2.card_id
              FROM card_question_options
                   INNER JOIN cards c2
                      ON c2.card_id = card_question_options.card_id
                   INNER JOIN saved_card
                      ON     c2.card_id = saved_card.card_id
                         AND saved_card.status IN ("1", "2")
                   LEFT JOIN saved_card_feedbacks
                      ON     saved_card_feedbacks.saved_card_id =
                                saved_card.saved_card_id
                         AND saved_card_feedbacks.status = "1"
                   INNER JOIN users
                      ON     saved_card.user_id = users.user_id
                         AND users.status = "1"
                         AND users.gender = "2"
             WHERE 1   AND card_question_options.status = "1"
            GROUP BY card_question_options.card_question_option_id)
           AS table1
     WHERE table1.card_id = cards.card_id)
      AS cardOptionsMainFemale
  FROM cards
   INNER JOIN campaigns ON cards.camapign_id = campaigns.campaign_id
   INNER JOIN saved_card ON saved_card.card_id = cards.card_id
   INNER JOIN users ON saved_card.user_id = users.user_id
   LEFT JOIN redeem_code ON saved_card.redeem_id = redeem_code.redeem_id
WHERE     cards.status = "1"
   AND users.status = "1"
   AND saved_card.status IN ("1", "2")
   AND campaigns.campaign_id = :campaign_id
GROUP BY cards.card_id

在此查询中,我会检索一个广告系列中所有卡片的数据。

  1. 广告系列将有20-30张卡片。 [卡表]
  2. 每张卡片将分发给用户[没有限制。它将在活动到期日结束。] [saved_card表将与用户表相关]
  3. 卡可能有兑换代码..因此它也可以是1到N.可以使用卡附加500-1000或任意数量的redeem_coupons。 [reddem_code表,与saved_card表相关,将与用户表相关]
  4. 我正在从其他表中检索将save_card_id作为外键或card_id和user_id作为外键的数据。

2 个答案:

答案 0 :(得分:1)

假设这将在每次执行时返回大约20-30行,并且大部分时间将花费在子查询中,我预测您将会有不一致且令人失望的响应时间,因为

答案 1 :(得分:1)

这里有很多不必要的开支

考虑

(SELECT SUM((CASE WHEN users.gender = "2" THEN 1 ELSE 0 END) AS femaleSeenExtraInfoInner
   FROM rating_like
   JOIN users
     ON rating_like.user_id = users.user_id
  WHERE users.status = "1"
    AND rating_like.status = "1"
    AND rating_like.see_extra_info = "1"
    AND rating_like.card_id = cards.card_id
  GROUP BY rating_like.card_id)
 IS NULL

为什么所有的工作都要测试null? 减少工作量的结果相同

(SELECT top 1 users.gender AS femaleSeenExtraInfoInner
       FROM rating_like
       JOIN users
         ON rating_like.user_id = users.user_id
        AND users.status = "1"
        AND rating_like.status = "1"
        AND rating_like.see_extra_info = "1"
        AND rating_like.card_id = cards.card_id)
     IS NULL

即使您确实需要计数

SELECT SUM((CASE WHEN users.gender = "2" THEN 1 ELSE 0 END) AS femaleSeenExtraInfoInner
       FROM rating_like
       JOIN users
         ON rating_like.user_id = users.user_id
      WHERE users.status = "1"
        AND rating_like.status = "1"
        AND rating_like.see_extra_info = "1"
        AND rating_like.card_id = cards.card_id
      GROUP BY rating_like.card_id  

为什么按rating_like.card_id进行分组?您正在加入一张cards.card_id。

SELECT count(*) AS femaleSeenExtraInfoInner
       FROM rating_like
       JOIN users
         ON rating_like.user_id = users.user_id 
        AND rating_like.card_id = cards.card_id
        AND users.status = "1"
        AND rating_like.status = "1"
        AND rating_like.see_extra_info = "1"
        AND users.gender = "2"

或者只需使用

使其更简单
with cte_femaleSeenExtraInfoInner (card_id, count)
as 
(
  SELECT users.card_id, count(*) AS count
    FROM rating_like
    JOIN users
      ON rating_like.user_id = users.user_id 
     AND users.status = "1"
     AND rating_like.status = "1"
     AND rating_like.see_extra_info = "1"
     AND users.gender = "2"
   group by users.card_id
)
select distinct 
       cards.user_id, isnull(cte_femaleSeenExtraInfoInner.count, 0)
  FROM cards 
  left join cte_femaleSeenExtraInfoInner 
    on cte_femaleSeenExtraInfoInner.user_id = cards.user_id 
   ....

你甚至可以用

加倍性别
SELECT users.card_id, users.gender, count(*) AS count
  FROM rating_like
  JOIN users
    ON rating_like.user_id = users.user_id 
   AND users.status = "1"
   AND rating_like.status = "1"
   AND rating_like.see_extra_info = "1"
   AND users.gender = in ("1", "2")
 group by users.card_id, users.gender

更好地将cte实现为#temp,因此不会多次评估