数仓实践丨常量标量子查询做全连接导致整体慢

打印 上一主题 下一主题

主题 496|帖子 496|积分 1488

本文分享自华为云社区《GaussDB(DWS)性能调优:常量标量子查询做全连接导致整体慢》,作者: Zawami 。
问题描述

由于SQL中存在标量子查询同另一查询做笛卡尔积使SQL整体慢。标量子查询,即结果集只有一行一列的子查询。这里导致的SQL语句执行慢不只是在于做笛卡尔积慢,也会使后续聚合更慢。
原始语句
  1. WITH TMP AS(
  2. SELECT
  3. case
  4. when length('[“202309“]') = 6 then '[“202309“]' || '01'
  5. WHEN length('[“202309“]') <> 8 THEN TO_CHAR(CURRENT_DATE, 'YYYYMMDD')
  6. END AS V_DATE
  7. from
  8. DUAL
  9. )
  10. SELECT
  11. BG_CODE,
  12. BG_CN_NAME,
  13. BG_EN_NAME,
  14. METRIC_CODE --指标ID
  15. ,
  16. METRIC_CN_NAME --指标中文名称
  17. ,
  18. METRIC_EN_NAME --指标英文名称
  19. ,
  20. CURRENCY --币种
  21. ,
  22. OVERSEAS_FLAG,
  23. REGION_CODE,
  24. REGION_CN_NAME,
  25. REGION_EN_NAME,
  26. REPOFFICE_CODE,
  27. REPOFFICE_CN_NAME,
  28. REPOFFICE_EN_NAME,
  29. OFFICE_CODE,
  30. OFFICE_CN_NAME,
  31. OFFICE_EN_NAME,
  32. REGION_CUSTCATG_CODE,
  33. REGION_CUSTCATG_CN_NAME,
  34. REGION_CUSTCATG_EN_NAME,
  35. TOP_CUST_CATEGORY_CODE,
  36. TOP_CUST_CATEGORY_EN_NAME,
  37. TOP_CUST_CATEGORY_CN_NAME,
  38. ACCTCUST_HQ_CODE,
  39. ACCTCUST_HQ_CN_NAME,
  40. ACCTCUST_HQ_EN_NAME,
  41. ACCTCUST_BRANCH_CODE,
  42. ACCTCUST_BRANCH_CN_NAME,
  43. ACCTCUST_BRANCH_EN_NAME,
  44. ACCTCUST_SUBSIDIARY_CODE,
  45. ACCTCUST_SUBSIDIARY_CN_NAM,
  46. ACCTCUST_SUBSIDIARY_EN_NAM,
  47. COUNTRY_CODE --新增加入参
  48. ,
  49. COUNTRY_CN_NAME --新增加入参
  50. ,
  51. COUNTRY_EN_NAME --新增加入参
  52. ,
  53. AGREE_AMOUNT --BUSI_DSCT_00001 总优惠
  54. ,
  55. AGREE_REMAIN_AMOUNT --BUSI_DSCT_00002 即期优惠
  56. ,
  57. SIGN_AMOUNT --BUSI_DSCT_00003 即期优惠/一次性优惠
  58. ,
  59. USE_AMOUNT --BUSI_DSCT_00004 即期优惠/单价量折扣
  60. ,
  61. NOT_USED_VALID_AMOUNT --BUSI_DSCT_00005 延期优惠
  62. ,
  63. NOT_USED_INVALID_AMOUNT --BUSI_DSCT_00006 voucher
  64. ,
  65. NEW_SIGN_AMOUNT --BUSI_DSCT_00007 其他延期优惠
  66. ,
  67. NEW_USE_AMOUNT --BUSI_DSCT_00008 本月新使用金额
  68. ,
  69. EXPIRED_AMOUNT --BUSI_DSCT_00009 本月已过期金额
  70. ,
  71. IMMED_EXPIRED_AMOUNT --BUSI_DSCT_00010 半年内即将过期金额
  72. FROM
  73. (
  74. SELECT
  75. C.BG_CODE,
  76. C.BG_CN_NAME,
  77. C.BG_EN_NAME,
  78. C.M_ID AS METRIC_CODE --指标ID
  79. ,
  80. C.M_CN AS METRIC_CN_NAME --指标中文名称
  81. ,
  82. C.M_EN AS METRIC_EN_NAME --指标英文名称
  83. ,
  84. C.CURRENCY_CODE AS CURRENCY --币种
  85. ,CASE
  86. WHEN 1 = 0 THEN C.OVERSEA_FLAG
  87. ELSE NULL
  88. END AS OVERSEAS_FLAG,CASE
  89. WHEN 1 = 0 THEN C.REGION_CODE
  90. ELSE NULL
  91. END AS REGION_CODE,CASE
  92. WHEN 1 = 0 THEN C.REGION_CN_NAME
  93. ELSE NULL
  94. END AS REGION_CN_NAME,CASE
  95. WHEN 1 = 0 THEN C.REGION_EN_NAME
  96. ELSE NULL
  97. END AS REGION_EN_NAME,CASE
  98. WHEN 1 = 0 THEN C.REPOFFICE_CODE
  99. ELSE NULL
  100. END AS REPOFFICE_CODE,CASE
  101. WHEN 1 = 0 THEN C.REPOFFICE_CN_NAME
  102. ELSE NULL
  103. END AS REPOFFICE_CN_NAME,CASE
  104. WHEN 1 = 0 THEN C.REPOFFICE_EN_NAME
  105. ELSE NULL
  106. END AS REPOFFICE_EN_NAME,CASE
  107. WHEN 1 = 0 THEN C.OFFICE_CODE
  108. ELSE NULL
  109. END AS OFFICE_CODE,CASE
  110. WHEN 1 = 0 THEN C.OFFICE_CN_NAME
  111. ELSE NULL
  112. END AS OFFICE_CN_NAME,CASE
  113. WHEN 1 = 0 THEN C.OFFICE_EN_NAME
  114. ELSE NULL
  115. END AS OFFICE_EN_NAME,CASE
  116. WHEN 1 = 0 THEN C.REGION_CUSTCATG_CODE
  117. ELSE NULL
  118. END AS REGION_CUSTCATG_CODE,CASE
  119. WHEN 1 = 0 THEN C.REGION_CUSTCATG_CN_NAME
  120. ELSE NULL
  121. END AS REGION_CUSTCATG_CN_NAME,CASE
  122. WHEN 1 = 0 THEN C.REGION_CUSTCATG_EN_NAME
  123. ELSE NULL
  124. END AS REGION_CUSTCATG_EN_NAME,CASE
  125. WHEN 1 = 0 THEN C.TOP_CUST_CATEGORY_CODE
  126. ELSE NULL
  127. END AS TOP_CUST_CATEGORY_CODE,CASE
  128. WHEN 1 = 0 THEN C.TOP_CUST_CATEGORY_EN_NAME
  129. ELSE NULL
  130. END AS TOP_CUST_CATEGORY_EN_NAME,CASE
  131. WHEN 1 = 0 THEN C.TOP_CUST_CATEGORY_CN_NAME
  132. ELSE NULL
  133. END AS TOP_CUST_CATEGORY_CN_NAME,CASE
  134. WHEN 1 = 0 THEN C.ACCTCUST_HQ_CODE
  135. ELSE NULL
  136. END AS ACCTCUST_HQ_CODE,CASE
  137. WHEN 1 = 0 THEN C.ACCTCUST_HQ_CN_NAME
  138. ELSE NULL
  139. END AS ACCTCUST_HQ_CN_NAME,CASE
  140. WHEN 1 = 0 THEN C.ACCTCUST_HQ_EN_NAME
  141. ELSE NULL
  142. END AS ACCTCUST_HQ_EN_NAME,CASE
  143. WHEN 1 = 0 THEN C.ACCTCUST_BRANCH_CODE
  144. ELSE NULL
  145. END AS ACCTCUST_BRANCH_CODE,CASE
  146. WHEN 1 = 0 THEN C.ACCTCUST_BRANCH_CN_NAME
  147. ELSE NULL
  148. END AS ACCTCUST_BRANCH_CN_NAME,CASE
  149. WHEN 1 = 0 THEN C.ACCTCUST_BRANCH_EN_NAME
  150. ELSE NULL
  151. END AS ACCTCUST_BRANCH_EN_NAME,CASE
  152. WHEN 1 = 0 THEN C.ACCTCUST_SUBSIDIARY_CODE
  153. ELSE NULL
  154. END AS ACCTCUST_SUBSIDIARY_CODE,CASE
  155. WHEN 1 = 0 THEN C.ACCTCUST_SUBSIDIARY_CN_NAM
  156. ELSE NULL
  157. END AS ACCTCUST_SUBSIDIARY_CN_NAM,CASE
  158. WHEN 1 = 0 THEN C.ACCTCUST_SUBSIDIARY_EN_NAM
  159. ELSE NULL
  160. END AS ACCTCUST_SUBSIDIARY_EN_NAM,CASE
  161. WHEN 1 = 0 THEN C.COUNTRY_CODE
  162. ELSE NULL
  163. END AS COUNTRY_CODE --新增加入参
  164. ,CASE
  165. WHEN 1 = 0 THEN C.COUNTRY_CN_NAME
  166. ELSE NULL
  167. END AS COUNTRY_CN_NAME --新增加入参
  168. ,CASE
  169. WHEN 1 = 0 THEN C.COUNTRY_EN_NAME
  170. ELSE NULL
  171. END AS COUNTRY_EN_NAME --新增加入参
  172. ,
  173. SUM(C.AGREE_AMOUNT) AS AGREE_AMOUNT --协议金额
  174. ,
  175. SUM(C.AGREE_REMAIN_AMOUNT) AS AGREE_REMAIN_AMOUNT --协议剩余金额
  176. ,
  177. SUM(C.SIGN_AMOUNT) AS SIGN_AMOUNT --可用金额
  178. ,
  179. SUM(C.USE_AMOUNT) AS USE_AMOUNT --已使用金额
  180. ,
  181. SUM(
  182. CASE
  183. WHEN C.DSCT_TYPE = 'VOUCHER'
  184. AND NVL(
  185. C.EXPIRED_DATE,
  186. add_months(C.EFFECTIVE_DATE, C.VALID_MONTH)
  187. ) >= to_date(T.V_DATE, 'yyyymmdd') THEN C.AGREE_REMAIN_AMOUNT
  188. WHEN C.DSCT_TYPE in (
  189. 'FOC',
  190. 'Volume Based List Price Adjustment',
  191. 'One-Time Discount'
  192. )
  193. AND C.DSCT_END_DATE >= to_date(T.V_DATE, 'yyyymmdd') THEN C.EFFECTIVE_TOTAL_AMOUNT
  194. ELSE NULL
  195. END
  196. ) AS NOT_USED_VALID_AMOUNT --未使用金额(有效期外)
  197. ,
  198. SUM(
  199. CASE
  200. WHEN C.DSCT_TYPE = 'VOUCHER' THEN C.SIGN_AMOUNT
  201. ELSE C.EFFECTIVE_TOTAL_AMOUNT
  202. END - CASE
  203. WHEN C.DSCT_TYPE = 'VOUCHER' THEN C.USE_AMOUNT
  204. ELSE C.USED_TOTAL_AMOUNT
  205. END - CASE
  206. WHEN C.DSCT_TYPE = 'VOUCHER'
  207. AND NVL(
  208. C.EXPIRED_DATE,
  209. add_months(C.EFFECTIVE_DATE, C.VALID_MONTH)
  210. ) >= to_date(T.V_DATE, 'yyyymmdd') THEN C.AGREE_REMAIN_AMOUNT
  211. WHEN C.DSCT_TYPE in (
  212. 'FOC',
  213. 'Volume Based List Price Adjustment',
  214. 'One-Time Discount'
  215. )
  216. AND C.DSCT_END_DATE >= to_date(T.V_DATE, 'yyyymmdd') THEN C.EFFECTIVE_TOTAL_AMOUNT
  217. ELSE NULL
  218. END
  219. ) AS NOT_USED_INVALID_AMOUNT --未使用金额(有效期内)
  220. ,
  221. SUM(
  222. CASE
  223. WHEN C.DSCT_TYPE = 'VOUCHER'
  224. AND C.EXPIRED_DATE >= to_date(substr(T.V_DATE, 1, 6), 'yyyymm')
  225. and C.EXPIRED_DATE <= LAST_DAY(to_date(T.V_DATE, 'yyyymmdd')) THEN C.SIGN_AMOUNT
  226. WHEN C.DSCT_TYPE in (
  227. 'FOC',
  228. 'Volume Based List Price Adjustment',
  229. 'One-Time Discount'
  230. )
  231. AND C.DSCT_START_DATE >= to_date(substr(T.V_DATE, 1, 6), 'yyyymm')
  232. and C.DSCT_START_DATE <= LAST_DAY(to_date(T.V_DATE, 'yyyymmdd')) THEN C.EFFECTIVE_TOTAL_AMOUNT
  233. ELSE NULL
  234. END
  235. ) AS NEW_SIGN_AMOUNT --本月新增可用金额
  236. ,
  237. SUM(
  238. CASE
  239. WHEN C.DSCT_TYPE = 'VOUCHER'
  240. AND C.EFFECTIVE_DATE >= to_date(substr(T.V_DATE, 1, 6), 'yyyymm')
  241. and C.EFFECTIVE_DATE <= LAST_DAY(to_date(T.V_DATE, 'yyyymmdd')) THEN C.USE_AMOUNT
  242. WHEN C.DSCT_TYPE in (
  243. 'FOC',
  244. 'Volume Based List Price Adjustment',
  245. 'One-Time Discount'
  246. )
  247. AND C.DSCT_START_DATE >= to_date(substr(T.V_DATE, 1, 6), 'yyyymm')
  248. and C.DSCT_START_DATE <= LAST_DAY(to_date(T.V_DATE, 'yyyymmdd')) THEN C.USED_TOTAL_AMOUNT
  249. ELSE NULL
  250. END
  251. ) AS NEW_USE_AMOUNT --本月新使用金额
  252. ,
  253. SUM(
  254. CASE
  255. WHEN C.DSCT_TYPE = 'VOUCHER'
  256. AND C.EXPIRED_DATE < to_date(T.V_DATE, 'yyyymmdd') THEN C.AGREE_REMAIN_AMOUNT
  257. WHEN C.DSCT_TYPE in (
  258. 'FOC',
  259. 'Volume Based List Price Adjustment',
  260. 'One-Time Discount'
  261. )
  262. AND C.DSCT_END_DATE < to_date(T.V_DATE, 'yyyymmdd') THEN C.EFFECTIVE_TOTAL_AMOUNT
  263. ELSE NULL
  264. END
  265. ) AS EXPIRED_AMOUNT --本月已过期金额
  266. ,
  267. SUM(
  268. CASE
  269. WHEN C.DSCT_TYPE = 'VOUCHER'
  270. AND C.EXPIRED_DATE BETWEEN to_date(T.V_DATE, 'yyyymmdd')
  271. AND add_months(to_date(T.V_DATE, 'yyyymmdd'), 6) THEN C.AGREE_REMAIN_AMOUNT
  272. WHEN C.DSCT_TYPE in (
  273. 'FOC',
  274. 'Volume Based List Price Adjustment',
  275. 'One-Time Discount'
  276. )
  277. AND C.DSCT_END_DATE BETWEEN to_date(T.V_DATE, 'yyyymmdd')
  278. AND add_months(to_date(T.V_DATE, 'yyyymmdd'), 6) THEN C.EFFECTIVE_TOTAL_AMOUNT
  279. ELSE NULL
  280. END
  281. ) AS IMMED_EXPIRED_AMOUNT --半年内即将过期金额
  282. FROM
  283. DMSALESW.DM_SALE_BUSI_DSCT_SUM_F C
  284. LEFT JOIN TMP T ON 1 = 1
  285. WHERE
  286. C.CURRENCY_CODE IN ('USD') --改为多值
  287. AND C.BG_CODE IN ('PDCG901159')
  288. AND C.M_ID IN (
  289. 'BUSI_DSCT_00001',
  290. 'BUSI_DSCT_00002',
  291. 'BUSI_DSCT_00003',
  292. 'BUSI_DSCT_00004',
  293. 'BUSI_DSCT_00005',
  294. 'BUSI_DSCT_00006',
  295. 'BUSI_DSCT_00007'
  296. ) --新增加字段
  297. --AND C.M_CN IN ('#[#P_REPORT_ITEM_NAME#]#') --新增加字段
  298. --新增加字段
  299. GROUP BY
  300. C.BG_CODE,
  301. C.BG_CN_NAME,
  302. C.BG_EN_NAME,
  303. C.M_ID --指标ID
  304. ,
  305. C.M_CN --指标中文名称
  306. ,
  307. C.M_EN --指标英文名称
  308. ,
  309. C.CURRENCY_CODE --币种
  310. ,CASE
  311. WHEN 1 = 0 THEN C.OVERSEA_FLAG
  312. ELSE NULL
  313. END,CASE
  314. WHEN 1 = 0 THEN C.REGION_CODE
  315. ELSE NULL
  316. END,CASE
  317. WHEN 1 = 0 THEN C.REGION_CN_NAME
  318. ELSE NULL
  319. END,CASE
  320. WHEN 1 = 0 THEN C.REGION_EN_NAME
  321. ELSE NULL
  322. END,CASE
  323. WHEN 1 = 0 THEN C.REPOFFICE_CODE
  324. ELSE NULL
  325. END,CASE
  326. WHEN 1 = 0 THEN C.REPOFFICE_CN_NAME
  327. ELSE NULL
  328. END,CASE
  329. WHEN 1 = 0 THEN C.REPOFFICE_EN_NAME
  330. ELSE NULL
  331. END,CASE
  332. WHEN 1 = 0 THEN C.OFFICE_CODE
  333. ELSE NULL
  334. END,CASE
  335. WHEN 1 = 0 THEN C.OFFICE_CN_NAME
  336. ELSE NULL
  337. END,CASE
  338. WHEN 1 = 0 THEN C.OFFICE_EN_NAME
  339. ELSE NULL
  340. END,CASE
  341. WHEN 1 = 0 THEN C.REGION_CUSTCATG_CODE
  342. ELSE NULL
  343. END,CASE
  344. WHEN 1 = 0 THEN C.REGION_CUSTCATG_CN_NAME
  345. ELSE NULL
  346. END,CASE
  347. WHEN 1 = 0 THEN C.REGION_CUSTCATG_EN_NAME
  348. ELSE NULL
  349. END,CASE
  350. WHEN 1 = 0 THEN C.TOP_CUST_CATEGORY_CODE
  351. ELSE NULL
  352. END,CASE
  353. WHEN 1 = 0 THEN C.TOP_CUST_CATEGORY_EN_NAME
  354. ELSE NULL
  355. END,CASE
  356. WHEN 1 = 0 THEN C.TOP_CUST_CATEGORY_CN_NAME
  357. ELSE NULL
  358. END,CASE
  359. WHEN 1 = 0 THEN C.ACCTCUST_HQ_CODE
  360. ELSE NULL
  361. END,CASE
  362. WHEN 1 = 0 THEN C.ACCTCUST_HQ_CN_NAME
  363. ELSE NULL
  364. END,CASE
  365. WHEN 1 = 0 THEN C.ACCTCUST_HQ_EN_NAME
  366. ELSE NULL
  367. END,CASE
  368. WHEN 1 = 0 THEN C.ACCTCUST_BRANCH_CODE
  369. ELSE NULL
  370. END,CASE
  371. WHEN 1 = 0 THEN C.ACCTCUST_BRANCH_CN_NAME
  372. ELSE NULL
  373. END,CASE
  374. WHEN 1 = 0 THEN C.ACCTCUST_BRANCH_EN_NAME
  375. ELSE NULL
  376. END,CASE
  377. WHEN 1 = 0 THEN C.ACCTCUST_SUBSIDIARY_CODE
  378. ELSE NULL
  379. END,CASE
  380. WHEN 1 = 0 THEN C.ACCTCUST_SUBSIDIARY_CN_NAM
  381. ELSE NULL
  382. END,CASE
  383. WHEN 1 = 0 THEN C.ACCTCUST_SUBSIDIARY_EN_NAM
  384. ELSE NULL
  385. END,CASE
  386. WHEN 1 = 0 THEN C.COUNTRY_CODE
  387. ELSE NULL
  388. END --新增加入参
  389. ,CASE
  390. WHEN 1 = 0 THEN C.COUNTRY_CN_NAME
  391. ELSE NULL
  392. END --新增加入参
  393. ,CASE
  394. WHEN 1 = 0 THEN C.COUNTRY_EN_NAME
  395. ELSE NULL
  396. END
  397. ) T --新增加入参
