簡體   English   中英

MS SQL Server,多次插入

[英]MS SQL Server, multiple insert

假設我寫了查詢:

INSERT INTO DestinationTable
(ColumnA, ColumnB, ColumnC, etc.)
SELECT FROM SourceTable
(ColumnA, ColumnB, ColumnC, etc.)

我的源表有2200萬行。

SQL服務器填滿我的硬盤驅動器,並出錯。

為什么SQL服務器無法處理我的查詢?

我應該使用游標並一次插入一行嗎?

PS - 它是SQL Express 2005,但我可以嘗試完整版。

更新:我還想提一下,當我在管理工作室查看時,我的源表只占用大約1GB的存儲空間。 然而,我的25GB可用磁盤空間不知何故被填滿了嗎? 我也在使用2個不同的數據庫Source.mdf - > Destination.mdf,我不知道這是否有任何區別。

批量更新......

INSERT INTO DestinationTable
    (ColumnA, ColumnB, ColumnC, etc.)
SELECT TOP 100000 ColumnA, ColumnB, ColumnC, etc.
FROM SourceTable
WHERE NOT EXISTS (SELECT *
    FROM DestinationTable
    WHERE DestinationTable.KeyCols = SourceTable.KeyCols)

WHILE @@ROWCOUNT <> 0
    INSERT INTO DestinationTable
        (ColumnA, ColumnB, ColumnC, etc.)
    SELECT TOP 100000 ColumnA, ColumnB, ColumnC, etc.
    FROM SourceTable
    WHERE NOT EXISTS (SELECT *
        FROM DestinationTable
        WHERE DestinationTable.KeyCols = SourceTable.KeyCols)

如果您需要在一個txn等中處理檢查點,日志文件管理,則有各種變體

您可以將數據批量復制到本機格式的文件(編輯從Csv更改為本機),然后將其重新導入到新表中。

在這里閱讀BCP實用程序。

您可以嘗試將數據庫恢復模型設置為“簡單”而不是“完整”(默認值)。 這是在Management Studio中的數據庫屬性的“選項”頁面上完成的。 這應該會降低您的事務日志大小。 完成插入后,您始終可以將恢復模型設置回“完全”。

此博客文章包含有關將數據導入SQL Server的信息。

至於你的表填滿的原因,我會查看表的模式,並確保列的大小盡可能小。

我真的要分析是否所有數據都是必要的。

我強烈建議您在執行此類繁重的批量數據操作時將數據庫恢復模型設置為BULK_LOGGED。

默認情況下 - 數據庫設置為SIMPLE或FULL恢復模型。

完全記錄所有事務的完整恢復模型旨在用於正常使用。

大容量日志恢復模型旨在臨時在大型批量操作期間使用 - 假設它是受批量日志恢復模型影響的批量操作之一(有關更多信息,請參閱msdn中最小可記錄的操作) .microsoft.com / EN-US /庫/ ms191244.aspx)。

BULK_LOGGED恢復模型最少記錄事務

你可以使用下面的代碼片段來完成它

    --Determine the recovery model currently used for the database

    SELECT name AS [Database Name],
    recovery_model_desc AS [Recovery Model]
    FROM sys.databases 
    WHERE name=<database_name> ;

    --Remember this recovery model so that you can switch back to the same later

    --set the database recovery model to BULK_LOGGED

    ALTER DATABASE <database_name>  SET RECOVERY BULK_LOGGED;

    --Run your heavy data insert tasks
    INSERT INTO DestinationTable
    (ColumnA, ColumnB, ColumnC, etc.)
    SELECT FROM SourceTable
    (ColumnA, ColumnB, ColumnC, etc.)

    /*Again set the database recovery model to FULL or SIMPLE 
    (the result which we had got from first query)*/

    ALTER DATABASE <database_name>  SET RECOVERY FULL;   
    --OR 
    ALTER DATABASE <database_name>  SET RECOVERY SIMPLE;   

*注意 - 請在批量操作過程中保持耐心* [:P]

我以前做了很多次。 請告訴我這是否對您有所幫助。

有關在恢復模型之間切換的詳細信息,請參閱以下MSDN文章 - 在msdn.microsoft.com/en-us/library/ms190203.aspx上從完整或批量記錄恢復模型切換的注意事項

您正在以支持事務的方式插入數據。 無法通過您正在使用的方法禁用此功能,但是您可以通過其他方法在事務范圍之外執行此操作。 參見下文:

http://support.microsoft.com/kb/59462

關鍵的方法是:

DBOPTION'SELECT INTO'為真

http://www.mssqlcity.com/FAQ/Devel/select_into.htm

INSERT INTO ... SELECT(2200萬行)的問題在於它都作為一個事務運行。 因此,即使數據庫處於簡單恢復模式,您也可能會填滿事務日志驅動器。

一次插入一行是一個可怕的想法,它將需要永遠。

使用BCP導出數據,導入是BULK INSERT可能是最快的方法。 但它需要學習如何使用BCP實用程序。

如果您決定在T-SQL中執行此操作,則必須將其分解為批處理。 INSERT ... SELECT TOP(n)...上一個答案中的WHERE NOT EXISTS方法有效,但WHERE子句的執行時間可能會相加。 為了使它更高效,更復雜,我有時使用ROW_NUMBER()OVER(ORDER BY pk)和WHERE rn%(n)= 0來填充每n行的pk值的臨時表。然后你可以使用一個帶INSERT INTO ... SELECT ... WHERE pk> @a和pk <= @b的循環,帶有適當的代碼來更新temp表中每次迭代的變量。 只需確保在第一次或最后一次迭代中不會遺漏任何行。

您可能希望在Integration Services中執行此操作,Integration Services也可以執行批量插入。 有一篇關於在30分鍾左右內加載數TB數據的微軟白皮書。 他們將源數據導出(BCP?)到多個文件中,並創建了多個與目標結構相同的表。 然后將每個文件插入一個單獨的空表中,它們都可以作為最小化日志運行。 所有這些導入都作為單獨的並行進程運行。 最后使用表分區命令將每個導入表合並到目標表中。

在30分鍾內加載1TB: https//technet.microsoft.com/en-us/library/dd537533(v = sql.100).aspx

暫無
暫無

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

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