我的(简化)数据库架构:
每个操作都有一组主机名,可以生成错误。每个主机名都从域列表中接受,每个域都与组织相关联(通过接受阶段)。
我希望得到一个结果集:
+----+--------------------+--------------+----------------+--------------+
| 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
可能是一种方式吗?
答案 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
您没有提供有关数据库中索引的信息,因此无法得出有关索引使用情况的结论。我只能建议,如果数据库具有适用于所有主键和外键的索引 - 它足以有效执行上面给出的查询。