Để tăng tốc độ điều bạn nên sử dụng các giao dịch hàng loạt (Entity Nhóm giao dịch), cho phép bạn cam kết lên đến 100 mục trong một yêu cầu duy nhất:
foreach (var item in myItemsToAdd)
{
this.Context.AddObject(TableName, item);
}
this.Context.SaveChanges(SaveChangesOptions.Batch);
Bạn có thể kết hợp này với Partitioner.Create (+ AsParallel) để gửi nhiều yêu cầu về các luồng/lõi khác nhau cho mỗi lô 100 mục để làm cho mọi thứ thực sự nhanh chóng.
Nhưng trước khi thực hiện tất cả việc này, read through the limitations sử dụng giao dịch hàng loạt (100 mục, 1 phân vùng cho mỗi giao dịch, ...).
Cập nhật:
Vì bạn không thể sử dụng giao dịch ở đây là một số mẹo khác. Hãy xem this MSDN thread về cải thiện hiệu suất khi sử dụng bộ nhớ bảng. Tôi đã viết một số mã để cho bạn thấy sự khác biệt:
private static void SequentialInserts(CloudTableClient client)
{
var context = client.GetDataServiceContext();
Trace.WriteLine("Starting sequential inserts.");
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000; i++)
{
Trace.WriteLine(String.Format("Adding item {0}. Thread ID: {1}", i, Thread.CurrentThread.ManagedThreadId));
context.AddObject(TABLENAME, new MyEntity()
{
Date = DateTime.UtcNow,
PartitionKey = "Test",
RowKey = Guid.NewGuid().ToString(),
Text = String.Format("Item {0} - {1}", i, Guid.NewGuid().ToString())
});
context.SaveChanges();
}
stopwatch.Stop();
Trace.WriteLine("Done in: " + stopwatch.Elapsed.ToString());
}
Vì vậy, lần đầu tiên tôi chạy này tôi nhận được kết quả như sau:
Starting sequential inserts.
Adding item 0. Thread ID: 10
Adding item 1. Thread ID: 10
..
Adding item 999. Thread ID: 10
Done in: 00:03:39.9675521
Phải mất hơn 3 phút để thêm 1000 mặt hàng. Bây giờ, tôi đã thay đổi app.config dựa trên những lời khuyên trên diễn đàn MSDN (maxconnection nên 12 * số lõi CPU):
<system.net>
<settings>
<servicePointManager expect100Continue="false" useNagleAlgorithm="false"/>
</settings>
<connectionManagement>
<add address = "*" maxconnection = "48" />
</connectionManagement>
</system.net>
Và sau khi chạy ứng dụng một lần nữa tôi nhận được kết quả này:
Starting sequential inserts.
Adding item 0. Thread ID: 10
Adding item 1. Thread ID: 10
..
Adding item 999. Thread ID: 10
Done in: 00:00:18.9342480
Từ trên 3 phút đến 18 giây. Thật la khac biệt! Nhưng chúng ta có thể làm tốt hơn nữa. Dưới đây là một số mã chèn tất cả các mục sử dụng một phân vùng (chèn sẽ xảy ra song song):
private static void ParallelInserts(CloudTableClient client)
{
Trace.WriteLine("Starting parallel inserts.");
var stopwatch = new Stopwatch();
stopwatch.Start();
var partitioner = Partitioner.Create(0, 1000, 10);
var options = new ParallelOptions { MaxDegreeOfParallelism = 8 };
Parallel.ForEach(partitioner, options, range =>
{
var context = client.GetDataServiceContext();
for (int i = range.Item1; i < range.Item2; i++)
{
Trace.WriteLine(String.Format("Adding item {0}. Thread ID: {1}", i, Thread.CurrentThread.ManagedThreadId));
context.AddObject(TABLENAME, new MyEntity()
{
Date = DateTime.UtcNow,
PartitionKey = "Test",
RowKey = Guid.NewGuid().ToString(),
Text = String.Format("Item {0} - {1}", i, Guid.NewGuid().ToString())
});
context.SaveChanges();
}
});
stopwatch.Stop();
Trace.WriteLine("Done in: " + stopwatch.Elapsed.ToString());
}
Và kết quả:
Starting parallel inserts.
Adding item 0. Thread ID: 10
Adding item 10. Thread ID: 18
Adding item 999. Thread ID: 16
..
Done in: 00:00:04.6041978
Thì đấy, từ 3m39s chúng tôi giảm xuống còn 18s và bây giờ chúng tôi thậm chí giảm xuống 4s.
Bạn có vô tình gọi tất cả logic đó với CreateTableIfNotExist() trong một vòng lặp không? hoặc chỉ Add/SaveChanges() trong một vòng lặp? CreateTableIfNotExist() không phải là một cuộc gọi giá rẻ và bạn muốn bỏ qua nó nếu nó không cần thiết – Igorek
Mã này chạy cho mỗi yêu cầu. Bạn đang phải trả tiền để gọi CreateTableIfNotExist bất kỳ lúc nào. Tôi sẽ cố gắng loại bỏ nó và chỉ làm gì nếu bảng không tồn tại lỗi. – gabba