复制代码
把TMP作为一列放到T中后,性能有明显提升。
  1. id | operation | A-time | A-rows | E-rows | E-distinct | Peak Memory | E-memory | A-width | E-width | E-costs
  2. ----+-------------------------------------------------------------------------+----------------------+---------+---------+------------+----------------+----------+-----------+---------+-----------
  3. 1 | -> Row Adapter | 3037.648 | 7 | 245 | | 419KB | | | 1318 | 117210.62
  4. 2 | -> Vector Streaming (type: GATHER) | 3037.633 | 7 | 245 | | 777KB | | | 1318 | 117210.62
  5. 3 | -> Vector Hash Aggregate | [3031.872, 3032.516] | 7 | 245 | | [4MB, 4MB] | 16MB | [0,870] | 557 | 117128.41
  6. 4 | -> Vector Streaming(type: REDISTRIBUTE) | [3031.560, 3032.232] | 112 | 3920 | | [1MB, 1MB] | 2MB | | 557 | 116852.33
  7. 5 | -> Vector Hash Aggregate | [2728.059, 2909.255] | 112 | 3920 | | [8MB, 8MB] | 16MB | [833,833] | 557 | 116699.48
  8. 6 | -> Vector Nest Loop Left Join (7, 8) | [441.050, 471.725] | 3007901 | 2106919 | | [1MB, 1MB] | 1MB | | 237 | 67316.28
  9. 7 | -> CStore Scan on dmsalesw.dm_sale_busi_dsct_sum_f c | [145.354, 158.560] | 3007901 | 2106919 | | [5MB, 5MB] | 1MB | | 205 | 65011.82
  10. 8 | -> Vector Materialize | [32.034, 38.902] | 3007901 | 1 | | [288KB, 288KB] | 16MB | [21,21] | 32 | 0.03
  11. 9 | -> Vector Subquery Scan on dual | [0.067, 0.093] | 16 | 1 | | [128KB, 128KB] | 1MB | | 32 | 0.02
  12. 10 | -> Vector Adapter | [0.005, 0.006] | 16 | 1 | | [40KB, 40KB] | 1MB | | 0 | 0.01
  13. 11 | -> Result | [0.001, 0.002] | 16 | 1 | | [8KB, 8KB] | 1MB | | 0 | 0.01
复制代码
可以看到,不但省去了Nest Loop的耗时,而且后面Aggregate的耗时也减少了不少。整体从3s+优化到1.2s。
 
点击关注,第一时间了解华为云新鲜技术~
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

魏晓东

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表