提高查询性能/重写查询以便在MySQL上更快

时间:2012-10-29 18:04:14

标签: 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 
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表包含近19k条记录,cert_histories表也是如此(尽管将来该表预计会增长到cert_certificates表大小的2-3倍)。其他表都很小;每个不到10个记录。

现在唯一的索引是每个表和cert_certificates.number的id。我读了几个地方(例如here)来为外键添加索引,但是在cert_histories表的情况下,几乎所有的列(cert_certificate_id,inspector_id,cert_status_ref_id)也是{{ 3}}(根据该问题的一些答案,例如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   Using where; Using temporary; Using filesort
1   SIMPLE  i   ref 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  Using where; Using index
1   SIMPLE  h2  ALL NULL    NULL    NULL    NULL    19740   Using 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

1 个答案:

答案 0 :(得分:1)

您应该在连接字段上创建索引:

cert_certificates.cert_type_letter_ref_id
cert_histories.cert_certificate_id
cert_histories.date_changed
cert_histories.inspector_id