MS SQL - 查询运行时间太长

时间:2018-04-10 06:02:55

标签: sql-server

我有一个数据库触发器,而不是运行存储过程。

因此,每次将新数据插入表格时,此触发器都会运行。

这是存储过程查询:

已编辑:新查询



declare @transaction_type int
set @transaction_type = (select  TransTyp from inserted)


declare @transaction_ctr bigint
set @transaction_ctr = (select TransCtr from inserted)

declare @transaction_no nvarchar(15)
set @transaction_no = (select TransNum from inserted)

declare @transaction_date datetime
set @transaction_date = (select TransDt from inserted)

declare @customer_code nvarchar(10)
set @customer_code = (select CustCode from inserted)

declare @contact nvarchar(15)
set @contact = (select CellNum  from inserted)


declare @transaction_info nvarchar(130)
set	@transaction_info = (select TransInfo from inserted)


declare @date_received datetime
set	@date_received = (select DtRcv from inserted)

declare @is_active int
set @is_active= (select	IsActive
				 from	BigESentData.dbo.tbl_sentRegistration
				 where CellNum = @contact)

declare @value nvarchar(130)
declare @pos int
declare @len int

if @is_active= 0 OR @is_active is null
begin
	delete from BigESentData.dbo.tbl_sentTransaction where TransCtr = @transaction_ctr
end

else
begin
	--exec parseSentData @transType

	/** Inventory */
	if @transaction_type = 3
	begin
		if not exists(select TransCtr from BigEMerchandiser.dbo.tbl_Inventory_H where TransCtr = @transaction_ctr)
		begin
			insert into BigEMerchandiser.dbo.tbl_Inventory_H
			Values(@transaction_ctr,@customer_code, @date_received, @contact)

			set @pos = 0
			set @len = 0
				while charindex('-', @transaction_info, @pos + 1) > 0
				begin
					set @len = charindex('|', @transaction_info, @pos + 1) - @pos
					set @value = substring(@transaction_info, @pos, @len)
						insert into BigEMerchandiser.dbo.tbl_Inventory_D(TransCtr, Material, Qty, ExpDt)
						select	@transaction_ctr,
								ltrim(rtrim(left(@value, charindex('-', @value) - 1))) as Material,
								replace(substring(@value,charindex('-',@value),len(@value) - charindex('-', reverse(@value)) - charindex('-', @value) + 1),'-', '') as Qty,
								reverse(left(reverse(@value),charindex('-', reverse(@value)) - 1))as ExpDt
					set @pos = charindex('|', @transaction_info, @pos + @len) + 1
				end
		end		
	end
	
	/** Delivery */
	if @transaction_type = 2
	begin
		if not exists(select TransCtr from BigEMerchandiser.dbo.tbl_Delivery_H where TransCtr = @transaction_ctr)
		begin
			insert into BigEMerchandiser.dbo.tbl_Delivery_H
			Values(@transaction_ctr, @transaction_no, @transaction_date, @customer_code, @date_received, @contact)

			set @pos = 0
			set @len = 0
				while charindex('-', @transaction_info, @pos + 1) > 0
				begin
					set @len = charindex('|', @transaction_info, @pos + 1) - @pos
					set @value = substring(@transaction_info, @pos, @len)
						insert into BigEMerchandiser.dbo.tbl_Delivery_D(TransCtr, Material, Qty, ExpDt)
						select	@transaction_ctr,
								ltrim(rtrim(left(@value, charindex('-', @value) - 1))) as Material,
								replace(substring(@value,charindex('-',@value),len(@value) - charindex('-', reverse(@value)) - charindex('-', @value) + 1),'-', '') as Qty,
								reverse(left(reverse(@value),charindex('-', reverse(@value)) - 1))as ExpDt
					set @pos = charindex('|', @transaction_info, @pos + @len) + 1
				end
		end		
	end

	/** ABIS */
	if @transaction_type = 1
	begin
		if not exists(select TransCtr from BigEMerchandiser.dbo.tbl_Abis_H where TransCtr = @transaction_ctr)
		begin
			insert into BigEMerchandiser.dbo.tbl_Abis_H
			Values(@transaction_ctr, @transaction_no, @customer_code, @date_received, @contact)

			set @pos = 0
			set @len = 0
				while charindex('-', @transaction_info, @pos + 1) > 0
				begin
					set @len = charindex('|', @transaction_info, @pos + 1) - @pos
					set @value = substring(@transaction_info, @pos, @len)
						insert into BigEMerchandiser.dbo.tbl_Abis_D(TransCtr, Material, Qty, ExpDt)
						select	@transaction_ctr,
								ltrim(rtrim(left(@value, charindex('-', @value) - 1))) as Material,
								replace(substring(@value,charindex('-',@value),len(@value) - charindex('-', reverse(@value)) - charindex('-', @value) + 1),'-', '') as Qty,
								reverse(left(reverse(@value),charindex('-', reverse(@value)) - 1))as ExpDt
					set @pos = charindex('|', @transaction_info, @pos + @len) + 1
				end
		end		
	end

	/** end of transaction */
