MySQL慢速连接-但不总是,也不是所有表上都有

MySQL慢速连接-但不总是,也不是所有表上都有,mysql,join,performance,indexing,Mysql,Join,Performance,Indexing,我们遇到了一个MySQL数据库的性能问题,这太奇怪了,我们需要另一组眼睛来告诉我们是否疯了。 我们团队中有2名通过MySQL认证的开发人员,但他们只能说:“这是不可能的” 无论如何,情况是这样的:我们有一个疑问,理论上应该是合理的快速,但实际上是缓慢的。如果我们通过删除1个连接来缩小查询,查询将变得非常快。如果我们删除一个不同的联接,它仍然非常慢,尽管联接表的结构几乎相同。更糟糕的是:连接有时是快速的,有时不是。。。这似乎是某种随机问题,尽管它与服务器负载无关,因为我在本地系统上也有它 表结构如

我们遇到了一个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_报纸和046_分类都有一个主键(幸运的是)。它们都被外键引用自a046_文章。当我们运行以下查询时:

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秒后得到一个结果,这非常快

现在,当我们将join with Paper替换为join with category时:

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脚本,甚至需要访问数据库,那么您可以尝试一下,让我知道。。。我们的客户抱怨了很多关于慢页面的问题

谢谢

  • 始终使用解释(查询)来分析和理解MySQL是如何解析您的查询的
  • 检查您的索引,MySQL很可能为select选择了错误的索引
  • 尝试使用选择和索引提示

    从表1中选择*使用索引(col1\U索引、col2\U索引) 其中col1=1,col2=2,col3=3

    从表1中选择*忽略索引(col3_索引) 其中col1=1,col2=2,col3=3


  • 我将对所有表在表上显示索引,并检查基数列是否正确(即没有空值)。或者,您可以对每个表进行分析,以获得更好的度量。由于您有2名经过认证的MySQL开发人员,您可能已经这样做了


    下一步是查看解释,看看MySQL是如何优化它的。您可能需要使用强制、使用或忽略以使其正确优化。由于MySQL和具有缓存数据(即索引)的操作系统不同,速度也会有所不同,但当您指定“无缓存”时,查询的速度则不同。您可以发布解释吗?

    我想您可以尝试使用标量查询。

    如果查询优化器被愚弄了,可能会出现问题。奇怪的是,它是随机发生的。。。看一看直线连接;这允许您避免查询优化器重新排列它们。我们遇到了相同的问题,这里不再允许连接。我们通过修改查询而不是join来解决这个问题,我们使用select*from table1,table2,其中table1.field=table2.field。人们会告诉你,对你的问题,两个查询的EXPLAIN的性能和输出都不一样,但没有区别。@Grumpy:我也很难相信这一点。你有没有任何测试案例可以证明这一点?@Grumpy:我更改了两个查询,每个查询都有几个连接,并且删除了连接,EXPLAIN给出的结果没有任何变化。我相信您的改进来自其他地方,我不认为这是一条通向优化的道路,相反,它可能导致更难阅读的代码。