簡體   English   中英

SQL 2005查詢優化

[英]SQL 2005 Query Optimisation

我有一個SQL 2005表,包含大約一千萬條記錄(dbo.Logs)。

我有另一個表dbo.Rollup,該表將不同的dbo.Logs.URL匹配到第三個表dbo.Files中的FileId列。 dbo.Rollup表構成了我們稍后階段運行的各種匯總報告的基礎。

到目前為止,我遇到的問題是有效填充dbo.Rollup。

根據定義,dbo.Logs可能有成千上萬的行,它們共享相同的URL字段值。 在我們的應用程序中,一個URL可以與一個dbo.Files.FileId匹配。 IE dbo.Logs.URL和dbo.Files.FileId之間存在多對一的關系(我們解析dbo.Logs的值來確定給定URL的適當FileId)。

我的目標是顯着減少運行三個存儲過程中的第一個所花費的時間,以便從原始日志數據中創建有意義的統計信息。

我需要的是一個具體示例,說明如何將這個SQL查詢重構為更加有效的方法:

sp-Rollup-Step1:

INSERT INTO dbo.Rollup ([FileURL], [FileId])

SELECT 
 logs.RequestedFile As [URL],
 FileId = dbo.fn_GetFileIdFromURL(l.RequestedFile, l.CleanFileName)

FROM
 dbo.Logs l (readuncommitted) 

WHERE    

NOT EXISTS (
    SELECT
     FileURL
    FROM
     dbo.Rollup
    WHERE
     FileUrl = RequestedFile
)

fn_GetFileIdFromURL()

CREATE FUNCTION [dbo].[fn_GetFileIdFromURL] 
(       
    @URL nvarchar(500),
    @CleanFileName nvarchar(255)
)
RETURNS uniqueidentifier
AS
BEGIN

     DECLARE @id uniqueidentifier

     if (exists(select FileURL from dbo.[Rollup] where [FileUrl] = @URL))
     begin
        -- This URL has been seen before in dbo.Rollup.
            -- Retrieve the FileId from the dbo.Rollup table.
        set @id = (select top 1 FileId from dbo.[Rollup] where [FileUrl] = @URL)        
     end
     else
     begin
        -- This is a new URL. Hunt for a matching URL in our list of files,
            -- and return a FileId if a match is found.
        Set @id = (

            SELECT TOP 1
            f.FileId

            FROM
            dbo.[Files] f

            INNER JOIN
            dbo.[Servers] s on s.[ServerId] = f.[ServerId]

            INNER JOIN
            dbo.[URLs] u on 
                   u.[ServerId] = f.[ServerId]

            WHERE
                Left(u.[PrependURLProtocol],4) = left(@URL, 4)
            AND @CleanFileName = f.FileName  
     )

     end

     return @id

END

關鍵注意事項:

  • 對於dbo.tLogs中找到的每個DISTINCT /唯一URL,dbo.Rollup應該僅包含一個條目。
  • 我想省略將記錄插入dbo。[Rollup]的FileId為NULL的記錄。

根據我自己的觀察,到目前為止,查詢中最慢的部分似乎是存儲過程:“ NOT EXISTS”子句(在這一點上,我不確定這是否會持續刷新表)。

我正在尋找一種特定的解決方案(使用偽代碼或通過修改此處顯示的過程提供示例)-答案將被授予提供該解決方案的人!

在此先感謝您提供的任何幫助。

/理查德。

簡短的答案是您在這里有一個游標。 每行輸出都會運行標量UDF。

udf可以是派生表上的2個LEFT JOIN。 粗略的輪廓:

...
COALESCE (F.xxx, L.xxx) --etc
...
FROM
 dbo.Logs l (readuncommitted)
 LEFT JOIN
 (select DISTINCT --added after comment
FileId, FileUrl from dbo.[Rollup]) R ON L.FileUrl = R.FileUrl
 LEFT JOIN
 (SELECT DISTINCT --added after comment
                f.FileId,
FileName ,
left(@PrependURLProtocol, 4) + '%' AS Left4
                FROM
                dbo.[Files] f

                INNER JOIN
                dbo.[Servers] s on s.[ServerId] = f.[ServerId]

                INNER JOIN
                dbo.[URLs] u on 
                           u.[ServerId] = f.[ServerId]
) F ON L.CleanFileName = R.FileName AND L.FileURL LIKE F.Left4
...

由於udf的工作方式,我也不確定您是否需要NOT EXISTS。 如果這樣做,請確保對列進行索引。

我認為您的熱點位於:

Left(u.[PrependURLProtocol],4) = left(@URL, 4)

這將導致服務器對url表進行掃描。 您不應在join子句中的字段上使用函數。 嘗試將其重寫為類似

... where PrependURLProtocol like left(@URL, 4) +"%"

並確保您在該字段上有一個索引。

INSERT INTO dbo.Rollup ([FileURL], [FileId])
SELECT  
 logs.RequestedFile As [URL], 
 FileId = dbo.fn_GetFileIdFromURL(l.RequestedFile, l.CleanFileName)
FROM dbo.Logs l (readuncommitted) LEFT OUTER JOIN dbo.Rollup
 on FileUrl = RequestedFile
WHERE FileUrl IS NULL

這里的邏輯是,如果給定的FileUrl不存在dbo.Rollup,則左外部聯接將變為null。 現在,NOT EXISTS變為IS NULL,這更快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM