一次成功的sql优化,2个表joinI/O 极大,大约9million

本文通过实例分享了一次SQL优化经验,针对2个表JOIN导致的I/O过高问题进行了解决。优化策略包括更新策略调整、避免大表直接JOIN、使用临时表等,有效减少了数据库操作的资源消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


原始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)), '')



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值