前提:
需要nuget PredicateLib 0.0.5;
SqlServer 2008R2 (建議安裝 64 位);
.net 4.5 或以上;
當前電腦配置: I7 4核 3.6GHZ,8G 內存 (辦公電腦 ,win10 64位)
描述:
在實際項目中我們會遇到多個表關聯查詢數據,並進行分頁操作;當數據量很大的時候如(500萬或以上)的時候,分頁很吃力,特別還需要一些模糊查詢,排序的時候會導致很慢;
本文章主要解決分頁及多個數據表關系查詢速度慢的問題:
解決辦法及優化過程:
1、通常我們對 數據庫的優化莫過於索引,儲存過程等;
2、能使用一條Sql 語句查詢的話,不要使用多條語句(學習使用 linq 語法);
3、盡量少使用 in ('.....') 多個值;經測試超過 5萬個 in 的時候會提示內存不足異常;
4、order 的使用很是奇葩,原本用 order Id(主鍵),反而查詢非常慢,而且 Cpu 使用一下子 100%,換成別的字段就完全沒壓力;(暫時無法理解,在出現問題后可嘗試改變 order)
5、盡量 select 少的字段,在實際中遇到 分頁的時候,先 select 出 Id,然后在通過 Id 去查詢完整數據,會比直接查詢完整要快 N 倍;
如通過兩條語句查詢出大數據的時候:var ids = select top 10 Id from ViewTable;
var datas = select * from ViewTable where Id in (ids);
結合表示式生成分頁查詢擴展(完美優化):
非常實用的硬代碼,在大數據分頁的時候性能優越:
主要原理跟上面 第 5點 一樣,但優化只通過一次查詢出完整數據;
缺點: 每頁的數據量建議不要太大,比如:每頁1萬
/// <summary> /// 執行分頁 /// 性能比較好 /// </summary> /// <typeparam name="T">實體類型<peparam> /// <param name="source">數據源</param> /// <param name="orderBy">排序字符串</param> /// <param name="pageIndex">分頁索引</param> /// <param name="pageSize">分頁大小</param> /// <param name="idSelector">Id選擇器</param> /// <returns></returns> public static async Task<PageInfo<T>> ToPageAsync<T, TId>(this IQueryable<T> source, string orderBy, int pageIndex, int pageSize, Expression<Func<T, TId>> idSelector) where T : class where TId : class { source = source.Where(Predicate.Create(idSelector, null, Operator.NotEqual)); int total = await source.CountAsync(); var inc = total % pageSize > 0 ? 0 : -1; var maxPageIndex = (int)Math.Floor((double)total / pageSize) + inc; pageIndex = Math.Max(0, Math.Min(pageIndex, maxPageIndex)); var idQuery = source.OrderBy(orderBy).Skip(pageIndex * pageSize).Take(pageSize).Select(idSelector); var datas = await source.Join(idQuery, idSelector, item => item, (item, id) => item).OrderBy(orderBy).ToArrayAsync(); var page = new PageInfo<T>(total, datas) { PageIndex = pageIndex, PageSize = pageSize }; return page; }