mysql:子查询使全局查询比仅使用子查询的实际结果慢

时间:2016-05-24 14:28:04

标签: mysql sql

我在mysql数据库中有以下表格:

  1. 文章 - 有一个数字AUTO_INCREMENT id字段,以及一些使用全文索引的文本字段

  2. 类别 - 具有数字AUTO_INCREMENT id字段,以及其他一些不相关的字段

  3. articles_categories - 使用两个外键将文章连接到分类:article_id(指向文章的id字段)和category_id(指向类别的id字段)

  4. 现在,我正在运行以下查询:

    select AC.category_id, count(*) as num_articles
    from categories C
    join articles_categories AC on C.id = AC.category_id
    where AC.article_id in (
    select id from articles where match(name, teaser, plaintext_contents) against ('some text' in boolean mode)
    )
    group by AC.category_id;
    

    ,并且在每张桌子上花了将近3秒的时间来运行几个字段。以下是使用EXPLAIN运行此查询的结果:

    1   SIMPLE  C   index   PRIMARY PRIMARY 4       187 Using index; Using temporary; Using filesort
    1   SIMPLE  AC  ref IX_articles_categories_category_id_article_id   IX_articles_categories_category_id_article_id   4   kalir_co_il.C.id    56  Using where; Using index
    1   SIMPLE  articles    eq_ref  PRIMARY PRIMARY 4   kalir_co_il.AC.article_id   1   Using index condition; Using where
    

    但这是奇怪的。

    在我的查询中间运行的以下子查询只需0.4秒:

    select id from articles where match(name, teaser, plaintext_contents) against ('some text' in boolean mode)
    

    所以我认为查询的其余部分需要这么长时间。但是......当我用它的实际结果替换子查询时,它是27个ID(数字)的列表,我运行整个查询,并在不到0.1秒的时间内执行!

    select AC.category_id, count(*) as num_articles
    from categories C
    join articles_categories AC on C.id = AC.category_id
    where AC.article_id in (61,
    167,
    352,
    374,
    407,
    419,
    455,
    462,
    467,
    502,
    575,
    696,
    746,
    756,
    759,
    851,
    1001,
    1046,
    1052,
    1311,
    1497,
    1501,
    1502,
    1503,
    1508,
    1514,
    1538
    )
    group by AC.category_id;
    

    来自EXPLAIN的以下结果:

    1   SIMPLE  C   index   PRIMARY PRIMARY 4       187 Using index; Using temporary; Using filesort
    1   SIMPLE  AC  ref IX_articles_categories_category_id_article_id   IX_articles_categories_category_id_article_id   4   kalir_co_il.C.id    56  Using where; Using index
    

    这有什么意义?

    注意:我希望避免发布实际的表和索引代码,但如果必须,我会这样做。感谢任何愿意帮助的人......

1 个答案:

答案 0 :(得分:1)

Mysql的历史是不能很好地处理子查询。根据你的mysql版本,标志等,有许多错综复杂可以在这方面发挥作用。请查看此文档了解详细信息 - https://dev.mysql.com/doc/refman/5.7/en/subquery-optimization.html

另外,您是否尝试将查询重写为连接?

select AC.category_id, count(*) as num_articles
from categories C
join articles_categories AC on C.id = AC.category_id
join (
  select id from articles where match(name, teaser, plaintext_contents) against ('some text' in boolean mode)
) A_IDS ON A_IDS.id=AC.article_id

group by AC.category_id;

那么性能如何呢?