一次成功的sql優化,2個表joinI/O 極大,大約9million
阿新 • • 發佈:2019-01-06
原始sql:
更新#result表,更新warr_bal.I/O大的原因是CIS..trans_acd_bal資料量太大,
並且#result表的資料量並不大,且如果有重複的資料,sum出來的結果呈倍數增長。
CREATE TABLE #scm(
scm_no int NULL
,amt money NULL
)
INSERT INTO #scm
SELECT scm_no
,sum(isnull(gl_amt, 0))
FROM #result t
INNER JOIN CIS..trans_acd_bal ta
ON ta.gl_project = t.scm_no
WHERE ta.gl_year = @pre_year
AND ta.gl_month = @pre_month
GROUP BY scm_no
UPDATE #result
SET warr_bal = scm.amt
FROM #result t
INNER JOIN #scm scm
ON t.scm_no = scm.scm_no
修改後的sql如下:I/O小了,並且時間也減少。
迴圈的時候最重要的是紅色的sql語句
-----------update trans_bal from CIS..trans_acd_bal begin DECLARE @max_idn int ,@min_idn int ,@bal_amt money ,@scm_no int SELECT @min_idn = isnull(min(idn), 0) FROM #result SELECT @max_idn = isnull(max(idn), 0) + 1 FROM #result WHILE (@min_idn < @max_idn) BEGIN SELECT @scm_no = isnull(scm_no, 0) ,@bal_amt = warr_bal FROM #result t WHERE t.idn = @min_idn IF (@bal_amt IS NULL)
BEGIN SELECT @bal_amt = sum(gl_amt) FROM CIS..trans_acd_bal ta WHERE ta.gl_year = @pre_year AND ta.gl_month = @pre_month AND ta.gl_project = @scm_no UPDATE #result SET warr_bal = @bal_amt FROM #result t WHERE t.idn = @min_idn OR t.scm_no = @scm_no END SELECT @min_idn = min(idn) FROM #result WHERE idn > @min_idn END -----------update trans_bal from CIS..trans_acd_bal end
第二個例子:
優化前sql,2個表直接inner join I/O 異常大。
journal_entry是個大表,且有索引。
SELECT b.dept_no
,max(b.dept_name) AS dept_name
FROM journal_entry a
INNER JOIN department_info b
ON a.gl_department = b.dept_no
WHERE a.gl_acct_no > 700000
GROUP BY b.dept_no
優化後i/O降低了大概只有原來1/10的I/O,
SELECT a.gl_department as dept_no
,(select max(b.dept_name) from department_info b where a.gl_department = b.dept_no) AS dept_name
FROM journal_entry a
WHERE a.gl_acct_no > 700000
GROUP BY a.gl_department
第三個例子,普通取模迴圈
declare @iloop int,@ibatch int
SET @iloop = 0
SELECT @ibatch = (count(*) / 200000) + 1
FROM #pay_tmp
WHILE @iloop < @ibatch
BEGIN
EXEC (
"
UPDATE #pay_tmp
SET payment = payment + pay_amt
FROM #pay_tmp a1701250030(index id_1)
INNER JOIN #temp_pay b(index id_1)
ON a1701250030.order_no = b.order_no
AND a1701250030.order_type = b.order_type
WHERE abs(isnull(a1701250030.order_no, 0)) % @ibatch = @iloop
"
)
EXEC (
"
DELETE #temp_pay
FROM #pay_tmp a1701250031(index id_1)
INNER JOIN #temp_pay b(index id_1)
ON a1701250031.order_no = b.order_no
AND a1701250031.order_type = b.order_type
WHERE abs(isnull(a1701250031.order_no, 0)) % @ibatch = @iloop
"
)
INSERT #pay_tmp(
order_type
,order_no
,payment
)
SELECT order_type
,order_no
,pay_amt
FROM #temp_pay a
WHERE abs(isnull(a.order_no, 0)) % @ibatch = @iloop
SET @iloop = @iloop + 1
END
第四個例子:old sql update 太大,為降低I/O,增加臨時表。
old sql 每個都join 去sum,所以I/O 太大
UPDATE #result
SET w0 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 0
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w1 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 1
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w2 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 2
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w3 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 3
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w4 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 4
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w5 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 5
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w6 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 6
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w7 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 7
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w8 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 8
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w9 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 9
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w10 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 10
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w11 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 11
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w12 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 12
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w13 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 13
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w14 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 14
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w15 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 15
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w16 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 16
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w17 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 17
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w18 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 18
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w19 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 19
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w20 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 20
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w21 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 21
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w22 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 22
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w23 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 23
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w24 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 24
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w25 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 25
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
,w26 = (
SELECT s.reqQty
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND s.idx = 26
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
)
FROM #result r
UPDATE #result
SET forecast_total = (
SELECT sum(isnull(s.reqQty, 0))
FROM #res s
WHERE r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')
GROUP BY s.custNo
,s.group_id
,s.loc_no
,s.skuNo
,isnull(ltrim(rtrim(s.refNo)), '')
)
FROM #result r
新的sql,放入臨時表,把結果計算出來後,再去update
insert into #temptable
SELECT s.custNo
,s.group_id
,s.loc_no
,s.skuNo
,isnull(ltrim(rtrim(s.refNo)), '') AS refNo
,sum(CASE
WHEN s.idx = 0
THEN s.reqQty
END) AS w0
,sum(CASE
WHEN s.idx = 1
THEN s.reqQty
END) AS w1
,sum(CASE
WHEN s.idx = 2
THEN s.reqQty
END) AS w2
,sum(CASE
WHEN s.idx = 3
THEN s.reqQty
END) AS w3
,sum(CASE
WHEN s.idx = 4
THEN s.reqQty
END) AS w4
,sum(CASE
WHEN s.idx = 5
THEN s.reqQty
END) AS w5
,sum(CASE
WHEN s.idx = 6
THEN s.reqQty
END) AS w6
,sum(CASE
WHEN s.idx = 7
THEN s.reqQty
END) AS w7
,sum(CASE
WHEN s.idx = 8
THEN s.reqQty
END) AS w8
,sum(CASE
WHEN s.idx = 9
THEN s.reqQty
END) AS w9
,sum(CASE
WHEN s.idx = 10
THEN s.reqQty
END) AS w10
,sum(CASE
WHEN s.idx = 11
THEN s.reqQty
END) AS w11
,sum(CASE
WHEN s.idx = 12
THEN s.reqQty
END) AS w12
,sum(CASE
WHEN s.idx = 13
THEN s.reqQty
END) AS w13
,sum(CASE
WHEN s.idx = 14
THEN s.reqQty
END) AS w14
,sum(CASE
WHEN s.idx = 15
THEN s.reqQty
END) AS w15
,sum(CASE
WHEN s.idx = 16
THEN s.reqQty
END) AS w16
,sum(CASE
WHEN s.idx = 17
THEN s.reqQty
END) AS w17
,sum(CASE
WHEN s.idx = 18
THEN s.reqQty
END) AS w18
,sum(CASE
WHEN s.idx = 19
THEN s.reqQty
END) AS w19
,sum(CASE
WHEN s.idx = 20
THEN s.reqQty
END) AS w20
,sum(CASE
WHEN s.idx = 21
THEN s.reqQty
END) AS w21
,sum(CASE
WHEN s.idx = 22
THEN s.reqQty
END) AS w22
,sum(CASE
WHEN s.idx = 23
THEN s.reqQty
END) AS w23
,sum(CASE
WHEN s.idx = 24
THEN s.reqQty
END) AS w24
,sum(CASE
WHEN s.idx = 25
THEN s.reqQty
END) AS w25
,sum(CASE
WHEN s.idx = 26
THEN s.reqQty
END) AS w26
,sum(s.reqQty) as wall
FROM #res s
GROUP BY s.custNo
,s.group_id
,s.loc_no
,s.skuNo
,isnull(ltrim(rtrim(s.refNo)), '')
UPDATE #result
SET w0 = s.w0
,w1 = s.w1
,w2 = s.w2
,w3 = s.w3
,w4 = s.w4
,w5 = s.w5
,w6 = s.w6
,w7 = s.w7
,w8 = s.w8
,w9 = s.w9
,w10 = s.w10
,w11 = s.w11
,w12 = s.w12
,w13 = s.w13
,w14 = s.w14
,w15 = s.w15
,w16 = s.w16
,w17 = s.w17
,w18 = s.w18
,w19 = s.w19
,w20 = s.w20
,w21 = s.w21
,w22 = s.w22
,w23 = s.w23
,w24 = s.w24
,w25 = s.w25
,w26 = s.w26
,forecast_total = s.wall
FROM #result r
INNER JOIN #temptable s
ON r.cust_no = s.custNo
AND r.group_id = s.group_id
AND r.loc_no = s.loc_no
AND r.sku_no = s.skuNo
AND isnull(ltrim(rtrim(r.ref_no)), '') = isnull(ltrim(rtrim(s.refNo)), '')