提高查询性能/在MySQL上更快地重写查询
我有几个查询使用数据库中当前的数据运行得非常慢(几分钟),我想提高它们的性能。不幸的是,它们有点复杂,所以我通过谷歌获得的信息不足以让我确定要添加哪些索引,或者我是否需要重写我的查询或什么。。。我希望有人能帮忙。我不认为他们应该这么慢,如果事情安排得当的话 第一个查询是:提高查询性能/在MySQL上更快地重写查询,mysql,sql,Mysql,Sql,我有几个查询使用数据库中当前的数据运行得非常慢(几分钟),我想提高它们的性能。不幸的是,它们有点复杂,所以我通过谷歌获得的信息不足以让我确定要添加哪些索引,或者我是否需要重写我的查询或什么。。。我希望有人能帮忙。我不认为他们应该这么慢,如果事情安排得当的话 第一个查询是: SELECT i.name, i.id, COUNT(c.id) FROM cert_certificates c JOIN cert_histories h ON h.cert_certificate_id = c.id
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
选择识别号、识别号、计数(c.id)
来自证书c
在h.cert\u certificate\u id=c.id上加入证书
h.inspector_id=i.id上的左外连接检验者i
左外连接证书
ON(h2.cert\u certificate\u id=c.id和h.date\u changed
第二个问题是:
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
选择l.字母、c.编号
来自证书c
在c上加入证书类型字母参考l。证书类型字母参考id=l.id
在h.cert\u certificate\u id=c.id上加入证书
左外连接证书
ON(h2.cert\u certificate\u id=c.id和h.date\u changed
cert_certificates表和cert_histories表包含近19k条记录(尽管在未来,该表预计将增长到cert_certificates表大小的2-3倍)。其他的桌子都很小;每个记录少于10条
现在唯一的索引是每个表的id和cert_certificates.number。我读了几个地方(例如)来为外键添加索引,但是在cert_histories表的情况下,几乎所有的列(cert_certificate_id、inspector_id、cert_status_ref_id)也是(根据关于这个问题的一些答案,例如Markus Winand的),所以我有点迷路了
任何帮助都将不胜感激
ETA:第一个查询的解释结果是(对不起,格式太糟糕了;我正在使用SQLyog,它在一个漂亮的表中显示,但StackOverflow似乎不支持表?)
id选择\u类型表类型可能的\u键\u长度参考行额外
1简单h所有空19740使用where;使用临时设备;使用文件排序
1个简单的i参考索引\u检查员\u id索引\u检查员\u id 768营销\u开发。h.检查员\u id 1
1个简单的c参考索引证书id上的证书索引id上的证书768 marketing\u development.h.cert\u certificate\u id 91,使用where;使用索引
1简单h2所有空19740使用where
第二个问题:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE h ALL NULL NULL NULL NULL 19795 Using where; Using temporary; Using filesort
1 SIMPLE c ref index_cert_certificates_on_id index_cert_certificates_on_id 768 marketing_development.h.cert_certificate_id 91 Using where
1 SIMPLE l ALL index_cert_type_letter_refs_on_id NULL NULL NULL 5 Using where; Using join buffer
1 SIMPLE h2 ALL NULL NULL NULL NULL 19795 Using where
id选择\u类型表类型可能的\u键\u长度参考行额外
1简单h所有空19795使用where;使用临时设备;使用文件排序
1简单c参考索引证书id上的证书索引id上的证书768营销开发h证书id 91使用何处
1简单l所有索引证书类型字母参考id NULL 5使用where;使用连接缓冲区
1 SIMPLE h2 ALL NULL 19795使用where应在连接字段上创建索引:
cert_certificates.cert_type_letter_ref_id
cert_histories.cert_certificate_id
cert_histories.date_changed
cert_histories.inspector_id
那没用。我仍然不知道问题出在哪里。将排除连接更改为
不存在是否有帮助?呃。。。我的意思是你可以把EXPLAIN
的结果包含在这里,不是吗?用EXPLAIN your_query
的完整输出编辑你的问题,这样我们可以给你更好的建议。顺便说一句,我错过了什么吗;为什么需要在JOIN
条件中包含`AND h.date\u changedcert_certificates.cert_type_letter_ref_id
cert_histories.cert_certificate_id
cert_histories.date_changed
cert_histories.inspector_id