我在mysql数据库中有以下表格:
文章 - 有一个数字AUTO_INCREMENT id字段,以及一些使用全文索引的文本字段
类别 - 具有数字AUTO_INCREMENT id字段,以及其他一些不相关的字段
articles_categories - 使用两个外键将文章连接到分类:article_id(指向文章的id字段)和category_id(指向类别的id字段)
现在,我正在运行以下查询:
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
这有什么意义?
注意:我希望避免发布实际的表和索引代码,但如果必须,我会这样做。感谢任何愿意帮助的人......
答案 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;
那么性能如何呢?