加入vs子查询来计算嵌套对象

时间:2016-07-04 14:55:15

标签: mysql sql join subquery

假设我的模型包含2个表:人员和地址。一个人可以拥有O,1个或更多地址。我正在尝试执行一个列出所有人的查询,并分别包含他们拥有的地址数。以下是我必须实现的2个查询:

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`

我想知道一个人在表现方面是否优于另一个。

2 个答案:

答案 0 :(得分:0)

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

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

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

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

答案 1 :(得分:0)

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

mysql表存储结构是索引组织表(clustered index),因此主键索引比连接操作中的普通索引快得多。