【问题标题】:Mysql query optimization takes more than 30 secMysql查询优化耗时30多秒
【发布时间】:2015-02-14 21:07:43
【问题描述】:

嗨朋友们可以请任何人帮我优化这个查询,它需要30多秒。 任何建议都热烈欢迎。

查询:

SELECT 
    CONCAT(CCD.CONTACT_FIRST_NAME, ' ', CCD.CONTACT_LAST_NAME) AS NAME,
    A.EMAIL_IDS,
    CCD.UNSUBSCRIBE,
    IFNULL(CSL.LOG_DATE, '') AS LOG_DATE,
    CSL.IP_ADDRESS,
    IF(CSL.BROWSER IS NULL, '', CSL.BROWSER) AS BROWSER,
    (CASE
        WHEN (UNSUBSCRIBE = 0 OR UNSUBSCRIBE IS NULL) THEN 'Opted In'
        ELSE (CASE
            WHEN (UNSUBSCRIBE = 1) THEN 'Opted Out'
            ELSE (CASE
                WHEN
                    ((UNSUBSCRIBE = 2 OR UNSUBSCRIBE = 3)
                        AND CCD.CONTACT_ID NOT IN (SELECT 
                            CONTACT_ID
                        FROM
                            CM_SUBSCRIPTION_MAIL_DATA
                        WHERE
                            IS_MAIL_SENT = 'Y'))
                THEN
                    'Opt-In Request not Sent'
                ELSE 'Opt-In Pending'
            END)
        END)
    END) AS CURR_SUB,
    (CASE
        WHEN (SUBSCRIBE_FROM = 0) THEN 'Opted In'
        ELSE (CASE
            WHEN (SUBSCRIBE_FROM = 1) THEN 'Opted Out'
            ELSE (CASE
                WHEN (SUBSCRIBE_FROM = 2 OR SUBSCRIBE_FROM = 3) THEN 'Opt-In Pending'
                ELSE ''
            END)
        END)
    END) AS SUB_FROM,
    SUBSCRIBE_FROM,
    (CASE
        WHEN (SUBSCRIBE_TO = 0) THEN 'Opted In'
        ELSE (CASE
            WHEN (SUBSCRIBE_TO = 1) THEN 'Opted Out'
            ELSE (CASE
                WHEN (SUBSCRIBE_TO = 2 OR SUBSCRIBE_TO = 3) THEN 'Opt-In Pending'
                ELSE ''
            END)
        END)
    END) AS SUB_TO,
    SUBSCRIBE_TO
FROM
    CM_CONTACT_DETAILS CCD
        LEFT JOIN
    ADDRESS A ON CCD.CONTACT_ID = A.FOREIGN_ID
        LEFT JOIN
    CM_SUBSCRIPTION_LOGS CSL ON CSL.CONTACT_ID = CCD.CONTACT_ID
WHERE
    1 = 1
GROUP BY CSL.LOG_DATE , CCD.CONTACT_ID
ORDER BY NAME DESC , LOG_DATE DESC
LIMIT 0 , 20

【问题讨论】:

    标签: mysql query-optimization


    【解决方案1】:

    您的案例/何时可以简化,但我相信您查询的杀手是未发送您的选择加入请求的相关 NOT IN SELECT 子句。

    我已将您的查询更改为根据联系人和“Y”的邮寄状态对您的邮寄表进行左连接。因此,这简化了您的案例,只需检查邮件表联系人 ID 的 IS NULL。

    您不能在性能方面做太多事情,因为您的 Group by 是由不同表中的列组成的,不会利用任何索引优化,那么所有按名称排序的东西都会使它成为一个问题......但是每次对左连接执行的每个字段的相关子查询应该有帮助。

    SELECT 
          CONCAT(CCD.CONTACT_FIRST_NAME, ' ', CCD.CONTACT_LAST_NAME) AS NAME,
          A.EMAIL_IDS,
          CCD.UNSUBSCRIBE,
          IFNULL(CSL.LOG_DATE, '') AS LOG_DATE,
          CSL.IP_ADDRESS,
          IF(CSL.BROWSER IS NULL, '', CSL.BROWSER) AS BROWSER,
          CASE WHEN UNSUBSCRIBE = 0 OR UNSUBSCRIBE IS NULL THEN 'Opted In'
               WHEN UNSUBSCRIBE = 1 THEN 'Opted Out'
               WHEN UNSUBSCRIBE IN (2,3) AND SMD.CONTACT_ID IS NULL THEN 'Opt-In Request not Sent'
               ELSE 'Opt-In Pending' END AS CURR_SUB,
          CASE WHEN SUBSCRIBE_FROM = 0 THEN 'Opted In'
               WHEN SUBSCRIBE_FROM = 1 THEN 'Opted Out'
               WHEN SUBSCRIBE_FROM = 2 OR SUBSCRIBE_FROM = 3 THEN 'Opt-In Pending'
               ELSE '' END AS SUB_FROM,
          SUBSCRIBE_FROM,
          CASE WHEN SUBSCRIBE_TO = 0 THEN 'Opted In'
               WHEN SUBSCRIBE_TO = 1 THEN 'Opted Out'
               WHEN SUBSCRIBE_TO = 2 OR SUBSCRIBE_TO = 3 THEN 'Opt-In Pending'
               ELSE '' END AS SUB_TO,
          SUBSCRIBE_TO
       FROM
          CM_CONTACT_DETAILS CCD
             LEFT JOIN ADDRESS A 
                ON CCD.CONTACT_ID = A.FOREIGN_ID
             LEFT JOIN CM_SUBSCRIPTION_LOGS CSL 
                ON CSL.CONTACT_ID = CCD.CONTACT_ID
             LEFT JOIN CM_SUBSCRIPTION_MAIL_DATA SMD
                ON CCD.CONTACT_ID = SMD.CONTACT_ID
                AND IS_MAIL_SENT = 'Y'
       WHERE
          1 = 1
       GROUP BY 
          CSL.LOG_DATE, 
          CCD.CONTACT_ID
       ORDER BY 
          NAME DESC, 
          LOG_DATE DESC
       LIMIT 
          0, 20
    

    【讨论】:

    • 感谢您的宝贵时间,但到目前为止需要 21 秒,请提供其他建议。
    • @susantomahato,没有更详细的表、索引以及 group by、order by 和 limit 的原因,不多...限制 FORCES ALL 记录在 20 限制之前返回和排序可以考虑,因此它必须处理所有行。
    猜你喜欢
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多