在管理 IIS 伺服器時,將海量的存取日誌匯入 SQL Server 進行分析是常見需求。本文詳細記錄從建立資料表、使用 BCP 工具大量匯入,到撰寫 C# 程式預處理日誌檔案的完整流程,助你高效完成資料導入。
首先依據 IIS 日誌預設欄位(W3C 格式)建立資料表。因日誌量大,建議依月份分表儲存(如 web_201007)。所有欄位採用 varchar/nvarchar 並預留足夠長度,避免匯入時發生字串截斷錯誤。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[web_201007](
[date] [varchar](255) NULL,
[time] [varchar](255) NULL,
[s-ip] [varchar](255) NULL,
[cs-method] [varchar](255) NULL,
[cs-uri-stem] [nvarchar](255) NULL,
[cs-uri-query] [nvarchar](1000) NULL,
[s-port] [varchar](255) NULL,
[cs-username] [varchar](255) NULL,
[c-ip] [varchar](255) NULL,
[cs(User-Agent)] [nvarchar](1000) NULL,
[cs(Referer)] [nvarchar](1000) NULL,
[sc-status] [varchar](255) NULL,
[sc-substatus] [varchar](255) NULL,
[sc-win32-status] [varchar](255) NULL,
[time-taken] [varchar](255) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
注意: 實際欄位須依 IIS 設定的「記錄欄位」調整;若啟用完整記錄,欄位數可能超過 15 個。
BCP (Bulk Copy Program) 是 SQL Server 內建的高效大量匯入工具。關鍵參數說明:
-t"*":欄位分隔符(IIS 日誌預設為空白,建議先以程式替換為 * 等特殊字元)-r"\r":列分隔符(IIS 日誌為 CR 換行)-w:使用 Unicode 編碼(含中文時必須;純英文可用 -c 節省空間)-U/-P/-S:登入帳號、密碼、伺服器實例名bcp [database].dbo.[web_201007] in "g:\IISlog\log.txt" -w -t"*" -r"\r" -U"sa" -P"123456" -S"UKEASSERVER\SQLEXPRESS"
避坑指南:
*.log 且每日一檔,BCP 不支援直接讀取多檔,需先合併預處理。編寫專用工具 FormatLog 類別,功能包含:
u_exYYMMDD.log)篩選特定月份檔案# 開頭)*Encoding.Unicode 輸出合併後的 log.txt核心程式碼片段:
public void Execute() {
Regex reg = new Regex(@"u_ex(\d{6})\.log");
string[] files = Directory.GetFiles(inputDirectory);
var targetFiles = files.Where(f => reg.Match(f).Groups[1].Value.StartsWith("1011")).ToArray();
using (FileStream fs = new FileStream(outputFileName, FileMode.Create))
using (StreamWriter sw = new StreamWriter(fs, Encoding.Unicode)) {
foreach (string f in targetFiles) {
foreach (string line in GetRecordLineForFile(f)) {
sw.Write(line);
sw.Write(rowSeparator); // "\r"
}
}
}
}
private List<string> GetRecordLineForFile(string fileName) {
var list = new List<string>();
using (FileStream fs = new FileStream(fileName, FileMode.Open))
using (StreamReader sr = new StreamReader(fs, Encoding.UTF8)) {
string line;
while ((line = sr.ReadLine()) != null) {
if (!line.StartsWith("#")) {
line = line.Replace(" ", fieldSeparator); // " "
if (line.Split(fieldSeparator.ToCharArray()).Length == fieldLength) // 15
list.Add(line);
}
}
}
return list;
}
呼叫範例:
string inputDir = @"g:\IISlog\logs";
string outputFile = @"g:\IISlog\log.txt";
string errorFile = @"g:\IISlog\error.txt";
FormatLog log = new FormatLog(inputDir, outputFile, errorFile);
log.Execute();
// log.WriteInvalidFields(); // 選擇性:輸出欄位長度超標記錄

error.txt 記錄欄位不符行數,定期人工複核。掌握此流程,即可將 IIS 原始日誌轉化為結構化資料,支援後續的流量分析、異常偵測、報表產出等高價值應用。