Vì vậy, tôi đang làm việc trên một cơ sở dữ liệu mà tôi sẽ bổ sung cho các dự án tương lai của mình như một db hỗ trợ, nhưng tôi có một chút vấn đề với nó, đặc biệt là các bản ghi.Sql Server 2008 Điều chỉnh với các giao dịch lớn (700k + hàng/giao dịch)
Cơ sở dữ liệu về cơ bản cần được cập nhật mỗi tháng một lần. Bảng chính phải được thanh lọc và sau đó nạp lại một tệp CSV. Vấn đề là Sql Server sẽ tạo ra một bản ghi cho nó là MEGA lớn. Tôi đã thành công trong việc lấp đầy nó một lần, nhưng muốn kiểm tra toàn bộ quá trình bằng cách thanh lọc nó và sau đó bơm lại nó.
Đó là khi tôi gặp lỗi khi tệp nhật ký được lấp đầy. Nó nhảy từ 88MB (sau khi thu nhỏ thông qua kế hoạch bảo trì) đến 248MB và sau đó dừng quá trình hoàn toàn và không bao giờ hoàn thành.
Tôi đã giới hạn tốc độ tăng trưởng là 256MB, tăng 16MB, đó là lý do tại sao nó không thành công, nhưng trên thực tế, tôi không cần nó để ghi lại bất kỳ thứ gì. Có cách nào để hoàn toàn bỏ qua đăng nhập vào bất kỳ truy vấn đang chạy với cơ sở dữ liệu?
Cảm ơn bạn đã trả lời trước!
CHỈNH SỬA: Theo đề xuất của @ mattmc3 Tôi đã triển khai SqlBulkCopy cho toàn bộ quy trình. Nó hoạt động AMAZING, ngoại trừ, vòng lặp của tôi bằng cách nào đó bị rơi vào đoạn cuối cùng còn lại cần được chèn vào. Tôi không chắc chắn nơi tôi đang đi sai, heck tôi thậm chí không biết nếu đây là một vòng lặp thích hợp, vì vậy tôi sẽ đánh giá cao một số trợ giúp về nó.
Tôi biết rằng đó là vấn đề với các cuộc gọi GetDataTable hoặc SetSqlBulkCopy cuối cùng. Tôi đang cố gắng để chèn 788.189 hàng, 788.000 nhận được trong và số còn lại 189 đang đâm ...
string[] Rows;
using (StreamReader Reader = new StreamReader("C:/?.csv")) {
Rows = Reader.ReadToEnd().TrimEnd().Split(new char[1] {
'\n'
}, StringSplitOptions.RemoveEmptyEntries);
};
int RowsInserted = 0;
using (SqlConnection Connection = new SqlConnection("")) {
Connection.Open();
DataTable Table = null;
while ((RowsInserted < Rows.Length) && ((Rows.Length - RowsInserted) >= 1000)) {
Table = GetDataTable(Rows.Skip(RowsInserted).Take(1000).ToArray());
SetSqlBulkCopy(Table, Connection);
RowsInserted += 1000;
};
Table = GetDataTable(Rows.Skip(RowsInserted).ToArray());
SetSqlBulkCopy(Table, Connection);
Connection.Close();
};
static DataTable GetDataTable(
string[] Rows) {
using (DataTable Table = new DataTable()) {
Table.Columns.Add(new DataColumn("A"));
Table.Columns.Add(new DataColumn("B"));
Table.Columns.Add(new DataColumn("C"));
Table.Columns.Add(new DataColumn("D"));
for (short a = 0, b = (short)Rows.Length; a < b; a++) {
string[] Columns = Rows[a].Split(new char[1] {
','
}, StringSplitOptions.RemoveEmptyEntries);
DataRow Row = Table.NewRow();
Row["A"] = Columns[0];
Row["B"] = Columns[1];
Row["C"] = Columns[2];
Row["D"] = Columns[3];
Table.Rows.Add(Row);
};
return (Table);
};
}
static void SetSqlBulkCopy(
DataTable Table,
SqlConnection Connection) {
using (SqlBulkCopy SqlBulkCopy = new SqlBulkCopy(Connection)) {
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("A", "A"));
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("B", "B"));
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("C", "C"));
SqlBulkCopy.ColumnMappings.Add(new SqlBulkCopyColumnMapping("D", "D"));
SqlBulkCopy.BatchSize = Table.Rows.Count;
SqlBulkCopy.DestinationTableName = "E";
SqlBulkCopy.WriteToServer(Table);
};
}
EDIT/CUỐI CÙNG Mã sản phẩm: Vì vậy, các ứng dụng hiện nay là hoàn thành và các công trình tuyệt vời, và khá nhanh chóng! @ mattmc3, cảm ơn tất cả sự giúp đỡ! Đây là mã cuối cùng cho bất kỳ ai có thể thấy nó hữu ích:
List<string> Rows = new List<string>();
using (StreamReader Reader = new StreamReader(@"?.csv")) {
string Line = string.Empty;
while (!String.IsNullOrWhiteSpace(Line = Reader.ReadLine())) {
Rows.Add(Line);
};
};
if (Rows.Count > 0) {
int RowsInserted = 0;
DataTable Table = new DataTable();
Table.Columns.Add(new DataColumn("Id"));
Table.Columns.Add(new DataColumn("A"));
while ((RowsInserted < Rows.Count) && ((Rows.Count - RowsInserted) >= 1000)) {
Table = GetDataTable(Rows.Skip(RowsInserted).Take(1000).ToList(), Table);
PerformSqlBulkCopy(Table);
RowsInserted += 1000;
Table.Clear();
};
Table = GetDataTable(Rows.Skip(RowsInserted).ToList(), Table);
PerformSqlBulkCopy(Table);
};
static DataTable GetDataTable(
List<string> Rows,
DataTable Table) {
for (short a = 0, b = (short)Rows.Count; a < b; a++) {
string[] Columns = Rows[a].Split(new char[1] {
','
}, StringSplitOptions.RemoveEmptyEntries);
DataRow Row = Table.NewRow();
Row["A"] = "";
Table.Rows.Add(Row);
};
return (Table);
}
static void PerformSqlBulkCopy(
DataTable Table) {
using (SqlBulkCopy SqlBulkCopy = new SqlBulkCopy(@"", SqlBulkCopyOptions.TableLock)) {
SqlBulkCopy.BatchSize = Table.Rows.Count;
SqlBulkCopy.DestinationTableName = "";
SqlBulkCopy.WriteToServer(Table);
};
}
Một vài đề xuất nếu bạn muốn tăng tốc độ này nhiều hơn nữa. 1.) Thay vì làm Reader.ReadToEnd(), tạo một vòng lặp và đọc Reader.ReadLine() một dòng tại một thời điểm. Nó sẽ mất ít bộ nhớ hơn. 2.) Nếu không ai sẽ truy cập vào bảng của bạn trong thời gian bạn đang tải nó, hãy sử dụng tùy chọn 'SqlBulkCopyOptions.TableLock'. 3.) Để lưu lại một số mã, đối tượng SqlBulkCopy sẽ chèn ánh xạ cột của bạn nếu bạn đặt tên cho các cột giống như những gì trong bảng đích của bạn, và vì bạn đang xử lý chunking, không có lý do gì để thiết lập .BatchSize. Chúc mừng mã hóa! – mattmc3
Về chủ đề suy luận các cột, nó sẽ hoạt động nếu: 'DBTable = {Id (PK, IDENTITY), A, B, C, D}', nhưng 'DataTable = {A, B, C, D}'? Tôi nghĩ rằng nó đã gây rắc rối cho tôi, đó là lý do tại sao tôi chỉ định cho họ, nhưng sau đó một lần nữa, tôi có thể đã được screwing nó bằng cách nào đó ... – Gup3rSuR4c
Vâng, nó được thực hiện! Tôi đã triển khai mọi thứ bạn đã đề xuất và nó hoạt động tuyệt vời! Bộ nhớ đã giảm một nửa xuống còn 85MB và toàn bộ hoạt động mất khoảng 45 giây để hoàn thành. Và tôi đã tìm ra các cột ở trên, tôi đã đúng, nhưng tôi chỉ thêm một trình giữ chỗ cho 'Id' và nó hoạt động. 'THANK YOU TRỢ GIÚP TÔI VỀ NÀY VÀ CHO DẠY CHO TÔI VỀ NHỮNG ĐIỀU Tôi KHÔNG BAO GIỜ BIẾT !!!” – Gup3rSuR4c