我们遇到了一个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脚本甚至可以访问数据库,那么您可以尝试一下,让我知道......我们的客户对这些慢页面抱怨很多......
谢谢!
答案 0 :(得分:0)
尝试使用SELECT和INDEX提示。 http://dev.mysql.com/doc/refman/5.1/en/index-hints.html。
SELECT * FROM table1 USE INDEX(col1_index,col2_index) 其中col1 = 1 AND col2 = 2 AND col3 = 3;
SELECT * FROM table1 IGNORE INDEX(col3_index) 其中col1 = 1 AND col2 = 2 AND col3 = 3;
答案 1 :(得分:0)
我会为所有表执行SHOW INDEX ON表,并检查基数列是否正确(即没有NULL)。或者您可以在每张桌子上进行分析以获得良好的测量结果。由于那里有2位经过认证的MySQL开发人员,您可能已经这样做了。
下一步是查看EXPLAIN并了解MySQL如何优化它。您可能需要使用FORCE,USE或IGNORE才能使其正确优化。自MySQL和具有缓存数据(即索引)的操作系统以来,速度会有所不同,但是当您指定“无缓存”时,速度将不同。你可以发布解释吗?
答案 2 :(得分:0)
我认为您可以尝试使用标量查询。