暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

数据库的基础的exists

原创 薛晓刚 2024-08-05
106

很多基础的东西可以拿来细说一下:

假设X和Y两个表如下:
mysql> select * from x;
±—±-----+
| id | a |
±—±-----+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 10 | 10 |
±—±-----+
10 rows in set (0.00 sec)

mysql> select * from y;
±—±-----+
| id | a |
±—±-----+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
±—±-----+
3 rows in set (0.00 sec)

如果写成exists那么,这两种是一样的结果。由于Y表只有3行数据库。X表也只有10条。不会有性能问题。

实际上这样写,子查询有一条或者是1万条都是 只看1条。仅做一次判断。然后就执行父查询,几乎没有差别。

mysql> select * from x where exists (select *from y where y.id=1);
±—±-----+
| id | a |
±—±-----+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 10 | 10 |
±—±-----+
10 rows in set (0.00 sec)

mysql> select * from x where exists (select *from y);
±—±-----+
| id | a |
±—±-----+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 8 |
| 9 | 9 |
| 10 | 10 |
±—±-----+
10 rows in set (0.00 sec)

而实际工作中X和表Y表都会很大。而且实际工作中更多的是下面这种写法。这种关联子查询的方式。

我见到的多是下面这种。开发就写成这样了。我一直觉得这其实属于数据库表设计问题。

那么这种就是返回了较少的表的全部数据。当然这种会随着两个表的数量上升以及关联的范围越来越大会变得越来越慢。

真实的情况是两个表结果集都很大。不可能只有3条数据的。当然这就和exists本身关系不大了。那就两个表直接关联好了。

失去了exists的意义。

mysql> select * from x where exists (select *from y where x.id=y.id);
±—±-----+
| id | a |
±—±-----+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
±—±-----+
3 rows in set (0.00 sec)

有时候这个较少的表也很大。比如这时候子查询是2条。而实际情况子查询可能200万或者是2000万。
mysql> select * from x where exists (select *from y where x.id=y.id and y.id>1);
±—±-----+
| id | a |
±—±-----+
| 2 | 2 |
| 3 | 3 |
±—±-----+
2 rows in set (0.00 sec)

从日志中就可以看到,关联子查询不会再是子查询仅返回1行的那种优势了。随着结果集的变化而变化。

Query_time: 0.000857 Lock_time: 0.000012 Rows_sent: 3 Rows_examined: 6

select * from x where exists (select *from y where x.id=y.id);

Query_time: 0.001061 Lock_time: 0.000014 Rows_sent: 2 Rows_examined: 5

select * from x where exists (select *from y where x.id=y.id and y.id>1);

以上都有一些等价改写,不过我还是建议从设计出发来解决。

其实日常工作中遇到的都是基础问题,很难有什么高级问题。关注一下基础吧。

最后修改时间:2024-08-05 22:02:40
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论