查询sql特别慢,从4.3.2.1升级到4.3.5.2后

执行sql: SELECT
o.id,
o.topid,
o.card_id cardId,
SUBSTRING_INDEX( o.organizationname, ‘:C’, 1 ) AS organizationname,
o.parentid,
c.organizationname parent,
o.encoding encoding,
o.type,
o.organizationtype,
o.principal,
o.cascadeident,
o.is_external AS isExternal,
o.address,
o.lat,
o.lng,
o.address,
o.sort
FROM
ce_user_role_organization ur
LEFT JOIN ce_role r ON r.id = ur.roleid
LEFT JOIN ce_organization s ON s.id = ur.organizationid
LEFT JOIN ce_organization o ON o.cascadeident LIKE CONCAT( s.cascadeident, ‘%’ )
LEFT JOIN ce_organization c ON c.id = o.parentid
WHERE
r.DISABLE = 0
AND ur.userid = 1;

===================================================================================
|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)|

|0 |PX COORDINATOR | |2491 |37041 |
|1 |└─EXCHANGE OUT DISTR |:EX10001 |2491 |29030 |
|2 | └─HASH RIGHT OUTER JOIN | |2491 |11002 |
|3 | ├─TABLE FULL SCAN |c |1240 |57 |
|4 | └─NESTED-LOOP OUTER JOIN | |2487 |10345 |
|5 | ├─NESTED-LOOP OUTER JOIN | |7 |146 |
|6 | │ ├─EXCHANGE IN DISTR | |6 |50 |
|7 | │ │ └─EXCHANGE OUT DISTR (BC2HOST)|:EX10000 |6 |49 |
|8 | │ │ └─MERGE JOIN | |6 |47 |
|9 | │ │ ├─TABLE FULL SCAN |r |91 |11 |
|10| │ │ └─SORT | |6 |29 |
|11| │ │ └─TABLE RANGE SCAN |ur(userid) |6 |28 |
|12| │ └─TABLE GET |s |1 |16 |
|13| └─TABLE FULL SCAN |o(cascadeident)|413 |1685 |

Outputs & filters:

0 - output([INTERNAL_FUNCTION(o.id, o.topid, o.card_id, SUBSTRING_INDEX(o.organizationname, ‘:C’, 1), o.parentid, c.organizationname, o.encoding, o.type,
o.organizationtype, o.principal, o.cascadeident, o.is_external, o.address, o.lat, o.lng, o.address, o.sort)]), filter(nil), rowset=32
1 - output([INTERNAL_FUNCTION(o.id, o.topid, o.card_id, SUBSTRING_INDEX(o.organizationname, ‘:C’, 1), o.parentid, c.organizationname, o.encoding, o.type,
o.organizationtype, o.principal, o.cascadeident, o.is_external, o.address, o.lat, o.lng, o.address, o.sort)]), filter(nil), rowset=32
is_single, dop=1
2 - output([o.address], [o.parentid], [c.organizationname], [o.id], [o.cascadeident], [o.topid], [o.card_id], [o.organizationname], [o.encoding], [o.type],
[o.organizationtype], [o.principal], [o.is_external], [o.lat], [o.lng], [o.sort]), filter(nil), rowset=32
equal_conds([c.id = o.parentid]), other_conds(nil)
3 - output([c.id], [c.organizationname]), filter(nil), rowset=32
access([c.id], [c.organizationname]), partitions(p0)
is_index_back=false, is_global_index=false,
range_key([c.id]), range(MIN ; MAX)always true
4 - output([o.address], [o.parentid], [o.id], [o.cascadeident], [o.topid], [o.card_id], [o.organizationname], [o.encoding], [o.type], [o.organizationtype],
[o.principal], [o.is_external], [o.lat], [o.lng], [o.sort]), filter(nil), rowset=32
conds(nil), nl_params_([s.cascadeident(:4)]), use_batch=true
5 - output([s.cascadeident]), filter(nil), rowset=32
conds(nil), nl_params_([ur.organizationid(:2)]), use_batch=true
6 - output([ur.organizationid]), filter(nil), rowset=32
7 - output([ur.organizationid]), filter(nil), rowset=32
is_single, dop=1
8 - output([ur.organizationid]), filter(nil), rowset=32
equal_conds([cast(r.id, DECIMAL(20, 0)) = cast(ur.roleid, DECIMAL(-1, -1))]), other_conds(nil)
merge_directions([ASC])
9 - output([r.id]), filter([r.disable = 0]), rowset=32
access([r.id], [r.disable]), partitions(p0)
is_index_back=false, is_global_index=false, filter_before_indexback[false],
range_key([r.id]), range(MIN ; MAX)always true
10 - output([ur.organizationid], [cast(ur.roleid, DECIMAL(-1, -1))]), filter(nil), rowset=32
sort_keys([cast(ur.roleid, DECIMAL(-1, -1)), ASC])
11 - output([ur.organizationid], [cast(ur.roleid, DECIMAL(-1, -1))]), filter(nil), rowset=32
access([ur.id], [ur.roleid], [ur.organizationid]), partitions(p0)
is_index_back=true, is_global_index=false,
range_key([ur.userid], [ur.id]), range(1,MIN ; 1,MAX),
range_cond([ur.userid = 1])
12 - output([s.cascadeident]), filter(nil), rowset=32
access([GROUP_ID], [s.cascadeident]), partitions(p0)
is_index_back=false, is_global_index=false,
range_key([s.id]), range(MIN ; MAX),
range_cond([cast(s.id, DECIMAL(20, 0)) = cast(:2, DECIMAL(-1, -1))])
13 - output([o.id], [o.cascadeident], [o.parentid], [o.topid], [o.card_id], [o.organizationname], [o.encoding], [o.type], [o.organizationtype], [o.principal],
[o.is_external], [o.address], [o.lat], [o.lng], [o.sort]), filter([(T_OP_LIKE, o.cascadeident, CONCAT(:4, ‘%’), ‘\’)]), rowset=32
access([GROUP_ID], [o.id], [o.cascadeident], [o.parentid], [o.topid], [o.card_id], [o.organizationname], [o.encoding], [o.type], [o.organizationtype],
[o.principal], [o.is_external], [o.address], [o.lat], [o.lng], [o.sort]), partitions(p0)
is_index_back=true, is_global_index=false, filter_before_indexback[true],
range_key([o.cascadeident], [o.id]), range(MIN ; MAX);

