首页 > 解决方案 > 优化查询的技巧,在 MySQL 中有很多子查询

问题描述

我有大约 6 个表,我必须根据匹配的 site_ids 和日期对字段进行计数或求和。我有以下查询,其中有许多子查询需要花费大量时间才能运行。我确信有一种更简单、更有效的方法,但是我对这些更复杂的查询相当陌生。我已经阅读了有关优化的内容,特别是使用连接 ON 但难以理解和实施。

目标是加快速度,而不是在运行时让我的小型服务器瘫痪。非常感谢任何帮助或指导!

SELECT date(date_added) as dt_date,
       site_id as dt_site_id,
       (SELECT site_id from branch_mappings bm WHERE mark_id_site = dt.site_id) as site_id,
       (SELECT parent_id from branch_mappings bm WHERE mark_id_site = dt.site_id) as main_site_id,
       (SELECT corp_owned from branch_mappings bm WHERE mark_id_site = dt.site_id) as corp_owned,
       count(id) as dt_calls,
       (SELECT count(date_submitted) FROM mark_unbounce ub WHERE date(date_submitted) = dt_date AND ub.site_id = dt.site_id) as ub,
       (SELECT count(timestamp) FROM mark_wordpress_contact wp WHERE date(timestamp) = dt_date AND wp.site_id = dt.site_id) as wp,
       (SELECT count(added_on) FROM m_shrednations sn WHERE date(added_on) = dt_date AND sn.description = dt.site_id) as sn,
       (SELECT sum(users) FROM mark_ga ga WHERE date(ga.date) = dt_date AND channel LIKE 'Organic%' AND ga.site_id = dt.site_id) as ga_organic
FROM mark_dialogtech dt
WHERE site_id is not null
GROUP BY site_name, dt_date
ORDER BY site_name, dt_date;

标签: mysql

解决方案


您所做的相当于要求您的服务器在每次运行此查询时查询 7+ 个不同的表。就个人而言,我使用联接和嵌套查询,因为我可以减少做我需要的事情。

前 3 个子查询可以替换为...

SELECT date(date_added) as dt_date,
    dt.site_id as dt_site_id,
    bm.site_id as site_id,
    bm.parent_id as main_site_id,
    bm.corp_owned as corp_owned,
    
    
    FROM mark_dialogtech dt
        INNER JOIN branch_mappings bm
            ON bm.mark_id_site = dt.site_id

我不确定您为什么要运行最后 3 个。是否有业务需求?如果是这样,请考虑运行频率和时间。

如果绝对必要,请将它们添加到连接中,例如...

FROM mark_dialogtech dt
    INNER JOIN 
        (SELECT site_id, count(date_submitted) FROM mark_unbounce GROUP BY site_id) ub
            on ub.site_id = dt.site_id

这应该将结果限制为仅在 mark_dialogtech 和 mark_unbounce(或任何表)中存在 site_id 的记录。根据我的经验,这种方法加快了速度。

不过,我担心的是您正在执行的聚合数量。如果可以将它们缓存到仪表板并在缓慢的时间内拉出,那将是最好的。


推荐阅读