存储过程提高了性能

时间:2016-12-30 13:10:13

标签: sql-server vb.net tsql stored-procedures

我编写了一个与我的Visual Basic .NET代码完全相同的存储过程。现在我已经对它们进行了基准测试。使用while循环和for循环。但是两者都使用我的Visual Basic .NET代码给了我更糟糕的结果。有没有办法改善此代码的性能:

DECLARE @RelationCode nvarchar(50)
DECLARE @CompanyName nvarchar(256)
DECLARE @IncomingInvoice decimal(18, 2)
DECLARE @OutgoingInvoice decimal(18, 2)
DECLARE @Profit decimal(18, 2)
DECLARE @RelationTable as TABLE (RELATIONCODE nvarchar(10), COMPANY nvarhar(120))

INSERT INTO @RelationTable (RELATIONCODE, COMPANY) SELECT [fms].[dbo].[Relation].[RELATIONCODE], [fms].[dbo].[Relation].[COMPANYNAME] FROM [fms].[dbo].[Relation]

/* Result table */
DECLARE @RESULTTABLE TABLE (RelationCode nvarchar(50), Companyname nvarchar(256), IncomingInvoice nvarchar(50), OutgoingInvoice nvarchar(50), profit nvarchar(50))

WHILE EXISTS(SELECT * FROM @RelationTable)
BEGIN
SELECT TOP 1 @RelationCode = RELATIONCODE, @CompanyName = COMPANY FROM @RelationTable

    SELECT fmsTotalAmountIncoming INTO TempIncomingAmounts FROM (
            SELECT SUM(CASE WHEN fms1.currency != 'EUR'
                THEN fms1.amount * fms1.rate
            ELSE ISNULL(fms1.amount, 0) END) fmsTotalAmountIncoming
    FROM [fms].[dbo].[file] f
        INNER JOIN [fms].[dbo].[incominginvoiceline] fms1 ON 
       fms1.filenumber = CONVERT(NVARCHAR, f.filenumber)
    WHERE f.RELATIONCODE = @RelationCode
    ) a 

    SELECT fmsTotalAmountOutgoing INTO TempOutgoingAmounts FROM (
            SELECT SUM(CASE WHEN fms1.currency != 'EUR'
                THEN fms1.amount * fms1.rate
            ELSE ISNULL(fms1.amount, 0) END) fmsTotalAmountOutgoing
    FROM [fms].[dbo].[file] f
        INNER JOIN [fms].[dbo].[outgoinginvoiceline] fms1 ON 
       fms1.filenumber = CONVERT(NVARCHAR, f.filenumber)
    WHERE f.RELATIONCODE = @RelationCode
    ) a 
    SET @IncomingInvoice = (SELECT fmsTotalAmountIncoming FROM [fms].[dbo].[TempIncomingAmounts])
        SET @OutgoingInvoice = (SELECT fmsTotalAmountOutgoing FROM [fms].[dbo].[TempOutgoingAmounts])
        SET @Profit = ((@OutgoingInvoice - @IncomingInvoice) / @OutgoingInvoice)

        INSERT INTO @RESULTTABLE ([RELATIONCODE], [CompanyName], [IncomingInvoice], [OutgoingInvoice], [Profit])
                VALUES (@RelationCode, @CompanyName, @IncomingInvoice, @OutgoingInvoice, @Profit)

        DROP TABLE [fms].[dbo].[TempIncomingAmounts]
        DROP TABLE [fms].[dbo].[TempOutgoingAmounts]

        DELETE FROM @RelationTable WHERE RelationCode = @RelationCode
    END

    SELECT * FROM @RESULTTABLE

我对此进行了基准测试,结果如下:

STORED PROCEDURE        VB.NET
6:54                    5:11
6:20                    5:11
6:19                    3:55
6:43                    4:01

有没有人知道如何提高VB.net性能以上的性能,因为这样存储过程就没用了。

1 个答案:

答案 0 :(得分:6)

您正在尝试在SQL中复制过程VB代码。 SQL是基于集合的,只在此基础上运行良好。在不确切了解您的架构的情况下,这大致是您的SQL应该是什么样子,以便更快地获得所需的结果:

;
WITH invoice (RELATIONCODE, COMPANYNAME, IncomingInvoice, OutgoingInvoice)
AS (
    SELECT r.[RELATIONCODE], r.[COMPANYNAME], 
    SUM(CASE WHEN fms1.currency != 'EUR'
            THEN fms1.amount * fms1.rate
        ELSE ISNULL(fms1.amount, 0) END) AS IncomingInvoice, 
    SUM(CASE WHEN fmso.currency != 'EUR'
            THEN fmso.amount * fmso.rate
        ELSE ISNULL(fmso.amount, 0) END) AS OutgoingInvoice
    FROM [fms].[dbo].[Relation] r
    LEFT OUTER JOIN [fms].[dbo].[file] f
    ON f.RELATIONCODE = r.[RELATIONCODE]
    LEFT OUTER JOIN [fms].[dbo].[incominginvoiceline] fms1
     ON fms1.filenumber = CONVERT(NVARCHAR, f.filenumber)
    LEFT OUTER JOIN [fms].[dbo].[outgoinginvoiceline] fmso
     ON fmso.filenumber = CONVERT(NVARCHAR, f.filenumber)
     GROUP BY r.[RELATIONCODE], r.[COMPANYNAME]
 )
 SELECT RELATIONCODE, 
    COMPANYNAME, 
    IncomingInvoice, 
    OutgoingInvoice,
     CASE WHEN OutgoingInvoice > 0 THEN (OutgoingInvoice - IncomingInvoice) / OutgoingInvoice 
    ELSE 0 END AS Profit
 FROM invoice

即。没有循环,if ... else语句,创建,删除然后重新创建永久表等。只有一个SQL语句按关系代码和公司名对结果进行分组。