注册

DM8 中 BIGINT 字段 GROUP BY 返回重复分组,CAST 为 VARCHAR 后正常

清澈 2026/10/30 316 5

DM8 中 BIGINT 字段 GROUP BY 返回重复分组,CAST 为 VARCHAR 后正常,请协助分析

以下表名、部分字段名和索引名已匿名化。

【DM版本】:

DM Database Server 64 V8 8.4 企业版 DB Version: 0x7000c 03134284194-20250707-281643-20108 Msg Version: 14 Gsu level(5) cnt: 0

查询工具:disql V8。

【操作系统】:麒麟。

【问题描述】*:

BIGINT 字段执行 GROUP BY 时,同一个 ID 被拆成两组;将分组表达式改成 VARCHAR 后结果正常。希望协助分析具体原因,以及是否有对应的修复或规避方案。

一、相关表结构说明

  • tree_node:通过 id、parent_id 存储节点层级关系。
  • node_record_rel:通过 node_id 关联末级节点。
  • del_flag=0 表示未删除。
  • 已通过 USER_TAB_COLUMNS 确认,tree_node.id、tree_node.parent_id 均为 BIGINT,DATA_SCALE=0。

查询通过节点表的三次关联,按上级节点 ID 统计末级节点的关联记录数。

二、异常查询及实际结果

执行以下 SQL:

SELECT l.parent_id AS node_id, CAST(l.parent_id AS VARCHAR(100)) AS id_text, LENGTH(CAST(l.parent_id AS VARCHAR(100))) AS id_length, COUNT(r.id) AS record_count FROM tree_node l INNER JOIN tree_node s ON l.id = s.parent_id INNER JOIN tree_node c ON s.id = c.parent_id INNER JOIN node_record_rel r ON c.id = r.node_id WHERE l.parent_id IN ( 1066440524199625030, 1983446954328997890, 2115984052879773697 ) AND l.del_flag = 0 AND s.del_flag = 0 AND c.del_flag = 0 GROUP BY l.parent_id ORDER BY l.parent_id;

实际返回四行:

node_id id_text id_length record_count ------------------- ------------------- --------- ------------ 1066440524199625030 1066440524199625030 19 3008 1983446954328997890 1983446954328997890 19 1708 2115984052879773697 2115984052879773697 19 87 1983446954328997890 1983446954328997890 19 32

异常表现:

  1. 1983446954328997890 在 GROUP BY 结果中出现两次,分别统计为 1708、32。
  2. 已指定 ORDER BY l.parent_id,但最后一行没有按升序排列。

三、已核对问题 ID 的类型及内部字节

问题父节点下有四个未删除的直接子节点。执行:

SELECT l.id AS child_id, l.parent_id, DUMP(l.parent_id, 16) AS parent_id_dump FROM tree_node l WHERE l.parent_id = 1983446954328997890 AND l.del_flag = 0 ORDER BY l.id;

结果:

child_id parent_id parent_id_dump ------------------- ------------------- ---------------------------------- 1983446954379329536 1983446954328997890 Typ=8 Len=8: 2,40,9c,7,7f,9e,86,1b 1983446954391912448 1983446954328997890 Typ=8 Len=8: 2,40,9c,7,7f,9e,86,1b 1983446954400301056 1983446954328997890 Typ=8 Len=8: 2,40,9c,7,7f,9e,86,1b 1983446954404495360 1983446954328997890 Typ=8 Len=8: 2,40,9c,7,7f,9e,86,1b

四个节点的父 ID 为 BIGINT,显示值及内部字节完全一致。

四、单独计数,不进行分组时返回 1740

执行:

SELECT COUNT(r.id) AS record_count FROM tree_node l INNER JOIN tree_node s ON l.id = s.parent_id INNER JOIN tree_node c ON s.id = c.parent_id INNER JOIN node_record_rel r ON c.id = r.node_id WHERE l.parent_id = 1983446954328997890 AND l.del_flag = 0 AND s.del_flag = 0 AND c.del_flag = 0;

返回:

record_count ------------ 1740

正好等于异常分组结果中的:

1708 + 32 = 1740

五、两层聚合且不带 ORDER BY 时,同样出现重复分组

应用原查询采用“内层 COUNT 并分组、外层 SUM 再分组”的结构,不带 ORDER BY:

