反馈已提交

网络繁忙

定时任务执行慢问题排查

  • 文档创建者:Wendy123456
  • 历史版本:2
  • 最近更新:Wendy123456 于 2025-11-04
  • 1. 概述

    注:若出现定时任务卡住、排队的问题,请参见:定时任务排队问题排查方案

    定时任务运行后或者运行过程中,发现定时任务执行的非常慢,从前端页面看任务执行了很久,读写速度那边也基本为0B/s。

    24.png

    25.png

    2. 判断是读取慢还是写入慢

    2.1 任务正在执行

    1)先终止该定时任务的执行。

    将该定时任务的日志等级设置为 INFO,用于记录定时任务的读写明细。保存之后重启一下任务,开始记录。

    26.png

    2)执行一段时间后,下载日志开始分析。

    27.png

    3)根据用户查询与输出的 SQL 定位任务日志的位置。

    28.png

    从上面的截图我们可以看出需要该任务对应的任务名称是job[22]。然后我们往下翻,能看到job[22]任务的读写情况。

    29.png

    数据来源代表表输入、数据去向代表表输出。因为我们的同步过程是流式的,所以可以看到一个任务拆成了多个读取与写入。

    然后看后面的 waittime。数据来源的 waittime 代表目前在等待数据完成写入,数据去向的 waittime 代表目前正在等待数据完成读取。哪个时间大,说明在等待另一个线程完成对应的任务。

    从上面我们可以看出数据来源的时间比数据去向大很多,说明当前任务卡在了数据写入的状态下。

    因此我们需要进一步排查。

    2.2 任务执行完毕

    直接看历史运维记录的统计,看是输入还是输出慢。

    31.png

    3. 读取慢排查步骤

    1)测带宽

    选择一张有一定数据量(数据量过大可以截取 3W 数据)的简单表进行数据同步,等运行结束之后查看表输入带宽。如果带宽在3~4MB/s,说明读取带宽没有问题。

    34.png

    如果带宽较小,则需要沟通是否可以切换内网忽略带宽问题或者增加公网的带宽。

    2)使用并行取数

    针对数据基数较大的表,可能初始读取速度会较慢。表现现象为输入、输出0行/s的等待时间稍微有点长。

    此时我们可以使用 并行读取 功能,通过切分键将数据拆成多个同步任务。降低部分步骤初始等待时间。

    3)是否因为数据库锁,导致查询不返回

    通过查询 SQL 运行状态,查看是否被数据库锁住(locaked)。根据锁的类型判断如何进行优化。

    4)优化 SQL 语句

    优化SQL
    说明
    对过滤字段增加索引通过对 Where 字段增加索引的方式,加快速度读取

    索引查询从最左侧的索引列开始,避免跳过中间的索引列

    范围查询放到最后

    SELECT 子句中避免使用 “*”  

    当你想在 SELECT 子句中列出所有的 columns 时,使用动态 SQL 列引用‘*’是一个方便的方法

    不幸的是,这是一个非常低效的方法。 实际上,Oracle 在解析的过程中, 会将“*” 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间

    left join小表在前把重复关联键少的表放在 join 前面做关联可以提高 join 的效率
    计算记录条数 和一般的观点相反count(*) count(1)稍快,当然如果可以通过索引检索,对索引列的计数仍旧是最快的。例如 COUNT(EMPNO) 
    删除重复记录(使用了 ROWIDDELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO)
    用 TRUNCATE 替代 DELETE 当删除表中的记录时,在通常情况下,回滚段(rollback segments)用来存放可以被恢复的信息。如果你没有 COMMIT 事务,Oracle 会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况),而当运用 TRUNCATE 时, 回滚段不再存放任何可被恢复的信息。当命令运行后,数据不能被恢复。因此很少的资源被调用,执行时间也会很短
    用 >= 替代 >

    例如 DEPTNO 上有一个索引: 

    高效:

    SELECT *  FROM EMP  WHERE DEPTNO >=4  

    低效:

    SELECT *  FROM EMP   WHERE DEPTNO >3

    用 EXISTS 替代 IN在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,使用 EXISTS 或 NOT EXISTS 可以提高查询的效率。例如:

    低效:

    SELECT * FROM EMP WHERE EMPNO > 0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT WHERE LOC ='MELB')

    高效:

    SELECT * FROM EMP WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’  FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = 'MELB')

    用 EXISTS 替换 DISTINCT  

    当提交一个包含一对多表信息( 比如部门表和雇员表 )的查询时,避免在 SELECT 子句中使用 DISTINCT, 一般可以考虑用 EXIST 替换。例如:

    低效:     

    SELECT DISTINCT DEPT_NO,DEPT_NAME  FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO 

    高效:  

    SELECT DEPT_NO,DEPT_NAME  FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO)

    应尽量避免在 where 子句中对字段判断

    例如:

    select id from t where num is null

    可以在 num 上设置默认值 0,确保表中 num 列没有 null 值,然后这样查询:

    select id from t where num=0

    应避免在 where 中使用 != 或 <> 操作符将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。
    应避免在 where 子句中使用 or 连接

    否则将导致引擎放弃使用索引而进行全表扫描,例如:

    select id from t where num=10 or num=20

    可以这样查询:

    select id from t where num=10 union all select id from t where num=20

    in 和 not in 也要慎用

    因为 IN 会使系统无法使用索引,而只能直接搜索表中的数据。例如:

    select id from t where num in(1,2,3)

    对于连续的数值,能用 between 就不要用 in 了:

    select id from t where num between 1 and 3

    应避免在 where 中进行表达式操作这将导致引擎放弃使用索引而进行全表扫描。例如:
    • SELECT * FROM T1 WHERE F1/2=100应改为:SELECT * FROM T1 WHERE F1=100*2

    • SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)='5378'应改为:SELECT * FROM RECORD WHERE CARD_NO LIKE '5378%'

    • SELECT member_number, first_name, last_name FROM members WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21应改为:SELECT member_number, first_name, last_name FROM members WHERE dateofbirth < DATEADD(yy,-21,GETDATE())

    注:任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。

    应避免在 where 子句中进行函数操作

    这将导致引擎放弃使用索引而进行全表扫描。例如:

    • name 以 abc 开头的 id:select id from t where substring(name,1,3)='abc'应改为:select id from t where name like 'abc%'

    • '2005-11-30'生成的 id:select id from t where datediff(day,createdate,'2005-11-30')=0应改为:select id from t where createdate>=’2005-11-30′ and createdate<'2005-12-1'

    不要在 where 中的“=”左边运算进行函数、算术运算或其他表达式运算,系统将可能无法正确使用索引。
    充分利用连接条件

    在某种情况下,两个表之间可能不只一个的连接条件,这时在 WHERE 子句中将连接条件完整的写上,有可能大大提高查询速度。例如:

    SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO

    SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO

    第二句将比第一句执行快得多

    能用 GROUP BY 就不用 DISTINCT

    SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10

    可改为:

    SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BY OrderID

    能用 UNION ALL 就不要用 UNIONUNION ALL 不执行 SELECT DISTINCT 函数,这样就会减少很多不必要的资源
    尽量不要用 SELECT INTO 语句SELECT INTO 语句会导致表锁定,阻止其他用户访问该表

    5)测试是否为驱动问题

    在驱动网站查找较高或者较低版本的数据库驱动,测试读取速度。

    6)是否为数据库自身问题

    Greenplum 可能会有系统或者业务表膨胀问题导致读取速度越使用越慢,需要定期处理业务表膨胀。

    7)测试是否为FDL问题

    使用服务器数据集,通过数据集输入测试读取速度。

    8)还是排查不出原因,找技术支持协助或社区问答进行协助。

    4. 写入慢排查步骤

    1)上行带宽

    选择一张有一定数据量(数据量过大可以截取3W数据)的简单表使用自动建表无主键方式进行写入,测试写入带宽是否在3~4MB/s。

    2)数据库主键

    整体数据同步速率:无物理主键+直接写入>大数据量的数据比对更新(个别数据库逻辑可能不符,比如sr、doris)~中等数据量的物理主键直接覆盖>逻辑主键直接覆盖

    所以有时可将逻辑主键修改为物理主键,或者新增物理主键,写入速度会提升。

    • 主键设置不合理。select count(*) from 来源表与目标表数量不匹配。

    • select 主键字段,count(*) from (select count(*) from 来源表) a group by 主键字段,发现按照主键字段数据不唯一。说明来源端的数据在写入目标表时,一直在按照主键进行数据覆盖。如果来源表数据量很大的话,会导致写入速度非常慢。

    3)数据写入方式

    使用清空导入并且存在物理主键时,也会按照上面自己覆盖自己的方式进行数据写入导致速度很慢。

    4)写入语句锁表

    当触发表级锁或者行级锁,或者清空写入执行 truncate 被锁表时,会导致写入速度非常慢。

    5)数据库特性

    • Clickhouse 主键更新慢,建议使用数据比对更新。

    6)是否为数据库自身问题

    Greenplum 可能会有系统或者业务表膨胀问题导致写入速度越使用越慢,需要定期处理业务表膨胀。




    附件列表


    主题: 运维中心
    • 有帮助
    • 没帮助
    • 只是浏览
    中文(简体)

    鼠标选中内容,快速反馈问题

    鼠标选中存在疑惑的内容,即可快速反馈问题,我们将会跟进处理。

    不再提示

    10s后关闭



    AI

    联系我们
    在线支持
    获取专业技术支持,快速帮助您解决问题
    工作日9:00-12:00,13:30-17:30在线
    页面反馈
    针对当前网页的建议、问题反馈
    售前咨询
    采购需求/获取报价/预约演示
    或拨打: 400-811-8890 转1
    qr
    热线电话
    咨询/故障救援热线:400-811-8890转2
    总裁办24H投诉:17312781526
    提交页面反馈
    仅适用于当前网页的意见收集,帆软产品问题请在 问答板块提问前往服务平台 获取技术支持