乍一看 s o c 竟然是同一个表 。
https://www.modb.pro/db/1914145876138799104

可以改写成 with as 语法 看看。

ce_role ce_organization 相互关联的字段 都是走的 全表扫描??
先增加下索引看看吧。

顶一下

:+1: :+1:

这个设计是沿用的,之前是4.3.2.1,查询都在1秒内,现在升级了发现带like的都特别慢

试了cte这种,也不行

加了索引,的不顶用,下面这个是其他老版本oceanbase的,这个数据量还更大,查询很快

|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)|

|0 |NESTED-LOOP OUTER JOIN | |9 |562 |
|1 |├─NESTED-LOOP OUTER JOIN | |9 |431 |
|2 |│ ├─MERGE JOIN | |9 |180 |
|3 |│ │ ├─TABLE FULL SCAN |r |93 |11 |
|4 |│ │ └─SORT | |9 |161 |
|5 |│ │ └─NESTED-LOOP OUTER JOIN | |9 |160 |
|6 |│ │ ├─TABLE RANGE SCAN |ur(userid) |8 |31 |
|7 |│ │ └─DISTRIBUTED TABLE GET|s |1 |16 |
|8 |│ └─DISTRIBUTED TABLE FULL SCAN|o(cascadeident)|1 |31 |
|9 |└─DISTRIBUTED TABLE GET |c |1 |16 |

Outputs & filters:

0 - output([o.id], [o.topid], [o.card_id], [SUBSTRING_INDEX(o.organizationname, ‘:C’, 1)], [o.parentid], [c.organizationname], [o.encoding], [o.type],
[o.organizationtype], [o.principal], [o.cascadeident], [o.is_external], [o.address], [o.lat], [o.lng], [o.address], [o.sort]), filter(nil), rowset=256
conds(nil), nl_params_([o.parentid(:3)]), use_batch=true
1 - output([o.parentid], [o.id], [o.topid], [o.card_id], [o.encoding], [o.type], [o.organizationtype], [o.principal], [o.cascadeident], [o.is_external],
[o.address], [o.lat], [o.lng], [o.sort], [o.organizationname]), filter(nil), rowset=256
conds(nil), nl_params_([s.cascadeident(:4)]), use_batch=false
2 - output([s.cascadeident]), filter(nil), rowset=256
equal_conds([cast(r.id, DECIMAL(20, 0)) = cast(ur.roleid, DECIMAL(-1, -1))]), other_conds(nil)
merge_directions([ASC])
3 - output([r.id]), filter([r.disable = 0]), rowset=256
access([r.id], [r.disable]), partitions(p0)
is_index_back=false, is_global_index=false, filter_before_indexback[false],
range_key([r.id]), range(MIN ; MAX)always true
4 - output([s.cascadeident], [cast(ur.roleid, DECIMAL(-1, -1))]), filter(nil), rowset=256
sort_keys([cast(ur.roleid, DECIMAL(-1, -1)), ASC])
5 - output([s.cascadeident], [cast(ur.roleid, DECIMAL(-1, -1))]), filter(nil), rowset=256
conds(nil), nl_params_([ur.organizationid(:2)]), use_batch=true
6 - output([ur.roleid], [ur.organizationid]), filter(nil), rowset=256
access([ur.id], [ur.roleid], [ur.organizationid]), partitions(p0)
is_index_back=true, is_global_index=false,
range_key([ur.userid], [ur.id]), range(1,MIN ; 1,MAX),
range_cond([ur.userid = 1])
7 - output([s.cascadeident]), filter(nil), rowset=256
access([GROUP_ID], [s.cascadeident]), partitions(p0)
is_index_back=false, is_global_index=false,
range_key([s.id]), range(MIN ; MAX),
range_cond([cast(s.id, DECIMAL(20, 0)) = cast(:2, DECIMAL(-1, -1))])
8 - output([o.id], [o.cascadeident], [o.parentid], [o.topid], [o.card_id], [o.organizationname], [o.encoding], [o.type], [o.organizationtype], [o.principal],
[o.is_external], [o.address], [o.lat], [o.lng], [o.sort]), filter([(T_OP_LIKE, o.cascadeident, CONCAT(:4, ‘%’), ‘\’)]), rowset=256
access([o.id], [o.cascadeident], [o.parentid], [o.topid], [o.card_id], [o.organizationname], [o.encoding], [o.type], [o.organizationtype], [o.principal],
[o.is_external], [o.address], [o.lat], [o.lng], [o.sort]), partitions(p0)
is_index_back=true, is_global_index=false, filter_before_indexback[true],
range_key([o.cascadeident], [o.id]), range(MIN ; MAX)
9 - output([c.organizationname]), filter(nil), rowset=256
access([GROUP_ID], [c.organizationname]), partitions(p0)
is_index_back=false, is_global_index=false,
range_key([c.id]), range(MIN ; MAX),
range_cond([c.id = :3])

这几个表的 leader是在同一台 Observer上吧 ?? 这几个表是否有分区?

DISTRIBUTED TABLE RANGE SCAN 表示在查询执行时会对分布式表进行区间扫描。

TABLE get 是使用了主键或者唯一键 进行单行查询。 这两个执行计划说明 s c 肯定使用索引了吧

从资源评估上分析: 第一个的数据量要比 第二个的大吧。 est_rows 和 est.time时间数据量都比较大

收集下 统计信息 看看???

可能是ob4352上动态采样问题导致 是个已知问题 你先查看一下这个参数 show global variables optimizer_dynamic_sampling;
obdiag收一下 看看信息
日志采集场景: SQL性能问题
日志采集命令: obdiag gather scene run --scene=observer.perf_sql --env “{db_connect=’-h127.0.0.1 -P2881 -utest@test -p****** -Dtest’, trace_id=‘Yxx’}”

没有分区,是在一个节点,sc也有索引,o表没有索引。 统计信息怎么收集的

查出来是1

explain extended sql 具体的执行计划发一下 保存在文本里 不要直接发出来 太乱了
加一下 这个hint试一下/+dynamic_sampling(0)/ 关闭动态采样

区别不大,我连接代理执行同样的sql会慢很多,不连代理基本上1秒左右,连了有时候会7-8秒,基本上保持在3秒左右

具体的执行计划发出来 上面发的执行计划 信息太少了
explain extended sql 这样执行 信息提供全
obdiag收集一下 要不然 信息不全没有办法看具体的问题

新建 文本文档.txt (11.5 KB)

老师,怎么样,4352版本还有没有什么已知的会造成这种

是大部分都慢 还是个别语句查询性能降级了

都慢,一个简单的查询单表,对比其他版本会慢2倍

下载最新的obdiag 收集一下信息 有些信息 还要结合看看
–根据时间和执行语句查询trace_id
select query_sql,svr_ip,TRACE_ID,client_ip,TENANT_NAME,user_name,DB_NAME,ELAPSED_TIME,RET_CODE,FROM_UNIXTIME(ROUND(REQUEST_TIME/1000/1000),’%Y-%m-%d %H:%i:%S’) from GV$OB_SQL_AUDIT
WHERE REQUEST_TIME>=‘2024-04-05 14:34:00’ and lower(query_sql) like ‘%select%’;

SQL 详情收集

obdiag gather plan_monitor --trace_id YB420BA2D99B-0005EBBFC45D5A00-0-0 --env"{db_connect=’-hxx -Pxx -uxx -pxx -Dxx’}"