经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » SQL语言 » 查看文章
OceanBase 金融项目优化案例
来源:cnblogs  作者:小至尖尖  时间:2024/6/12 21:31:54  对本文有异议

领导让我帮忙支持下其他项目的SQL优化工作,呦西,是收集案例的好时候。??

下面SQL都是在不能远程的情况下,按照原SQL的逻辑等价改写完成否发给现场同事验证。


案例一

慢SQL,4.32秒:

  1. SELECT MY_.*, RM
  2. FROM (SELECT ROWNUM RM, V_.*
  3. FROM (SELECT *
  4. FROM (select count(1) processidnum,
  5. t.processid,
  6. t.proc_name_ as procname
  7. FROM tkdkdkdk t
  8. WHERE 1 = 1
  9. and (t.ASSIGNEE_ = 'server' or exists(select 1
  10. FROM pepepep p
  11. WHERE p.task_ = t.ID_
  12. and (p.agent_userid_ = 'server' or
  13. (substr(p.groupid_, 6) in
  14. (select role_code
  15. FROM upupupup
  16. WHERE user_code = 'server') or
  17. p.userid_ = 'server'))))
  18. GROUP BY t.processid, t.proc_name_)) V_
  19. WHERE ROWNUM <= 100000) MY_
  20. WHERE RM >= 1;

慢SQL执行计划:


 

 改写优化,445ms:

  1. SELECT *
  2. FROM (SELECT *
  3. FROM (SELECT a.*,
  4. rownum rn
  5. FROM (SELECT count(1) processidnum,
  6. t.processid,
  7. t.proc_name_ AS procname
  8. FROM tkdkdkdk t
  9. LEFT JOIN
  10. (SELECT distinct p.task_
  11. FROM pepepep p
  12. LEFT JOIN
  13. (SELECT role_code
  14. FROM upupupup
  15. WHERE user_code = 'server'
  16. GROUP BY role_code) tsu
  17. ON (substr(p.groupid_, 6) = tsu.role_code)
  18. WHERE (p.agent_userid_ = 'server'
  19. OR (tsu.role_code is NOT null
  20. OR p.userid_ = 'server'))) x
  21. ON t.ID_ = x.task_
  22. WHERE 1 = 1
  23. AND (t.ASSIGNEE_ = 'server'
  24. OR x.task_ is NOT NULL)
  25. GROUP BY t.processid, t.proc_name_) a)
  26. WHERE rownum <= 100000)
  27. WHERE rn >= 1;

改写优化后执行计划:

 优化思路:

  1、原SQL有很多子查询,可能会导致计划走NL,改成JOIN后让CBO自动判断是否走HASH还是NL。

  2、换了个标准的分页框架。


 案例二

慢SQL,2.6秒:

  1. SELECT MY_.*, RM
  2. FROM (SELECT ROWNUM RM, V_.*
  3. FROM (SELECT *
  4. FROM (select t.*, t.org_code || '-' || t.org_name as codename
  5. FROM (select tc.*
  6. FROM tgtgtgtg tc
  7. start with TC.ORG_ID = '6000001'
  8. connect by prior ORG_ID = tc.parent_id) t
  9. WHERE org_level <= 3
  10. ORDER BY CASE
  11. WHEN ',' || nvl(null, 'fingard') || ',' like '%,' || ORG_ID || ',%' THEN CASE
  12. WHEN length(nvl(org_order, '')) = '9'
  13. then org_order || ''
  14. else '1' || org_code end
  15. when length(nvl(org_order, '')) = '9' then '99999999' || org_order || ''
  16. else '999999991' || org_code end)) V_
  17. WHERE ROWNUM <= 10) MY_;
  18. WHERE RM >= 1;


 

 改写优化一,3.4秒:

  1. SELECT MY_.*, RM
  2. FROM (SELECT ROWNUM RM, V_.*
  3. FROM (SELECT *
  4. FROM (select a.*, a.org_code || '-' || a.org_name as codename
  5. FROM (WITH t(
  6. lv,
  7. codename,
  8. ORG_ID,
  9. parent_id,
  10. org_order,
  11. org_code,
  12. org_name,
  13. org_level
  14. ) AS (SELECT 1 as lv,
  15. tc.org_code || '-' || tc.org_name AS codename,
  16. tc.org_name,
  17. tc.ORG_ID,
  18. tc.parent_id,
  19. tc.org_order,
  20. tc.org_code,
  21. tc.org_level
  22. FROM tgtgtgtg tc
  23. WHERE tc.ORG_ID = '6000001'
  24. UNION ALL
  25. SELECT t.lv + 1,
  26. e.org_code || '-' || e.org_name AS codename,
  27. e.org_name,
  28. e.ORG_ID,
  29. e.parent_id,
  30. e.org_order,
  31. e.org_code,
  32. e.org_level
  33. FROM tgtgtgtg e
  34. INNER JOIN t ON t.ORG_ID = e.parent_id)
  35. SELECT *
  36. FROM t) a
  37. WHERE a.org_level <= 3
  38. ORDER BY CASE
  39. WHEN ',' || nvl(null, 'fingard') || ',' like '%,' || ORG_ID || ',%' THEN CASE
  40. WHEN length(nvl(org_order, '')) = '9'
  41. then org_order || ''
  42. else '1' || org_code end
  43. when length(nvl(org_order, '')) = '9' then '99999999' || org_order || ''
  44. else '999999991' || org_code end)) V_
  45. WHERE ROWNUM <= 10) MY_;
  46. WHERE RM >= 1;

