2010-05-21 58 views
1

我正在尋找將數據插入MS SQL數據庫的性能非常高的可能性。數據是具有關係的對象(相對較大)的構造。出於安全原因,我想使用存儲過程而不是直接表訪問。MS SQL - 使用存儲過程插入高性能數據

可以說我有這樣的結構:

  • 文獻
    • 元數據
      • 用戶
      • 設備
    • 內容
      • ContentItem [0]
        • 子項[0]
        • 子項[1]
        • 子項[2]
      • ContentItem [1]
        • ...
      • ContentItem [2]
        • ...

現在我想建立一個大的查詢,做這樣服用點(只是僞代碼):

EXEC @DeviceID = CreateDevice ...; 
EXEC @UserID = CreateUser ...; 
EXEC @DocID = CreateDocument @DeviceID, @UserID, ...; 

EXEC @ItemID = CreateItem @DocID, ... 
EXEC CreateSubItem @ItemID, ... 
EXEC CreateSubItem @ItemID, ... 
EXEC CreateSubItem @ItemID, ... 
... 

但這是性能的最佳解決方案嗎?如果不是,那會更好嗎? 將它拆分成更多querys?將所有數據提供給一個大的存儲過程以減少查詢的大小?任何其他表現線索?我也想過給一個存儲過程多個項目,但我不認爲它有可能給存儲過程非靜態數量的項目。由於'INSERT INTO A VALUES(B,C),(C,D),(E,F)比3個單個插入物更高效,所以我認爲我可以在這裏獲得一些性能。

感謝您的任何提示, 商標

回答

1

一個存儲過程儘可能:

INSERT INTO MyTable(field1,field2) 
SELECT "firstValue", "secondValue" 
UNION ALL 
SELECT "anotherFirstValue", "anotherSecondValue" 
UNION ALL 

如果你不能確定你能有多少項目,你要插入構造SQL查詢在存儲過程中,然後執行它。這裏有一個程序,我寫取組的CSV列表和添加他們的關係到用戶的實體:

ALTER PROCEDURE [dbo].[UpdateUserADGroups] 
@username varchar(100), 
@groups varchar(5000) 
AS 
BEGIN 
DECLARE @pos int, 
@previous_pos int, 
@value varchar(50), 
@sql varchar(8000) 

SET @pos = 1 
SET @previous_pos = 0 
SET @sql = 'INSERT INTO UserADGroups(UserID, RoleName)' 

DECLARE @userID int 
SET @userID = (SELECT TOP 1 UserID FROM Users WHERE Username = @username) 

WHILE @pos > 0 
BEGIN 
SET @pos = CHARINDEX(',',@groups,@previous_pos+1) 
IF @pos > 0 
BEGIN 
SET @value = SUBSTRING(@groups,@previous_pos+1,@[email protected]_pos-1) 
SET @sql = @sql + 'SELECT ' + cast(@userID as char(5)) + ',''' + @value + ''' UNION ALL ' 
SET @previous_pos = @pos 
END 
END 

IF @previous_pos < LEN(@groups) 
BEGIN 
    SET @value = SUBSTRING(@groups,@previous_pos+1,LEN(@groups)) 
    SET @sql = @sql + 'SELECT ' + cast(@userID as char(5)) + ',''' + @value + '''' 
END 
print @sql 
exec (@sql) 

END 

這遠遠不是單個的INSERT更快。

此外,確保您只是主鍵上的單個聚集索引,更多索引會減慢INSERT,因爲它們需要更新。

但是,您的數據集越複雜,您可以執行上述操作的可能性就越小,因此您只需做出邏輯折衷。實際上我最終調用了大約8000次的上述例程。

+0

你真的確定,構建查詢比單個插入(制定基準)更快嗎?我認爲SQL服務器將無法使用緩存的執行計劃進行即時生成的查詢。但我會試一試。 有關IDS問題的任何想法?我認爲生成所有父元素,然後生成所有子元素會更高效。但是如何在父元素中設置子元素的外鍵呢? – Marks 2010-05-21 09:59:22

+0

唯一可以告訴的方式是配置文件,我發現它使我的整個程序更快(不記得時間)。我不知道它是否會緩存執行計劃,但它並不需要,因爲它會非常基礎。我的例子只能工作一層嵌套(一個記錄與許多基本的孩子),也許看看序列化和解析你的項目從XML - http://weblogs.asp.net/jgalloway/archive/2007/02/ 16/passing-lists-to-sql-server-2005-with-xml-parameters.aspx – 2010-05-21 10:29:11

+0

我用我的一個CreateUser SP做了一些分析。 (...),(...),... * 1000個行(INSERT INTO Users(...))... 1000個行情況1:第一次:220ms,重複:〜220ms 情況2:第一次:2960ms,重複:~20ms 即使不創建INSERT INTO實時,由於提交的用戶數量不同,插入緩存的執行計劃的另一數量的用戶被修復。 我會尋找一個Xml解決方案,並希望得到更好的結果。但是,謝謝。 – Marks 2010-05-21 11:32:25