我编写了一个与我的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性能以上的性能,因为这样存储过程就没用了。
答案 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语句按关系代码和公司名对结果进行分组。