SELECT parent_id AS node_id, SUM(record_count) AS record_count FROM ( SELECT l.parent_id, COUNT(r.id) AS record_count FROM tree_node l INNER JOIN tree_node s ON l.id = s.parent_id AND l.del_flag = 0 INNER JOIN tree_node c ON s.id = c.parent_id AND c.del_flag = 0 INNER JOIN node_record_rel r ON c.id = r.node_id WHERE l.parent_id IN ( 1066440524199625030, 1983446954328997890, 2115984052879773697 ) AND l.del_flag = 0 AND s.del_flag = 0 AND c.del_flag = 0 GROUP BY l.parent_id ) a GROUP BY parent_id;

仍返回四行:

node_id record_count ------------------- ------------ 1066440524199625030 3008 1983446954328997890 1708 2115984052879773697 87 1983446954328997890 32

六、改为字符串表达式分组后正常

保持关联及过滤条件不变,执行以下 SQL:

SELECT CAST(l.parent_id AS VARCHAR(100)) AS node_id_text, COUNT(r.id) AS record_count FROM tree_node l INNER JOIN tree_node s ON l.id = s.parent_id INNER JOIN tree_node c ON s.id = c.parent_id INNER JOIN node_record_rel r ON c.id = r.node_id WHERE l.parent_id IN ( 1066440524199625030, 1983446954328997890, 2115984052879773697 ) AND l.del_flag = 0 AND s.del_flag = 0 AND c.del_flag = 0 GROUP BY CAST(l.parent_id AS VARCHAR(100)) ORDER BY CAST(l.parent_id AS VARCHAR(100));

正常返回三行:

node_id_text record_count ------------------- ------------ 1066440524199625030 3008 1983446954328997890 1740 2115984052879773697 87

七、异常查询的执行计划

以下为第二部分中单层 BIGINT 分组查询的执行计划,对象名称已对应匿名化:

1 #NSET2: [15, 6, 208] 2 #PRJT2: [15, 6, 208]; exp_num(4), is_atom(FALSE) 3 #SAGR2: [14, 6, 208]; grp_num(1), sfun_num(1), distinct_flag[0]; slave_empty(0) keys(l.parent_id) 4 #SORT3: [14, 6, 208]; key_num(1), partition_key_num(1), is_distinct(FALSE), top_flag(0), is_adaptive(1) 5 #HASH2 INNER JOIN: [13, 660, 208]; KEY_NUM(1); KEY(c.id=r.node_id) KEY_NULL_EQU(0) 6 #NEST LOOP INDEX JOIN2: [13, 660, 208] 7 #ACTRL: [13, 660, 208] 8 #SLCT2: [11, 330, 192]; exp_cast(c.del_flag) = 0 9 #HASH2 INNER JOIN: [11, 330, 192]; KEY_NUM(1); KEY(s.id=c.parent_id) KEY_NULL_EQU(0) 10 #SLCT2: [11, 330, 192]; exp_cast(c.del_flag) = 0 11 #NEST LOOP INDEX JOIN2: [11, 330, 192] 12 #ACTRL: [11, 330, 192] 13 #HASH2 INNER JOIN: [10, 165, 128]; KEY_NUM(1); KEY(s.parent_id=l.id) KEY_NULL_EQU(0) 14 #SLCT2: [5, 2203, 64]; exp_cast(s.del_flag) = 0 SLCT_PUSHDOWN(TRUE) 15 #CSCN2: [5, 44062, 64]; INDEX33560418(tree_node as s) NEED_SLCT(TRUE); btr_scan(1) 16 #SLCT2: [3, 3304, 64]; exp_cast(l.del_flag) = 0 17 #NEST LOOP INDEX JOIN2: [3, 3304, 64] 18 #CONST VALUE LIST: [1, 3, 8]; row_num(3), col_num(1) 19 #BLKUP2: [3, 1101, 64]; idx_parent_id(l) 20 #SSEK2: [3, 1101, 64]; scan_type(ASC), idx_parent_id(tree_node as l), scan_range[DMTEMPVIEW_895658659.colname,DMTEMPVIEW_895658659.colname], is_global(0) 21 #BLKUP2: [1, 2, 8]; idx_parent_id(c) 22 #SSEK2: [1, 2, 8]; scan_type(ASC), idx_parent_id(tree_node as c), scan_range[s.id,s.id], is_global(0) 23 #CSCN2: [5, 44062, 64]; INDEX33560418(tree_node as c); btr_scan(1) 24 #BLKUP2: [2, 2, 8]; idx_node_id(r) 25 #SSEK2: [2, 2, 8]; scan_type(ASC), idx_node_id(node_record_rel as r), scan_range[c.id,c.id], is_global(0) 26 #CSCN2: [4, 45720, 16]; INDEX33560903(node_record_rel as r); btr_scan(1)

