MySQL慢速连接 - 但并非总是而不是所有表 [英] MySQL Slow join - but not always and not on all tables

查看:177
本文介绍了MySQL慢速连接 - 但并非总是而不是所有表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们遇到了一个MySQL数据库的性能问题很奇怪我们需要另外一组眼睛来告诉我们我们是否疯了。
我们团队中有2位MySQL认证开发人员,但他们只能说:这是不可能的。

We're experiencing a performance issue with a MySQL database that's so weird we need another set of eyes to tell us whether we're going crazy or not. We've got 2 MySQL Certified Developers in the team, but all they can say is : "this is impossible".

无论如何,情况如下:我们有一个理论上应该合理快速的查询,但实际上是缓慢的。如果我们通过删除1个连接来减少查询,则查询变得非常快。如果我们删除不同的连接,它仍然非常慢,尽管连接表具有几乎相同的结构。更糟糕的是:连接有时很快,有时候不是......它似乎是某种随机问题,虽然它与服务器负载无关,因为我在本地系统上也有。

Anyway, here's the situation : we have a query that in theory should be reasonbly fast, but in reality is slow. If we slim down the query by removing 1 join, the query becomes extremely fast. If we remove a different join, it's still very slow, although the joined table has nearly the same structure. Worse even : the joins are SOMETIMES fast, sometimes not... it seems it's a random problem of some kind, although it has nothing to do with server load, since I have it on my local system too.

表结构如下所示:

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引用的。当我们运行以下查询时:

Now comes the weird part : as you can see 046_newspaper and 046_category both have a primary key (luckily). They're both referenced from a046_article by a foreign key. When we run the following query :

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

We get a result after 0.016 seconds, which is pretty fast.

现在,当我们通过类别的加入替换报纸的加入时:

Now when we replace the join with newspaper by a 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秒。

奇怪的是,并非总是这样。有时,由于没有明显的原因,第一个查询也需要很长时间。

The odd thing is that this isn't always the case. Sometimes, for no apparent reason, the first query takes about that long too.

最后我们要做的是:

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秒。

which takes over 12 seconds at this point. This is partly due to the *, which we could replace by individual fields, but then it still takes 3 seconds.

我们尝试了很多东西:
- 添加索引(尽管所有必需的索引已经存在并且添加更多只是一个坏主意)
- 增加排序缓冲区大小和密钥缓冲区
- 看看解释很多...
- 一遍又一遍地阅读MySQL手册
- 阅读很多论坛
然而,没有这样的事情解决了这个问题。

We've tried a number of things : - Adding indexes (although all required indexes were there already and adding more is simply a bad idea) - Increasing the sort buffer size and key buffer - Looking at explain a lot... - Reading the MySQL manual over and over again - Reading a lot of forums However, nothing like this has solved the issue.

如果有人有任何想法,请随时大喊!如果您需要SQL脚本甚至可以访问数据库,那么您可以尝试一下,让我知道......我们的客户对这些慢页面抱怨很多......

If anyone has any ideas, feel free to shout ! If you need the SQL-script or even access to the database, so you can give it a try, let me know... our client is complaining a lot about the slow pages...

谢谢!

推荐答案

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

I think you can try with scalar query .

这篇关于MySQL慢速连接 - 但并非总是而不是所有表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