雙設備每秒寫入 4000 筆,單純 INSERT 僅能寫入 2800 筆,**遺失 1200 筆/秒**。經測試,以下兩種方案顯著改善。
'111|222|333|456,7894,7458|0|1|2014-01-01 12:15:16;1111|2222|3333|456,7894,7458|0|1|2014-01-01 12:15:16'INSERT ... SELECT * FROM TVF(...)CREATE FUNCTION [dbo].[fun_BatchInsert]
(
@str VARCHAR(MAX),
@rowSplit CHAR(1), -- ';'
@colSplit CHAR(1) -- '|'
)
RETURNS @t TABLE
(
MaxValue FLOAT,
Phase INT,
SlopeValue FLOAT,
Data VARCHAR(600),
Alarm INT,
AlmLev INT,
GpsTime DATETIME,
UpdateTime DATETIME
)
AS
BEGIN
-- 雙層 WHILE 迴圈解析行與欄位,INSERT INTO @t
-- 完整程式碼見原文
RETURN
END
-- 呼叫範例
INSERT INTO [MyTable]
SELECT * FROM [dbo].[fun_BatchInsert](
'111|222|333|456,7894,7458|0|1|2014-01-01 12:15:16;...',
';', '|'
)
優點:單次往返、減少網路往返與編譯開銷;缺點:函數邏輯複雜、維護成本高。
EXEC master..xp_cmdshell 'BCP db_mgr.dbo.T_Student format nul -f C:/student_fmt.xml -x -c -T'EXEC master..xp_cmdshell 'BCP db_mgr.dbo.T_Student out C:/student.data -f C:/student_fmt.xml -T'TRUNCATE TABLE db_mgr.dbo.T_StudentBULK INSERT db_mgr.dbo.T_Student FROM 'C:/student.data' WITH (FORMATFILE = 'C:/student_fmt.xml')-- 目標表需存在
INSERT INTO db_mgr.dbo.T_Student(F_Code, F_Name)
SELECT F_Code, F_Name
FROM OPENROWSET(BULK N'C:/student.data', FORMATFILE=N'C:/student_fmt.xml') AS t
-- 目標表可不存在(自動建表)
SELECT F_Code, F_Name INTO db_mgr.dbo.tt
FROM OPENROWSET(BULK N'C:/student.data', FORMATFILE=N'C:/student_fmt.xml') AS t
| 方案 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| TVF 字串解析 | 應用端無法寫檔、需即時寫入、資料量中等(萬~百萬) | 純 T-SQL、無外部依賴 | 解析邏輯複雜、CPU 佔用高 |
| BULK INSERT / bcp | 極大資料量(百萬~億)、ETL、離線匯入、可寫檔案 | 效能最強、支援平行、記錄最少 | 需檔案系統權限、啟用 xp_cmdshell 有風險 |
xp_cmdshell 預設關閉,啟用有安全風險,生產環境嚴格控管TABLOCK、DROP INDEX 再重建、簡易復原模式