【发布时间】:2022-01-19 02:40:06
【问题描述】:
我有 3 个表,它们之间的关系是多对多的。
This is the Image of my tables with its columns
我需要获取包含具有特定 category_id 文件的主题标签名称。
问题是,当我使用下面的查询而不指定类别时,它的性能像 0.05s 一样好。
select `hashtags`.`slug`
from `hashtags`
where EXISTS (
select * from `files`
inner join `file_hashtags` on `files`.`id` = `file_hashtags`.`file_id`
where `hashtags`.`id` = `file_hashtags`.`hashtag_id`
);
但是当我使用指定的类别执行以下查询时,它会像 3s 一样执行。
select `hashtags`.`slug`
from `hashtags`
where EXISTS (
select * from `files`
inner join `file_hashtags` on `files`.`id` = `file_hashtags`.`file_id`
where `hashtags`.`id` = `file_hashtags`.`hashtag_id`
and `files`.`category_id`=2
);
我可以做些什么来改进它以获得更好的查询时间?我也使用 IN 而不是 Exists 进行了此查询,但结果是相同的,在时间上表现得更好 0.1s。
关于索引:
-
files 表有 ID 作为主键,category_id 作为 BTREE 索引(当我需要执行简单的查询,比如获取具有特定类别的文件时需要这个),并且 slug 作为唯一索引。
-
hashtags 表有 ID 作为主键,slug 作为唯一索引。
-
file_hashtags 表有两个表的外键, (file_id , hashtag_id) 也是主键。
files 表中大约有 150k 行,hashtags 表中有 75 行,pivot 表中有 260k 行。
更新:
如果我在查询中使用 category=10,它的执行速度非常快,因为我得到了该类别的 3k 数据,但如果我使用 category=2,它会像 3 秒一样慢,因为我获得了超过 90k 的该类别数据,我希望这有助于找到问题。
另一件事是,当我使用解释时,它在第一个查询中使用文件表的主键,但在第二个查询中它使用文件表的类别索引,我认为这是正常行为。
【问题讨论】:
-
“这是我的表格及其列的图像” 不够全面。最好将
SHOW CREATE TABLE table_name;结果的结果发布到您的问题中。这也会显示所有的键和索引。 -
另外,您可以通过在两个查询中添加
EXPLAIN来检查您的查询执行计划。 -
我使用了解释,当 where 子句中没有类别时,它对文件表使用 PK,但是当 where 子句中有类别时,它使用我认为的正常行为