Mysql 对两个联接表的求和进行的大多数性能明智的查询

Mysql 对两个联接表的求和进行的大多数性能明智的查询,mysql,sql,join,subquery,left-join,Mysql,Sql,Join,Subquery,Left Join,我有三张桌子: 顾客 服务类型1 服务类型2 我想列出这些值:名称、服务类型1–总价、服务类型2–总价 我创建了两个查询,它们满足我的要求: A: B: 我对它们进行了基准测试,它们的执行时间是相同的*。是否可以编写更多性能方面的查询 *这不是真的。每个表中有30k+记录时,A的速度要快得多 我可能认为,如果使用适当的索引,这个版本会更好: SELECT u.name, (SELECT SUM(st.price) FROM service_type1 st

我有三张桌子:

顾客

服务类型1

服务类型2

我想列出这些值:名称、服务类型1–总价、服务类型2–总价

我创建了两个查询,它们满足我的要求:

A:

B:

我对它们进行了基准测试,它们的执行时间是相同的*。是否可以编写更多性能方面的查询


*这不是真的。每个表中有30k+记录时,A的速度要快得多

我可能认为,如果使用适当的索引,这个版本会更好:

SELECT u.name,
       (SELECT SUM(st.price)
        FROM service_type1 st
        WHERE st.customer_id = u.id
       ) as sum_service_type1,
       (SELECT SUM(price)
        FROM service_type2 st
        WHERE st.customer_id = u.id
       ) as sum_price  
FROM customer u
ORDER BY u.id;

最好的索引是customerid、名称、服务类型1客户id、价格和服务类型2客户id、价格。

如果我理解正确,请尝试以下方法:

选择id、sum\u service\u type1 进入T1 从服务类型1 按客户id分组

选择id、sum\u service\u type2 进入T2 从服务类型2 按客户id分组

挑选 名称 总服务类型1, 总服务类型2, 来自客户u a.id=u.id上的左连接T1 a b.id=u.id上的左连接T2 b


为了提高性能,您可以创建聚集索引

如何运行这两个查询,并在客户端使用合并排序将两个结果集合并为一个。它们已按u.id排序,因此我们可以轻松合并

SELECT
    name,
    SUM(price) AS sum_service_type1,
FROM customer u
    LEFT JOIN service_type1 a ON a.customer_id = u.id
GROUP BY u.id
ORDER BY u.id;

SELECT
    name,
    SUM(price) AS sum_service_type2,
FROM customer u
    LEFT JOIN service_type2 a ON a.customer_id = u.id
GROUP BY u.id
ORDER BY u.id;

我认为,如果两个查询的执行时间之和小于您的查询,则可以在客户端实现。

这是我的第一次尝试,我尝试了两个从两个相关子查询中避免的查询。顺便说一句,这三种解决方案在性能上非常接近。@igeomon这并没有避免两个子查询,但它确实避免了左联接,从长远来看,左联接应该会对某些问题有所帮助。@GordonLinoff您可能想说的是服务\u type1customer\u id,第二个索引建议的价格?:@JamieD77当我写这个解决方案时,也是我第一次尝试,我的A和B版本在性能上非常接近。@JamieD77我在每个表中测试了30k+记录,这个查询和A查询具有相同的性能,但是B在这个较大的记录集上要慢得多。不幸的是,如果两个服务类型的表都有2条记录,那么B的总和将是它应该的两倍。。我认为这是错误的,因为两个连接将行相乘,并创建错误的和值。我非常适合一个联接表。你是对的,但是纯sql解决方案是,这对我来说真的很有趣。@igeomon我想知道你是否在使用旧版本的MySQL。在MySQL 5.5中,我目前使用的是依赖子查询,在您的情况下,它比子查询慢。此外,MySQL5.6还有一个我还没有测试过的物化特性,我希望这对您有所帮助。
id
customer_id 
price (one to many relation to the customer)
SELECT
    name,
    SUM(price) AS sum_price,
    (SELECT SUM(price)
        FROM service_type2
        WHERE customer_id = u.id
    ) AS sum_price2 
FROM customer u
LEFT JOIN service_type1 a ON a.customer_id = u.id
GROUP BY u.id
ORDER BY u.id
SELECT
    name,
    SUM(price) AS sum_price,
    p.sum_price AS sum_price2
FROM customer u
LEFT JOIN service_type1 a ON a.customer_id = u.id
LEFT JOIN
(
    SELECT SUM(price) AS sum_price, customer_id
    FROM service_type2
    GROUP BY customer_id
) p ON p.customer_id = u.id
GROUP BY u.id
ORDER BY u.id
SELECT u.name,
       (SELECT SUM(st.price)
        FROM service_type1 st
        WHERE st.customer_id = u.id
       ) as sum_service_type1,
       (SELECT SUM(price)
        FROM service_type2 st
        WHERE st.customer_id = u.id
       ) as sum_price  
FROM customer u
ORDER BY u.id;
SELECT
    name,
    SUM(price) AS sum_service_type1,
FROM customer u
    LEFT JOIN service_type1 a ON a.customer_id = u.id
GROUP BY u.id
ORDER BY u.id;

SELECT
    name,
    SUM(price) AS sum_service_type2,
FROM customer u
    LEFT JOIN service_type2 a ON a.customer_id = u.id
GROUP BY u.id
ORDER BY u.id;