改进计数和连接多个表的查询

时间:2013-09-02 08:31:14

标签: mysql sql join count

我的(简化)数据库架构: Image

每个操作都有一组主机名,可以生成错误。每个主机名都从域列表中接受,每个域都与组织相关联(通过接受阶段)。

我希望得到一个结果集:

+----+--------------------+--------------+----------------+--------------+
| id | organization_count | domain_count | hostname_count | errors_count |
+----+--------------------+--------------+----------------+--------------+
| 79 |                  1 |            1 |              4 |            4 |
| 78 |                  1 |            4 |             16 |         NULL |
| 77 |                  1 |            4 |             16 |           16 |
| 76 |                  1 |            4 |             16 |         NULL |
+----+--------------------+--------------+----------------+--------------+

我的查询是:

SELECT operation.id,
       tally_o.organization_count,
       tally_d.domain_count,
       tally_h.hostname_count,
       tally_h.errors_count
FROM   operation
       LEFT JOIN (SELECT hostname_operation.operation_id,
                         COUNT(*) AS hostname_count,
                         errors.errors_count
                  FROM   hostname_operation
                         LEFT JOIN (SELECT operation_id,
                                           COUNT(*) AS errors_count
                                    FROM   hostname_operation
                                    WHERE  error_id IS NOT NULL
                                    GROUP  BY operation_id) AS errors
                                ON hostname_operation.operation_id =
                                   errors.operation_id
                  GROUP  BY operation_id) AS tally_h
              ON operation.id = tally_h.operation_id
       LEFT JOIN (SELECT hostname_operation.operation_id,
                         COUNT(DISTINCT domain.id) AS domain_count
                  FROM   domain
                         JOIN accepted
                           ON domain.id = accepted.domain_id
                         JOIN hostname
                           ON accepted.id = hostname.accepted_id
                         JOIN hostname_operation
                           ON hostname.id = hostname_operation.hostname_id
                  GROUP  BY hostname_operation.operation_id) AS tally_d
              ON operation.id = tally_d.operation_id
       LEFT JOIN (SELECT hostname_operation.operation_id,
                         COUNT(DISTINCT organization.id) AS organization_count
                  FROM   organization
                         JOIN accepted
                           ON organization.id = accepted.organization_id
                         JOIN hostname
                           ON accepted.id = hostname.accepted_id
                         JOIN hostname_operation
                           ON hostname.id = hostname_operation.hostname_id
                  GROUP  BY hostname_operation.operation_id) AS tally_o
              ON operation.id = tally_o.operation_id
ORDER  BY operation.id DESC
LIMIT  0, 4;

我正在使用MySQL 5.5。即使查询很快(~0.4s),问题在于EXPLAIN显示每个...LEFT JOIN (SELECT...数据库没有使用任何索引。另外像mysqltuner这样的软件显示我在没有索引的情况下进行了很多查询。

如何改进查询? SUM + GROUP BY可能是一种方式吗?

1 个答案:

答案 0 :(得分:1)

好消息是,您的查询可以在没有子查询的情况下重写,只使用3个左连接和单个分组。

<强>编辑:

select o.id,
  count(distinct a.organization_id) organization_count,
  count(distinct a.domain_id) domain_count,
  count(ho.hostname_id) hostname_count,
  count(ho.error_id) errors_count
from operation o 
  left outer join hostname_operation ho on o.id=ho.operation_id
  left join hostname h on h.id=ho.hostname_id
  left join accepted a on a.id=h.accepted_id
group by o.id
order by o.id

您没有提供有关数据库中索引的信息,因此无法得出有关索引使用情况的结论。我只能建议,如果数据库具有适用于所有主键和外键的索引 - 它足以有效执行上面给出的查询。

相关问题