mysql 视图 条件语句 疑似 bug

2018-08-26 18:23:10 +08:00
 sycxyc

什么情况下,下列语句会输出 t1_view 总行数?

select count(*) from t1_view where id not in (select id from t1_view);

以下为操作:

create table t1 (id int primary key);
create table t2 (id int primary key);
insert t1 values (1),(2),(3);
insert t2 values (1);
create view t1_view as select a.id from t1 a join t2 order by a.id;
MariaDB [tmp]> select count(*) from t1_view where id not in (select id from t1_view);
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

MariaDB [tmp]> select count(*) from t1_view a where not exists (select id from t1_view b where a.id=b.id);
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

当前用 not exists 结果合理,但在一些情况下也有问题.

MariaDB [tmp]> select count(*) from t1_view a where not exists (select id from t1 b where a.id=b.id);
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

不知道是什么情况,现在很混乱. 希望懂的人解释一下原因.

版本 10.1.29-MariaDB-6+b1 Debian buildd-unstable

3435 次点击
所在节点    MySQL
11 条回复
choury
2018-08-26 20:25:42 +08:00
说了这么多没用的……你直接 select * from t1_view 就怎知道了
sycxyc
2018-08-26 20:41:30 +08:00
@choury 你用手机所以可能不太清楚情况. t1 和 t1_view 数据是是一样的, 但结果应该都是 0. 实际程序比这个复杂很多, 复现条件是视图中至少要使用 join 和 order by, 我是很难再简化了.
choury
2018-08-26 20:47:28 +08:00
你这个不带条件的 JOIN 就是做了一个迪卡尔乘积
所以你这个视图里面的数据应该实施这样的
id t2.id
1 null
2 null
3 null
null 1
想明白怎么回事没?
sycxyc
2018-08-26 21:18:14 +08:00
@choury 笛卡尔乘积那来的 null?
执行一下就知道了 select a.id,t2.id from t1 a join t2 order by a.id;
现在我很混乱,你不要乱说啊
msg7086
2018-08-27 07:30:06 +08:00
SELECT * FROM t1_view c WHERE c.id NOT IN (SELECT id FROM t1);
SELECT * FROM t1_view c WHERE c.id IN (SELECT id FROM t1);

这两句的结果完全一样。

所以我觉得是,MySQL 不支持你把「同表查询」和「表连接」和「 IN 子查询」和「视图」混在一起用。
我没找到具体的文档,估计你得去找开发者论坛问了。
sycxyc
2018-08-27 09:40:09 +08:00
@msg7086 不支持应该会报错,例如下面这种

MariaDB [tmp]> select * from t1_view c where c.id not in (select id from t1 limit 1);
ERROR 1235 (42000): This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

我认为是 mysql 优化器对视图支持存在缺陷, 目前发现新版本可以

set @@optimizer_switch='materialization=off';

关闭后对 not exists 的结果会有所改善
禁用优化的另一种方法是,条件不要"简单直接"

select count(*) from t1_view where 0+id not in (select id from t1_view);
blodside
2018-08-27 13:11:50 +08:00
实际上我用 mysql 8.0.12 复现不出来这个问题,也就是例子里这几个 count 都是 0。
sycxyc
2018-08-27 13:52:16 +08:00
@blodside 感谢反馈
看来是 MariaDB 分支引入的 bug,
版本 5.6.37 MySQL Community Server (GPL) 也无法复现
msg7086
2018-08-27 14:01:21 +08:00
@sycxyc 我说的「不支持」就是说可能代码里没有考虑到这种情况所以出的 Bug。
建议还是回报到开发者论坛。
上面我贴的那两句查询已经足够说明问题了。
sycxyc
2018-08-27 18:36:25 +08:00
@msg7086 恩, mariadb 那边已经确认 bug 了
https://jira.mariadb.org/browse/MDEV-17074
msg7086
2018-08-28 03:50:47 +08:00
@sycxyc 好像是物化视图翻车……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/483371

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX