给定m2m关系:项目类别我有三个表:
我想找到一个属于所有给定类别集的项目:
Find Item
belonging to a category in [1,3,6]
and belonging to a category in [7,8,4]
and belonging to a category in [12,66,42]
and ...
我可以通过两种方式在mySQL中实现这一目标。
选项A:内部联合:
SELECT id from items
INNER JOIN category c1 ON (item.id = c1.item_id)
INNER JOIN category c2 ON (item.id = c2.item_id)
INNER JOIN category c3 ON (item.id = c3.item_id)
...
WHERE
c1.category_id IN [1,3,6] AND
c2.category_id IN [7,8,4] AND
c3.category_id IN [12,66,42] AND
...;
选项B:EXISTS:
SELECT id from items
WHERE
EXISTS(SELECT category_id FROM category WHERE category.item_id = id AND category_id in [1,3,6] AND
EXISTS(SELECT category_id FROM category WHERE category.item_id = id AND category_id in [7,8,4] AND
EXISTS(SELECT category_id FROM category WHERE category.item_id = id AND category_id in [12,66,42] AND
...;
两种选择都有效。问题是:哪个是大项目表最快/最优的?或者是否有一个我缺少的选项C?
答案 0 :(得分:11)
选项A
JOIN
优于EXIST
,因为它会更有效地使用索引,尤其是在大型表的情况下
答案 1 :(得分:11)
一般来说,JOIN
效率更高。
但是,需要注意的一点是,连接可以在输出中产生重复的行。例如,如果项目ID在类别1和3中,则第一个JOIN
将导致id为123的两行。如果项目ID 999在类别1,3,7,8,12和66中,则将在结果中获得999的 8个行(2 * 2 * 2)。
重复行是您需要注意和处理的事情。在这种情况下,您可以使用select distinct id...
。但是,通过复杂的查询,消除重复可能会变得更加复杂。
答案 2 :(得分:2)
您正在选项B 中使用加入,在选项B 中使用subquery。区别在于:
在大多数情况下,JOIN比子查询更快,并且子查询的速度非常快。
在JOIN中,RDBMS可以创建一个更适合您的查询的执行计划,并且可以预测应该加载哪些数据以进行处理并节省时间,这与子查询不同,后者将运行所有查询并将所有数据加载到做处理。
子查询的好处是它们比JOIN更具可读性:这就是大多数新SQL用户更喜欢它们的原因;这是简单的方法;但是在性能方面,JOINS在大多数情况下都更好,即使它们也不难阅读。
答案 3 :(得分:1)
select distinct `user_posts_id` from `user_posts_boxes`
where `user_id` = 5
and
exists (select * from `box` where `user_posts_boxes`.`box_id` = `box`.`id`
and `status` in ("A","F"))
order by `user_posts_id` desc limit 200;
select distinct `user_posts_id` from `user_posts_boxes`
INNER JOIN box on box.id = `user_posts_boxes`.`box_id` and box.`status` in ("A","F")
and box.user_id = 5
order by `user_posts_id` desc limit 200
我尝试了两个查询,但是上面的查询对我来说工作更快,两个表都有大数据集。几乎“ user_posts_boxes”有400万,盒子为150万。
第一个查询耗时= 0.147毫秒 第二次查询几乎= 0.5到0.9 MS
但是我的数据库表是inno db,并且还具有物理关系。
所以我应该继续存在,但这还取决于您的数据库结构如何。