end




让我告诉你一个故事如何运行。数据来自Android应用程序。它是超市中商家的应用程序。该应用程序将数据转换为SMS并将数据发送到SQL数据库。

现在,如果将来自应用程序的已发送数据插入数据库,则会触发触发器,并运行上述存储过程。

存储过程按以下顺序运行:

  1. 检查交易类型(在上面的查询中,它是3,即库存)
  2. 检查 tbl_sentdata 中未加入 tbltransactionheader 的所有记录,如果不是 tbltransactionheader ,请将其插入。

  3. 检查 tblsentdata 中未包含 tbltransactiondetail 的所有记录,解析分隔数据,并将每个记录插入一行。

  4. tblsentdata - 来自应用的数据

    tbltransactionheader - 标题表

    tbltransactiondetail - 详细信息表

    以下是该应用的原始数据:

    Raw Data

    现在,正如您在屏幕截图中看到的那样,应用程序中的数据是分隔的。所以我需要逐个解析它。(在上面的查询中,解析从注释开始" / *循环分隔数据* /")

    现在,如果我手动运行存储过程,对于TransTyp 3(库存),则需要很长时间。

    在我的猜测中,我上面的查询逐个检查来自 tblsentdata 的所有数据。 所以如果我有100,000条记录,它每次都会检查它,即使数据已经在交易表上。

    以下是我的问题:

    1. 我认为这是正确的吗?如果触发器触发,则运行查询。然后发送另一条文本消息,即使第一个查询未完成,触发器也会再次运行。然后发送另一条文本消息,触发器再次运行。

    2. 我的查询是否是最佳方法?有没有办法更快?我负担不起运行这个查询需要花费很多时间。

    3. 希望你能开导我,我是SQL查询的新手。或者至少引导我去哪里看。

      希望我能很好地解释自己。我将不胜感激任何帮助和建议。谢谢。

      更新日期:11/04/2018

      感谢 PSK 。在他的帮助下,我能够解决我的问题并最小化查询中的while循环。我刚刚删除了存储过程。我直接从触发器运行查询,只选择插入的数据。

      请参阅上面编辑的查询。

      谢谢你们。

1 个答案:

答案 0 :(得分:3)

您应避免在查询中使用WHILE,这会严重降低您的查询速度。对于您的情况,您可以轻松避免使用while循环,这将提高查询的性能。

例如

现有代码

WHILE @headerCount > 0
BEGIN
    SET @transCtr = (SELECT TOP 1 TransCtr FROM BigESentData.dbo.tbl_sentTransaction WHERE TransCtr NOT IN (SELECT TransCtr FROM BigEMerchandiser.dbo.tbl_Inventory_H) and TransTyp = 3)

    IF NOT EXISTS(SELECT TransCtr FROM BigEMerchandiser.dbo.tbl_Inventory_H where TransCtr = @transCtr)
    BEGIN
        INSERT INTO BigEMerchandiser.dbo.tbl_Inventory_H
        SELECT TOP 1 TransCtr, CustCode, DtRcv, CellNum
        FROM BigESentData.dbo.tbl_sentTransaction where TransCtr = @transCtr
    END
    SET @headerCount = @headerCount - 1
END

修改(不用时)

 INSERT INTO BigEMerchandiser.dbo.tbl_Inventory_H
    SELECT TOP 1 TransCtr, CustCode, DtRcv, CellNum
    FROM BigESentData.dbo.tbl_sentTransaction A

    WHERE EXISTS
    (
        SELECT 1 FROM 
        BigESentData.dbo.tbl_sentTransaction T WHERE TransCtr NOT IN 
            (SELECT TransCtr FROM BigEMerchandiser.dbo.tbl_Inventory_H) and TransTyp = 3)
        AND T.TransCtr = A.TransCtr
    ) 

使用类似的方法,您可以实现第二个while循环。