遇到慢SQL、SQL报错,应怎样快速定位题目 | OceanBase优化实践

[复制链接]
发表于 2026-1-16 07:46:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
在数据库的利用中,各人时常会遇到慢SQL,或实行堕落的SQL。对于某些SQL题目,其错误缘故原由显而易见,但也有不少情况难以直观判断。面临这类题目,我们应当怎样应对?怎样正确辨认SQL错误的根源?是否须要优化SQL本身?照旧数据库的设置存在不敷?接下来,将扼要先容怎样敏捷定位SQL题目的战略。
但在深入探究之前,让我们先一同相识,当一条SQL语句进入OceanBase数据库体系实行时,它毕竟会颠末哪些模块和路径。

访问路径

起首我们从SQL的访问路径开始先容,一条SQL从应用发出之后,一样平常会颠末负载平衡(根据情况选择是否须要),然后到OBProxy,然后再到OBServer。大概流程如下图所示:


OBProxy重要起到一个路由转发的作用,以及快速分析,根据OceanBase数据库中数据副天职布情况,直接将哀求快速发送到对应的OBServer上。
SQL在进入OBServer之后,还会履历数据库内部很多模块,详细如下:


SQL的在数据库内部的实行过程,这些模块详细的寄义,可以参考官网文档:SQL 哀求实行流程,在整个SQL实行过程中,会起首根据SQL的ip、port、自增序列号等信息天生一个全局唯一的trace_id,后续的sql跟踪,我们都利用这个trace_id来对sql举行定位追踪。

SQL错误

这种题目一样平常都比力优点理,大多都是sql写的格式不对,大概库、表、列名等不存在,大概OceanBase语法不支持等,一样平常情况,根据返回的错误信息,就大抵可以判断堕落误缘故原由。
但也有一些很埋伏的错误,一时很难判断出详细是那边错了,这个时间就要借助错误日志日志来资助我们举行判断了,这里就举一个例子,这是在一个用户那边实着实在遇到的题目,用户的场景比力复杂,拿OceanBase用来做数据的洗濯,将多张表举行关联盘算,然后将数据写入到结果表中,而在实行此中一条SQL过程中,收到了如许一个报错:
  1. ERROR 1292 (22007): Incorrect value