使用CTE递归改写方案在PostgreSQL上是个通用的做法,也能取得比较好的性能效果。

但是在OB上反而效果更差点,NL算子性能不够强,使用NESTED-LOOP JOIN 性能反而没有NESTED-LOOP CONNECT BY 算子好。

OB研发在NESTED-LOOP JOIN算子上还有继续优化的空间。


 

 改写优化二,1.5秒:

既然使用NL性能不够理想的情况下,就要想办法使用HASH来优化SQL整体的执行效率。

将自动递归的方式改成手动。

 

1、首先需要知道数据整体的层级有多少。

  1. SELECT DISTINCT lv
  2. FROM (SELECT level lv
  3. FROM tgtgtgtg tc
  4. START WITH TC.ORG_ID = '6000001'
  5. CONNECT BY PRIOR ORG_ID = tc.parent_id) t;

 

2、了解到整体的数据是13层,然后使用self join 将不同层级的数据关联起来。

  1. SELECT *
  2. FROM (SELECT *
  3. FROM (SELECT a.*, rownum rn
  4. FROM (SELECT x.*
  5. FROM (WITH tgtgtgtg AS
  6. (SELECT org_code, org_name, org_id, parent_id, org_order, org_level
  7. FROM tgtgtgtg)
  8. SELECT 1 AS lv,
  9. v1.org_code || '-' || v1.org_name AS codename,
  10. v1.ORG_ID,
  11. v1.parent_id,
  12. v1.org_order,
  13. v1.org_code,
  14. v1.org_level
  15. FROM tgtgtgtg v1
  16. WHERE v1.ORG_ID = '6000001'
  17.  
  18. UNION ALL
  19.  
  20. SELECT 2 AS lv,
  21. v2.org_code || '-' || v2.org_name AS codename,
  22. v2.ORG_ID,
  23. v2.parent_id,
  24. v2.org_order,
  25. v2.org_code,
  26. v2.org_level
  27. FROM tgtgtgtg v1
  28. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  29. WHERE v1.ORG_ID = '6000001'
  30.  
  31. UNION ALL
  32.  
  33. SELECT 3 AS lv,
  34. v3.org_code || '-' || v3.org_name AS codename,
  35. v3.ORG_ID,
  36. v3.parent_id,
  37. v3.org_order,
  38. v3.org_code,
  39. v3.org_level
  40. FROM tgtgtgtg v1
  41. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  42. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  43. WHERE v1.ORG_ID = '6000001'
  44.  
  45. UNION ALL
  46.  
  47. SELECT 4 AS lv,
  48. v4.org_code || '-' || v4.org_name AS codename,
  49. v4.ORG_ID,
  50. v4.parent_id,
  51. v4.org_order,
  52. v4.org_code,
  53. v4.org_level
  54. FROM tgtgtgtg v1
  55. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  56. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  57. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  58. WHERE v1.ORG_ID = '6000001'
  59.  
  60. UNION ALL
  61.  
  62. SELECT 5 AS lv,
  63. v5.org_code || '-' || v5.org_name AS codename,
  64. v5.ORG_ID,
  65. v5.parent_id,
  66. v5.org_order,
  67. v5.org_code,
  68. v5.org_level
  69. FROM tgtgtgtg v1
  70. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  71. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  72. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  73. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  74. WHERE v1.ORG_ID = '6000001'
  75.  
  76. UNION ALL
  77.  
  78. SELECT 6 AS lv,
  79. v6.org_code || '-' || v6.org_name AS codename,
  80. v6.ORG_ID,
  81. v6.parent_id,
  82. v6.org_order,
  83. v6.org_code,
  84. v6.org_level
  85. FROM tgtgtgtg v1
  86. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  87. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  88. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  89. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  90. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  91. WHERE v1.ORG_ID = '6000001'
  92.  
  93. UNION ALL
  94.  
  95. SELECT 7 AS lv,
  96. v7.org_code || '-' || v7.org_name AS codename,
  97. v7.ORG_ID,
  98. v7.parent_id,
  99. v7.org_order,
  100. v7.org_code,
  101. v7.org_level
  102. FROM tgtgtgtg v1
  103. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  104. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  105. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  106. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  107. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  108. JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
  109. WHERE v1.ORG_ID = '6000001'
  110.  
  111. UNION ALL
  112.  
  113. SELECT 8 AS lv,
  114. v8.org_code || '-' || v8.org_name AS codename,
  115. v8.ORG_ID,
  116. v8.parent_id,
  117. v8.org_order,
  118. v8.org_code,
  119. v8.org_level
  120. FROM tgtgtgtg v1
  121. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  122. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  123. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  124. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  125. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  126. JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
  127. JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
  128. WHERE v1.ORG_ID = '6000001'
  129.  
  130. UNION ALL
  131.  
  132. SELECT 9 AS lv,
  133. v9.org_code || '-' || v9.org_name AS codename,
  134. v9.ORG_ID,
  135. v9.parent_id,
  136. v9.org_order,
  137. v9.org_code,
  138. v9.org_level
  139. FROM tgtgtgtg v1
  140. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  141. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  142. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  143. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  144. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  145. JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
  146. JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
  147. JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
  148. WHERE v1.ORG_ID = '6000001'
  149.  
  150. UNION ALL
  151.  
  152. SELECT 10 AS lv,
  153. v10.org_code || '-' || v10.org_name AS codename,
  154. v10.ORG_ID,
  155. v10.parent_id,
  156. v10.org_order,
  157. v10.org_code,
  158. v10.org_level
  159. FROM tgtgtgtg v1
  160. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  161. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  162. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  163. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  164. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  165. JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
  166. JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
  167. JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
  168. JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
  169. WHERE v1.ORG_ID = '6000001'
  170.  
  171. UNION ALL
  172.  
  173. SELECT 11 AS lv,
  174. v11.org_code || '-' || v11.org_name AS codename,
  175. v11.ORG_ID,
  176. v11.parent_id,
  177. v11.org_order,
  178. v11.org_code,
  179. v11.org_level
  180. FROM tgtgtgtg v1
  181. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  182. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  183. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  184. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  185. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  186. JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
  187. JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
  188. JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
  189. JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
  190. JOIN tgtgtgtg v11 ON v10.ORG_ID = v11.parent_id
  191. WHERE v1.ORG_ID = '6000001'
  192.  
  193. UNION ALL
  194.  
  195. SELECT 12 AS lv,
  196. v12.org_code || '-' || v12.org_name AS codename,
  197. v12.ORG_ID,
  198. v12.parent_id,
  199. v12.org_order,
  200. v12.org_code,
  201. v12.org_level
  202. FROM tgtgtgtg v1
  203. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  204. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  205. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  206. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  207. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  208. JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
  209. JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
  210. JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
  211. JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
  212. JOIN tgtgtgtg v11 ON v10.ORG_ID = v11.parent_id
  213. JOIN tgtgtgtg v12 ON v11.ORG_ID = v12.parent_id
  214. WHERE v1.ORG_ID = '6000001'
  215.  
  216. UNION ALL
  217.  
  218. SELECT 13 AS lv,
  219. v13.org_code || '-' || v13.org_name AS codename,
  220. v13.ORG_ID,
  221. v13.parent_id,
  222. v13.org_order,
  223. v13.org_code,
  224. v13.org_level
  225. FROM tgtgtgtg v1
  226. JOIN tgtgtgtg v2 ON v1.ORG_ID = v2.parent_id
  227. JOIN tgtgtgtg v3 ON v2.ORG_ID = v3.parent_id
  228. JOIN tgtgtgtg v4 ON v3.ORG_ID = v4.parent_id
  229. JOIN tgtgtgtg v5 ON v4.ORG_ID = v5.parent_id
  230. JOIN tgtgtgtg v6 ON v5.ORG_ID = v6.parent_id
  231. JOIN tgtgtgtg v7 ON v6.ORG_ID = v7.parent_id
  232. JOIN tgtgtgtg v8 ON v7.ORG_ID = v8.parent_id
  233. JOIN tgtgtgtg v9 ON v8.ORG_ID = v9.parent_id
  234. JOIN tgtgtgtg v10 ON v9.ORG_ID = v10.parent_id
  235. JOIN tgtgtgtg v11 ON v10.ORG_ID = v11.parent_id
  236. JOIN tgtgtgtg v12 ON v11.ORG_ID = v12.parent_id
  237. JOIN tgtgtgtg v13 ON v12.ORG_ID = v13.parent_id
  238. WHERE v1.ORG_ID = '6000001') x
  239. WHERE org_level <= 3
  240. ORDER BY CASE
  241. WHEN ',' || NVL(NULL, 'fingard') || ',' LIKE '%,' || ORG_ID || ',%' THEN
  242. CASE
  243. WHEN LENGTH(NVL(org_order, '')) = '9' THEN
  244. org_order || ''
  245. ELSE '1' || org_code
  246. END
  247. WHEN LENGTH(NVL(org_order, '')) = '9' THEN
  248. '99999999' || org_order || ''
  249. ELSE '999999991' || org_code END ) a)
  250. WHERE rownum <= 10)
  251. WHERE rn >= 1;

现场同学差集比较,确认改写后的SQL是等价的,执行时间从2.6秒降低到1.5秒能跑出结果。

原来18行的SQL改成了250多行后才优化了1秒的执行时间,实在没其他办法了,希望OB产研后续能CBO算子继续优化下。??????

原文链接:https://www.cnblogs.com/yuzhijian/p/18244465

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号