2016-07-04 42 views
0

假设我的模型包含2个表格:个人和地址。一个人可以有O个,一个或多个地址。我试图执行一个查询,列出所有人,并包括他们分别拥有的地址数量。这里是2个查询,我要做到这一点:加入vs子查询来计算嵌套对象

SELECT 
    persons.*, 
    count(addresses.id) AS number_of_addresses 
FROM `persons` 
    LEFT JOIN addresses ON persons.id = addresses.person_id 
GROUP BY persons.id 

SELECT 
    persons.*, 
    (SELECT COUNT(*) 
    FROM addresses 
    WHERE addresses.person_id = persons.id) AS number_of_addresses 
FROM `persons` 

,我想知道,如果一个比其他在性能方面更好。

+0

这是什么'cube_models'表,为什么它只出现在第二个查询中?第二个查询使用相关的子查询,它通常倾向于比使用联接的类似查询慢。 –

+1

我相信第一个会更快,但它们非常相似。只需在两者上运行执行计划并查看差异。我怀疑有没有更好的办法。 – sagi

+0

我修复了cube_models,坏的复制/粘贴 – TrexXx

回答

0

确定性能特征的方法是实际运行查询并查看哪个更好。

如果你没有索引,那么第一个可能会更好。如果你有addresses(person_id)的索引,那么第二个可能会更好。

原因有点复杂。基本原因是group by(在MySQL中)使用排序。而且,排序是复杂度为O(n * log(n))。所以,进行排序的时间比数据增长得快(速度并不快,但有点快)。结果是,每个人的一堆聚合比一个人聚合的速度快于所有数据。

这是概念。事实上,MySQL将使用相关子查询的索引,所以它通常比不使用索引的整体group by更快。

0

我认为第一个查询是最优的,更多的优化可以通过改变表结构来提供。例如,将地址表中的主键定义为person_id和address_id字段(顺序很重要),以加快加入速度。

mysql表存储结构是索引组织表(聚集索引),所以主键索引在联接操作中特别快于正常索引。

+0

'persons.id','addresses.id'和'addresses.person_id'都有索引 – TrexXx

+0

@TrexXx,mysql表存储结构被索引组织表(clustered),因此主关键指标特别在连接操作中比正常指标快很多。 –