SELECT a.id AS “id”,
parent AS “pid”,
role_name AS “name”,
(SELECT sir.role_id
FROM t_sys_staff_inst_role sir
INNER JOIN t_sys_staff s
ON sir.staff_id = s.id
WHERE sir.institution_id = 100002
AND sir.staff_id = 51019
AND sir.role_id = a.id) AS checked
FROM t_sys_role a
WHERE a.platform_code = ‘ahis’
ORDER BY orders ASC;
以上语句在mysql中执行结果正确,在tidb中执行结果不正确
- 请问 tidb 版本是哪个?
- 请反馈建表语句,我们测试下,多谢。
其实我们不关心这个具体问题,想知道什么原因导致,是不是我们以后上生产了还碰到类似问题,能说明原因,我们心里有底
或者能告诉我们4.0.5通过修复什么BUG解决4.0.4这个问题的,我们自己去查一下问题原因
hi 这个问题是因 4.0 引入的 PointGet as datasource 优化(所以如果您使用的是 3.0 不会有这个问题), table:t_sys_staff 将使用性能更好的 PointGet 算子作为 t_sys_staff_inst_role 和 t_sys_staff 进行 join 的 probe 表
MySQL [test]> explain SELECT a.id AS id, parent AS pid, role_name AS name, (SELECT sir.role_id FROM t_sys_staff_inst_role sir INNER JOIN t_sys_staff s ON sir.staff_id = s.id WHERE sir.institution_id = 100002 AND sir.staff_id = 51019 AND sir.role_id = a.id) AS checked FROM t_sys_role a WHERE a.platform_code = 'ahis' ORDER BY orders ASC;
+--------------------------------------------+---------+-----------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+--------------------------------------------+---------+-----------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+
| Projection_14 | 0.08 | root | | test.t_sys_role.id, test.t_sys_role.parent, test.t_sys_role.role_name, test.t_sys_staff_inst_role.role_id |
| └─Sort_15 | 0.08 | root | | test.t_sys_role.orders:asc |
| └─Apply_18 | 0.08 | root | | CARTESIAN left outer join |
| ├─TableReader_21(Build) | 0.08 | root | | data:Selection_20 |
| │ └─Selection_20 | 0.08 | cop[tikv] | | eq(test.t_sys_role.platform_code, "ahis") |
| │ └─TableFullScan_19 | 79.00 | cop[tikv] | table:a | keep order:false, stats:pseudo |
| └─MaxOneRow_22(Probe) | 1.00 | root | | |
| └─HashJoin_24 | 0.00 | root | | CARTESIAN inner join |
| ├─IndexLookUp_31(Build) | 0.00 | root | | |
| │ ├─IndexRangeScan_28(Build) | 4.00 | cop[tikv] | table:sir, index:idx_staff_instrole_staff_instid(staff_id, institution_id) | range:[51019 100002,51019 100002], keep order:false |
| │ └─Selection_30(Probe) | 0.00 | cop[tikv] | | eq(test.t_sys_staff_inst_role.role_id, test.t_sys_role.id) |
| │ └─TableRowIDScan_29 | 4.00 | cop[tikv] | table:sir | keep order:false |
| └─Point_Get_32(Probe) | 1.00 | root | table:t_sys_staff, index:PRIMARY(id) | |
+--------------------------------------------+---------+-----------+----------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+
13 rows in set (0.001 sec)
但如上面看到的 t_sys_staff_inst_role 和 t_sys_staff 的 join 组合算子将被 t_sys_role 外表的每行数据进行 apply join,因此 t_sys_staff 表的 PointGet 算子将被多次 Open/Close,但 4.0.5 之前的 PointGet 算子的 Close 并没有做很完善清理重置操作(3.0 没问题是因为 Point 不可能会在 apply 下出现),导致非首次 apply probe 将返回上一次的数据,导致看到都是 NULL 的问题
这个问题会在 4.0.0 - 4.0.4 版本中 apply probe 侧孩子有 point-get 算子的情况出现,建议升级到 4.0.5 可以避免出现类似问题
修复细节见 https://github.com/pingcap/tidb/pull/19046/files#diff-df02d02a3dd97c99ecb50a845c2c4b46R127
应该是这个太长了,我在终端里也换行,但复制处理张贴到这里用 markdown 代码标签 刚好不换行