【发布时间】:2012-10-19 02:20:09
【问题描述】:
我有几个查询对我数据库中当前的数据运行非常缓慢(几分钟),我想提高它们的性能。不幸的是,它们有点复杂,所以我通过谷歌获得的信息不足以让我弄清楚要添加哪些索引,或者我是否需要重写我的查询或什么......我希望有人能提供帮助。如果设置正确,我不认为它们应该这么慢。
第一个查询是:
SELECT i.name, i.id, COUNT(c.id)
FROM cert_certificates c
JOIN cert_histories h ON h.cert_certificate_id = c.id
LEFT OUTER JOIN inspectors i ON h.inspector_id = i.id
LEFT OUTER JOIN cert_histories h2
ON (h2.cert_certificate_id = c.id AND h.date_changed < h2.date_changed)
WHERE (h.cert_status_ref_id = ? OR h.cert_status_ref_id = ?)
AND h2.id IS NULL
GROUP BY i.id, i.name
ORDER BY i.name
第二个查询是:
SELECT l.letter, c.number
FROM cert_certificates c
JOIN cert_type_letter_refs l ON c.cert_type_letter_ref_id = l.id
JOIN cert_histories h ON h.cert_certificate_id = c.id
LEFT OUTER JOIN cert_histories h2
ON (h2.cert_certificate_id = c.id AND h.date_changed < h2.date_changed)
WHERE h.cert_status_ref_id = ?
AND h2.id IS NULL
AND h.inspector_id = ?
ORDER BY l.letter, c.number
cert_certificates 表与 cert_histories 表一样包含近 19k 条记录(尽管未来该表预计将增长到 cert_certificates 表大小的大约 2-3 倍)。其他的桌子都很小;每条记录少于 10 条。
目前唯一的索引是每个表的 id 和 cert_certificates.number。我在几个地方(例如here)阅读以添加外键索引,但在cert_histories 表的情况下,几乎所有列(cert_certificate_id、inspector_id、cert_status_ref_id)也是not advisable(根据该问题的一些答案,例如 Markus Winand 的),所以我有点迷路了。
任何帮助将不胜感激。
ETA:EXPLAIN 对第一个查询的结果是(对不起,可怕的格式;我使用的是 SQLyog,它在一个不错的表中显示它,但似乎 StackOverflow 不支持表?):
id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE h ALL NULL NULL NULL NULL 19740 使用 where;使用临时的;使用文件排序 1 简单我参考 index_inspectors_on_id index_inspectors_on_id 768 marketing_development.h.inspector_id 1 1 SIMPLE c ref index_cert_certificates_on_id index_cert_certificates_on_id 768 marketing_development.h.cert_certificate_id 91 在哪里使用;使用索引 1 SIMPLE h2 ALL NULL NULL NULL NULL 19740 使用where
第二次查询:
id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE h ALL NULL NULL NULL NULL 19795 使用 where;使用临时的;使用文件排序 1 SIMPLE c ref index_cert_certificates_on_id index_cert_certificates_on_id 768 marketing_development.h.cert_certificate_id 91 使用 where 1 SIMPLE l ALL index_cert_type_letter_refs_on_id NULL NULL NULL 5 使用 where;使用连接缓冲区 1 SIMPLE h2 ALL NULL NULL NULL NULL 19795 使用where
【问题讨论】:
-
这没有帮助。我仍然不知道问题出在哪里。
-
将排除加入更改为
NOT EXISTS有帮助吗? -
呃...我的意思是你可以在这里包含
EXPLAIN的结果,不是吗? -
使用
EXPLAIN your_query的完整输出编辑您的问题,以便我们为您提供更好的建议。 -
而且,顺便说一句,我错过了什么吗?为什么需要在
JOIN条件中包含 `AND h.date_changed