关键路径为:

先 SORT3,再 SAGR2 分组

八、正常字符串分组查询的执行计划

以下为第六部分查询的执行计划,对象名称已对应匿名化:

1 #NSET2: [15, 6, 208] 2 #PRJT2: [15, 6, 208]; exp_num(2), is_atom(FALSE) 3 #SORT3: [15, 6, 208]; key_num(1), partition_key_num(0), is_distinct(FALSE), top_flag(0), is_adaptive(0) 4 #HAGR2: [14, 6, 208]; grp_num(1), sfun_num(1), distinct_flag[0]; slave_empty(0) keys(DMTEMPVIEW_895659480.TMPCOL0) 5 #PRJT2: [13, 660, 208]; exp_num(2), is_atom(FALSE) 6 #HASH2 INNER JOIN: [13, 660, 208]; KEY_NUM(1); KEY(c.id=r.node_id) KEY_NULL_EQU(0) 7 #NEST LOOP INDEX JOIN2: [13, 660, 208] 8 #ACTRL: [13, 660, 208] 9 #SLCT2: [11, 330, 192]; exp_cast(c.del_flag) = 0 10 #HASH2 INNER JOIN: [11, 330, 192]; KEY_NUM(1); KEY(s.id=c.parent_id) KEY_NULL_EQU(0) 11 #SLCT2: [11, 330, 192]; exp_cast(c.del_flag) = 0 12 #NEST LOOP INDEX JOIN2: [11, 330, 192] 13 #ACTRL: [11, 330, 192] 14 #HASH2 INNER JOIN: [10, 165, 128]; KEY_NUM(1); KEY(s.parent_id=l.id) KEY_NULL_EQU(0) 15 #SLCT2: [5, 2203, 64]; exp_cast(s.del_flag) = 0 SLCT_PUSHDOWN(TRUE) 16 #CSCN2: [5, 44062, 64]; INDEX33560418(tree_node as s) NEED_SLCT(TRUE); btr_scan(1) 17 #SLCT2: [3, 3304, 64]; exp_cast(l.del_flag) = 0 18 #NEST LOOP INDEX JOIN2: [3, 3304, 64] 19 #CONST VALUE LIST: [1, 3, 8]; row_num(3), col_num(1) 20 #BLKUP2: [3, 1101, 64]; idx_parent_id(l) 21 #SSEK2: [3, 1101, 64]; scan_type(ASC), idx_parent_id(tree_node as l), scan_range[DMTEMPVIEW_895659482.colname,DMTEMPVIEW_895659482.colname], is_global(0) 22 #BLKUP2: [1, 2, 8]; idx_parent_id(c) 23 #SSEK2: [1, 2, 8]; scan_type(ASC), idx_parent_id(tree_node as c), scan_range[s.id,s.id], is_global(0) 24 #CSCN2: [5, 44062, 64]; INDEX33560418(tree_node as c); btr_scan(1) 25 #BLKUP2: [2, 2, 8]; idx_node_id(r) 26 #SSEK2: [2, 2, 8]; scan_type(ASC), idx_node_id(node_record_rel as r), scan_range[c.id,c.id], is_global(0) 27 #CSCN2: [4, 45720, 16]; INDEX33560903(node_record_rel as r); btr_scan(1)

关键路径为:

先 HAGR2 分组,再 SORT3 排序

两份计划仍使用 idx_parent_id、idx_node_id 等相同索引访问路径。

九、其他排查及尝试

  1. 查询到的相关缓存计划均为:

    BINDED=N RS_CAN_CACHED=N
  2. 在异常查询中增加以下 HINT,结果仍返回四行:

    /*+ SORT_ADAPTIVE_FLAG(0) */
    /*+ SORT_FLAG(0) SORT_ADAPTIVE_FLAG(0) */

    V$HINT_INI_INFO 显示这两个参数的 HINT_TYPE 均为 EXEC。

  3. 增加以下 HINT 后,结果仍为四行:

    /*+ FULL(l) FULL(s) FULL(c) FULL(r) */

    但 EXPLAIN 中仍然使用原二级索引,因此这次尝试没有形成有效的访问路径对照,尚不能据此排除索引访问路径相关问题。

  4. 排查期间未修改业务数据、重建索引或调整全局参数。

目前只确认相同 BIGINT 分组键出现重复分组,以及改变分组表达式后结果正常,尚未确定具体内部原因。谢谢。

回答 0
暂无回答
扫一扫
联系客服