我们遇到了一个 MySQL 数据库的性能问题,这个问题非常奇怪,我们需要另一双眼睛来告诉我们是否要疯了。 我们的团队中有 2 名 MySQL 认证开发人员,但他们只能说:“这是不可能的”。
无论如何,情况是这样的:我们有一个查询,理论上应该相当快,但实际上很慢。如果我们通过删除 1 个连接来精简查询,查询将变得非常快。如果我们删除一个不同的连接,它仍然很慢,尽管连接表具有几乎相同的结构。更糟糕的是:连接有时很快,有时不是...这似乎是某种随机问题,尽管它与服务器负载无关,因为我的本地系统上也有它。
表结构如下:
Table : article Rows : 57491
Field Type Null Key Default Extra
arti_id int(10) unsigned NO PRI auto_increment
prev_id int(10) unsigned YES MUL (null)
news_id int(10) unsigned NO MUL (null)
cate_id int(10) unsigned NO MUL (null)
pdf_id int(10) unsigned YES MUL (null)
imag_id int(10) unsigned YES MUL (null)
publication_date date NO MUL (null)
title varchar(255) NO MUL (null)
full_text text YES (null) (null)
Table : category Rows : 3
Field Type Null Key Default Extra
cate_id int(10) unsigned NO PRI auto_increment
code varchar(7) NO (null) (null)
Table : language Rows : 4
Field Type Null Key Default Extra
lang_id int(10) unsigned NO PRI auto_increment
code varchar(2) NO (null) (null)
Table : newspaper Rows : 393
Field Type Null Key Default Extra
news_id int(10) unsigned NO PRI auto_increment
lang_id int(10) unsigned NO MUL (null)
name varchar(255) NO UNI (null)
现在出现了奇怪的部分:如您所见,046_newspaper 和 046_category 都有一个主键(幸运的是)。它们都是通过外键从 a046_article 引用的。当我们运行以下查询时:
SELECT SQL_NO_CACHE
article.*
FROM
article
INNER JOIN
newspaper AS `n`
ON
article.news_id = n.news_id
ORDER BY
article.publication_date DESC
LIMIT
50
我们在 0.016 秒后得到结果,这非常快。
现在,当我们用类别连接替换报纸连接时:
SELECT SQL_NO_CACHE
article.*
FROM
article
INNER JOIN
category AS `c`
ON
article.cate_id = c.cate_id
ORDER BY
article.publication_date DESC
LIMIT
50
查询耗时1.02秒。
奇怪的是,情况并非总是如此。有时,没有明显的原因,第一个查询也需要那么长时间。
最后我们要做的是:
SELECT SQL_CALC_FOUND_ROWS
*,
`n`.`name` AS `news_name`,
`c`.`cate_id`,
`c`.`code` AS `cate_name`,
`l`.`code` AS `lang_name`
FROM
`article`
INNER JOIN
`newspaper` AS `n`
ON
article.news_id = n.news_id
INNER JOIN
`category` AS `c`
ON
article.cate_id = c.cate_id
INNER JOIN
`language` AS `l`
ON
n.lang_id = l.lang_id
ORDER BY
`article`.`publication_date` DESC
LIMIT
50
此时需要超过 12 秒。这部分是由于 *,我们可以用单个字段替换它,但仍然需要 3 秒。
我们已经尝试了很多事情: - 添加索引(尽管所有必需的索引都已经存在并且添加更多只是一个坏主意) - 增加排序缓冲区大小和键缓冲区 - 看着解释了很多...... - 一遍又一遍地阅读 MySQL 手册 - 阅读大量论坛 然而,这样的事情并没有解决问题。
如果有人有任何想法,请随时大声疾呼!如果您需要 SQL 脚本甚至访问数据库,那么您可以尝试一下,让我知道...我们的客户提示页面速度慢...
谢谢!
最佳答案
- 始终使用 EXPLAIN(QUERY) 来分析和理解 MySQL 如何解析您的查询。
- 检查您的索引,MySQL 很可能为选择选择了错误的索引。
尝试使用 SELECT 和 INDEX 提示。 http://dev.mysql.com/doc/refman/5.1/en/index-hints.html .
SELECT * FROM table1 USE INDEX (col1_index,col2_index) WHERE col1=1 AND col2=2 AND col3=3;
SELECT * FROM table1 IGNORE INDEX (col3_index) WHERE col1=1 AND col2=2 AND col3=3;
关于MySQL Slow join - 但并非总是如此,也不是在所有表上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3100028/