表和视图关联查询报错runtime error: index out of range [0] with length 0

tidb版本:4.0.3
下面SQL语句执行报错:
SELECT
t1.qty,t1.cliitemcode,u.itemid
FROM
cli_clinicitem_fee_cmp t1,
fin_undruginfo u
WHERE t1.feeitemid = u.itemid
AND u.itemstatus = ‘1’
AND t1.isdrug = ‘0’

修改为下面的则没有问题:
SELECT
t1.qty,t1.cliitemcode,u.itemid,u.itemstatus
FROM
cli_clinicitem_fee_cmp t1,
fin_undruginfo u
WHERE t1.feeitemid = u.itemid
AND u.itemstatus = ‘1’
AND t1.isdrug = ‘0’

其中fin_undruginfo 为视图,cli_clinicitem_fee_cmp为表。

建表语句及数据见附件。
cli_clinicitem_fee_cmp.sql (2.9 KB) fin_undrug.sql (3.8 KB) fin_undrug_ext.sql (4.1 KB) fin_undruginfo.sql (1.7 KB)

好的,我们这边内部先复现下现象。

请问这个问题,能否再现?具体是什么原因呢。
是视图导致的么?
我们的业务代码中大量使用了视图,
全都梳理一遍很吃力啊

你好,附件中只看到建表语句没有相关数据,用上述语句在空表上进行查询时并没有报错:


你这边能反馈下具体报错信息吗?最好把数据也附上。谢谢!

不好意思。上次的附件忘了带数据了。
请用最新的附件。
cli_clinicitem_fee_cmp.sql (806.5 KB) fin_undrug.sql (310.1 KB) fin_undrug_ext.sql (3.3 MB) fin_undruginfo.sql (1.7 KB)

感谢反馈,辛苦在 shell 执行看下结果,并且将执行结果时间点对应 tidb log 中的信息也反馈下,辛苦。

你好,在 v4.0.3 版本中测试了下,确实复现了这个问题,我们这边内部先分析下,有结果后尽快反馈给你,谢谢。

分析可得,该问题是由于对于 view 构建 plan 的时候,一开始会在上面加一层 projection(会重新构建输出列,重新分配 uniqureID,加上自己本身的 projection 就是两层了),后面 plan 优化的时候,projection 被消除,导致构建物理执行 PhysicalHashJoin 的时候,其本身的 schema column 和孩子的 schma column 的 UniqueID不能匹配上(其中间本来是有层 projection 来做转化的)。最终导致输出时候 chunk 少填充了一列。index out of range

建议暂时绕过方案:可以直接使用构建视图的 select 定义作为 from 的子查询语句,后期我们会修复这个。

mysql> desc select t1.qty, u.itemid from cli_clinicitem_fee_cmp t1, myview u where t1.feeitemid = u.itemid and u.itemstatus = ‘1’;
±------------------------------±---------±----------±---------------------±----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
±------------------------------±---------±----------±---------------------±----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| HashJoin_15 | 10599.36 | root | | inner join, equal:[eq(test.cli_clinicitem_fee_cmp.feeitemid, Column#86)] |
| ├─TableReader_17(Build) | 3066.00 | root | | data:TableFullScan_16 |
| │ └─TableFullScan_16 | 3066.00 | cop[tikv] | table:t1 | keep order:false |
| └─HashJoin_47(Probe) | 8791.31 | root | | inner join, equal:[eq(test.fin_undrug.itemid, test.fin_undrug_ext.itemid)], other cond:eq(case(and(eq(test.fin_undrug.itemstatus, “1”), eq(test.fin_undrug_ext.status, “1”)), “1”, “0”), “1”) |
| ├─TableReader_57(Build) | 1013.00 | root | | data:TableFullScan_56 |
| │ └─TableFullScan_56 | 1013.00 | cop[tikv] | table:fin_undrug | keep order:false |
| └─TableReader_60(Probe) | 8800.00 | root | | data:Selection_59 |
| └─Selection_59 | 8800.00 | cop[tikv] | | not(isnull(test.fin_undrug_ext.itemid)) |
| └─TableFullScan_58 | 8800.00 | cop[tikv] | table:fin_undrug_ext | keep order:false |
±------------------------------±---------±----------±---------------------±----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
mysql> desc select t1.qty, u.itemid from cli_clinicitem_fee_cmp t1, (select (cas
e when ((fin_undrug.itemstatus = ‘1’) and (fin_undrug_ext.status = ‘1’))
then ‘1’ else ‘0’ end) AS ITEMSTATUS, fin_undrug.itemid AS ITEMID from
(fin_undrug join fin_undrug_ext) where (fin_undrug.itemid = fin_undrug_ext.itemid)) as u where t1.feeitemid = u.itemid and u.itemstatus = ‘1’;
±------------------------------±---------±----------±---------------------±----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
±------------------------------±---------±----------±---------------------±----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| HashJoin_14 | 10599.36 | root | | inner join, equal:[eq(test.cli_clinicitem_fee_cmp.feeitemid, test.fin_undrug.itemid)] |
| ├─TableReader_16(Build) | 3066.00 | root | | data:TableFullScan_15 |
| │ └─TableFullScan_15 | 3066.00 | cop[tikv] | table:t1 | keep order:false |
| └─HashJoin_46(Probe) | 8791.31 | root | | inner join, equal:[eq(test.fin_undrug.itemid, test.fin_undrug_ext.itemid)], other cond:eq(case(and(eq(test.fin_undrug.itemstatus, “1”), eq(test.fin_undrug_ext.status, “1”)), “1”, “0”), “1”) |
| ├─TableReader_56(Build) | 1013.00 | root | | data:TableFullScan_55 |
| │ └─TableFullScan_55 | 1013.00 | cop[tikv] | table:fin_undrug | keep order:false |
| └─TableReader_59(Probe) | 8800.00 | root | | data:Selection_58 |
| └─Selection_58 | 8800.00 | cop[tikv] | | not(isnull(test.fin_undrug_ext.itemid)) |
| └─TableFullScan_57 | 8800.00 | cop[tikv] | table:fin_undrug_ext | keep order:false |
±------------------------------±---------±----------±---------------------±----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

此为简化对比 SQL 可以用于复现。可以发现 view 和 from 子查询的计划是一致的,正是由于上述的原因才导致执行结果的差异

好吧,那我们在修复前只能调整SQL语句了。谢谢!

麻烦了,多谢。

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。