2016-12-30 84 views
1

我寫了一個與我的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

存儲過程*不*提高錯誤查詢的性能。而不是像這樣使用遊標或循環(實際上是一種更慢的遊標形式),您應該編寫適當的查詢 –

+0

請發佈您的表模式和數據示例。 –

+0

使用正確的工具進行工作。 Sql服務器就是爲保存和讀取數據而設計的IO設備。計算和其他「業務」邏輯可以在你的應用程序('vb.net')中完成 - 很容易,可以更快地完成(用於加載來自不同表格的數據的'async-await'方法),可讀(非常重要)和簡單保持。 – Fabio

回答

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語句按關係代碼和公司名稱對結果進行分組。

+0

這個工作起來很快,但是當它除以零時會自行消滅,如何消除它?我得到這個: https://gyazo.com/3d31bacdb4f26a67e61fe027bacf8c6a –

+1

我已經在'SELECT'中添加了一個'CASE'語句來檢查分母中的0值,這將避免除0除外。 – strickt01

+0

好吧,但我有很多行缺失,我有4474關係,它給了我1707行,很多關係沒有傳入或外出發票,如何仍然得到它們?即使它們是NULL –