回到目錄
最近總遇到大資料的問題,一次性處理幾千萬資料不實際,是以,我們需要對大資料進行分塊處理,或者叫分頁處理,我在EF架構裡曾經寫過類似的,那是在進行BulkInsert時,對大資料批量插入時候用到的,現在我把它拿出來,放在IQueryableExtensions類中,即它将作為IQueryable的一個擴充出現,我們可以把這個分頁處理的邏輯應用的更加廣泛,并且,在這個整理中,提供了異步并行版本,它比同版版本快了幾十倍之多,可以說,目前的伺服器,隻有使用了并且計算之後,才能發揮它的作用!
/// <summary>
/// 并行分頁處理資料,提高系統使用率,提升系統性能
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="item"></param>
/// <param name="method"></param>
public async static Task DataPageProcessAsync<T>(
IQueryable<T> item,
Action<IEnumerable<T>> method) where T : class
{
await Task.Run(() =>
{
DataPageProcess<T>(item, method);
});
}
/// <summary>
/// 在主線程上分頁處理資料
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="item"></param>
/// <param name="method"></param>
public static void DataPageProcess<T>(
IQueryable<T> item,
Action<IEnumerable<T>> method) where T : class
{
if (item != null && item.Count() > 0)
{
var DataPageSize = 100;
var DataTotalCount = item.Count();
var DataTotalPages = item.Count() / DataPageSize;
if (DataTotalCount % DataPageSize > 0)
DataTotalPages += 1;
for (int pageIndex = 1; pageIndex <= DataTotalPages; pageIndex++)
{
var currentItems = item.Skip((pageIndex - 1) * DataPageSize).Take(DataPageSize).ToList();
method(currentItems);
}
}
}
事實上,有了上面的方法,以後在進行分面處理資料時,隻要有IQueryable的結果集和要處理的方法傳進來就可以了,友善至極!
下面代碼是選自我的FastSocket項目,對大資料進行傳輸時,使用的代碼
#region 分頁資料傳輸
DataPageProcessAsync(model, (list) =>
{
client.Send("DSSInsert"
, 1
, 1
, item.Name//VersionHelper.GetNumber(ProjectID.NewLearningBar)
, SerializeMemoryHelper.SerializeToBinary(list)
, res => res.Buffer).ContinueWith(c =>
{
if (c.IsFaulted)
{
throw c.Exception;
}
Console.WriteLine(BitConverter.ToBoolean(c.Result, 0));
});
});
#endregion
我自己試了同步方法DataPageProcess和并行異步方法DataPageProcessAsync,後都比較前者至少要快幾十倍,當然這和你的CPU有關,你的CPU處理的線程數超多,這個倍數将會越大!
作者:倉儲大叔,張占嶺,
榮譽:微軟MVP
QQ:853066980
支付寶掃一掃,為大叔打賞!