复制代码
当时用户收到这个报错后很茫然,由于用户的SQL长达200多行,而且有多层嵌套子查询和多张表关联查询,以是一时间很难判断出来是那边出现了错误,SQL大抵如下(脱敏后):
  1. REPLACE INTO abc.table1(
  2.   m_id,
  3.   st_id,
  4.   con_id,
  5.   `date`,
  6.   t_ord,
  7.   t_role,
  8.   tag,
  9.   con_pri,
  10.   con_qu,
  11.   con_in,
  12.   update_time
  13. )
  14. SELECT
  15.         tmp5.m_id,
  16.         tmp5.st_id,
  17.         tmp5.con_id,
  18.         tmp5.`date`,
  19.         tmp5.t_ord_96,
  20.         tmp5.t_role,
  21.         tmp5.tag,
  22.         cast(sum(tmp5.con_pri) as decimal(20,6)) as con_pri,
  23.         cast(sum(tmp5.con_qu) as decimal(20,6)) as con_qu,
  24.         cast(sum(tmp5.con_in) as decimal(20,6)) as con_in,
  25.         current_timestamp
  26. FROM
  27.         (
  28.     SELECT
  29.     tmp4.m_id,
  30.     tmp4.st_id,
  31.     tmp4.con_id,
  32.     tmp4.`date`,
  33.     tmp4.t_ord,
  34.     dstl2.t_ord_96,
  35.     tmp4.t_role,
  36.     tmp4.tag,
  37.     case
  38.     when tmp4.t_ord = dstl2.t_ord_96 then con_pri
  39.     else 0
  40.     end as con_pri,
  41.     case
  42.     when tmp4.t_ord = dstl2.t_ord_96 then con_qu
  43.     else 0
  44.     end as con_qu,
  45.     case
  46.     when tmp4.t_ord = dstl2.t_ord_96 then con_in
  47.     else 0
  48.     end as con_in
  49.     FROM
  50.     (
  51.       SELECT
  52.       tmp3.m_id,
  53.       tmp3.st_id,
  54.       tmp3.con_id,
  55.       tmp3.`date`,
  56.       tmp3.t_ord_96 as t_ord,
  57.       tmp3.t_role,
  58.       tmp3.tag,
  59.       tmp3.con_pri,
  60.       cast(tmp3.con_qu as decimal(20,6)) as con_qu,
  61.       cast(tmp3.con_qu * tmp3.con_pri as decimal(20,6)) as con_in
  62.       FROM
  63.       (
  64.         SELECT
  65.         tmp2.m_id,
  66.         tmp2.st_id,
  67.         tmp2.con_id,
  68.         tmp2.`date`,
  69.         tmp2.t_ord_96,
  70.         case
  71.         when tmp2.con_name like '%xxx%' then 1
  72.         when tmp2.con_name like '%x%' then 2
  73.         when tmp2.con_name like '%xx%' then 3
  74.         else
  75.         case
  76.         when tmp2.contract_type_name like '%xx%' then 4
  77.         else 5
  78.         end
  79.         end as tag,
  80.         case
  81.         when tmp2.con_name like '%xxxxx%' then tmp2.vendee_price
  82.         else tmp2.sale_price
  83.         end as con_pri,
  84.         case
  85.         when tmp2.con_name like '%xxxxx%' then tmp2.vendee_energy
  86.         else tmp2.sale_energy
  87.         end as con_qu,
  88.         tmp2.t_role
  89.         FROM
  90.         (
  91.           select
  92.           tmp.m_id,
  93.           tmp.st_id,
  94.           tmp.st_name,
  95.           tmp.member_id,
  96.           tmp.con_id,
  97.           tmp.con_name,
  98.           dd.`date`,
  99.           tmp.t_ord_96,
  100.           tmp.sale_energy / (datediff(tmp.timepart_endtime, tmp.timepart_starttime) + 1) / tmp.re as sale_energy,
  101.           tmp.sale_price,
  102.           tmp.vendee_energy / (datediff(tmp.timepart_endtime, tmp.timepart_starttime) + 1) / tmp.re as vendee_energy,
  103.           tmp.vendee_price,
  104.           tmp.timepart_starttime,
  105.           tmp.timepart_endtime,
  106.           tmp.seller_member_name,
  107.           tmp.contract_type_name,
  108.           tmp.t_role
  109.           from
  110.           (
  111.             select
  112.             tmp1.*,
  113.             dstl.t_ord_96,
  114.             count(1) over(PARTITION by member_id, con_id, time_division_range, timepart_endtime, timepart_starttime) as re
  115.             from
  116.             (
  117.               select
  118.               distinct
  119.               spcdp.m_id,
  120.               ds.st_id,
  121.               ds.st_name,
  122.               spcdp.member_id,
  123.               spcdp.con_id,
  124.               dc.con_name,
  125.               spcdp.sale_energy,
  126.               spcdp.sale_price,
  127.               spcdp.vendee_energy,
  128.               spcdp.vendee_price,
  129.               spcdp.time_division_code,
  130.               spcdp.time_division_name,
  131.               case
  132.               when dc.con_name like '%xx%' then
  133.               case
  134.               when substr(date_add(cast(concat('2022-10-01 ', right(spcdp.time_division_range, 5), ':00') as datetime), interval 1 hour), 12, 5) = '00:00' then concat(left(spcdp.time_division_range, 6), '24:00')
  135.               else concat(left(spcdp.time_division_range, 6), substr(date_add(cast(concat('2022-10-01 ', right(spcdp.time_division_range, 5), ':00') as datetime), interval 1 hour), 12, 5))
  136.               end
  137.               else spcdp.time_division_range
  138.               end as time_division_range,
  139.               spcdp.timepart_endtime,
  140.               spcdp.timepart_starttime,
  141.               dc.seller_member_name,
  142.               dc.contract_type_name,
  143.               case
  144.               when locate('x',dc.con_name) > 0 then 1
  145.               when locate('x',dc.con_name) > 0 then 2
  146.               else if(dc.con_qu>0,2,1)
  147.               end as t_role
  148.               from
  149.               (select distinct m_id, member_id, con_id, sale_energy, sale_price, vendee_energy, vendee_price, time_division_code, time_division_name, time_division_range, timepart_endtime, timepart_starttime from
  150.                select
  151.                DISTINCT
  152.                if(spcdp.m_id is null,spcdpa.m_id,spcdp.m_id) as m_id,
  153.                if(spcdp.member_id is null,spcdpa.member_id,spcdp.member_id) as member_id,
  154.                if(spcdp.con_id is null,spcdpa.con_id,spcdp.con_id) as con_id,
  155.                if(spcdp.sa
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表