.NetCore使用EFCore時大量數據分組排序還有多個表互相查詢很慢,優化后使用sql語句來運行,使用FromSqlRaw不是FromSql


前言:數據庫 :Sql Server2016

編輯器:VS2019
環境 :.net core 和efcore
數據量:5萬條
相關聯的表:3個相關表

!!!:這些表創建時沒有外鍵等相關連接,所以麻煩


需求:展示個人用戶所有所有的信息,數據分別存在大概5個表里面,有接近6萬人,查詢排列展示出來

吐槽:一開始搞了半天弄到5秒,不行!再改弄到3秒,還是不行!!最后壓縮到了1.4秒左右。這可能是目前我的極限了,如果有大佬有辦法 請!請!請! 給我留言說一下哪里還能優化

答案

一般有FromSqlRaw 和FromSql,我們選FromSqlRaw來用,而FromSql在Efcore3.0中顯示已過時

DbContext.set<ResultList>.FromSqlRaw("select * from ...").ToList() //ResultList是實體類,在數據庫中是視圖.Tolist()必加

 

詳情往下看

一般來說我們在lamdba表達式中進行處理的時候,查詢處理多個表我實測三萬人要處理17分鍾左右(看電腦性能)

 

    例子:以下都是簡寫,有說不通的地方那就對了,不重要,知道干嘛就行了

首先這些最終都是被存到了內存里面了,處理起來耗內存,而且這只是一個人查都占很大內存,
有人說可以不往內存里面存,但是那些排序取第一條,截取其中十幾條展示等等操作很難操作,照樣很慢

var Data = await _userServer.query().ToListAsync();  //所有的用戶 
var File= await _fileServer.query().ToListAsync();
var Photo= await _photoServer.query().ToListAsync();
var Cert = await _certServer.query().ToListAsync();
 
        var result = await Data.Select(x => new Filter
            {
                Id=x.Id,
                Name = x.Name,
                IdCard=x.IdCard,
                File= File.Where(y =>y.IdCard==x.IdCard).Select(t =>new Filter //文件有很多,取最新的一條
                {
                    Id=t.Id,
                    Name=t.Name,
                    CertCode=t.CertCode,
                }).OrderByDescending(t => t.Id).FirstOrDefault(),
                Photo = photo.Where(y =>y.IdCard==x.IdCard).Select(t => new Filter //照片也可以有很多張,取最新
                {
                    Id = t.Id,
                    Name = t.Name,
                    Photo=t.Photo,
                }).OrderByDescending(t => t.Id).FirstOrDefault(),
                Certs = _certService.Query(y => y.IdCard== x.IdCard).OrderByDescending(y => y.Id).FirstOrDefault(),
            }).OrderByDescending(x => x.Id).ToPagedListAsync(Page,PageSize);

看着上面的就很慢,而且,就是說幾萬條數據要在程序里面循環處理十幾萬次才能得出答案,

而最快的方法當然是   原生Sql語句 永遠的神

 

數據

WITH datas as    //這里使用With為了加快sql運行速度,with為SQL片段,截取一塊來用
     (select IdCard, Name from [dbo].[user] GROUP BY  IdCard, Name)

File as  
   (select * from [dbo].[user])
   
  select Data.Id,
         Data.Name,
         F.file,
         P.photo,
         C.Cert
  from datas 
     left join File F    //為什么要用left join 因為一個人對應的 文件 照片 證書 可能為空
           on  F.IdCard=datas.IdCard
           and F.name=datas.name
     left join ........
     left join.........  //懶得寫了,跟上一個一樣

現在數據庫就完成了,但是這樣雖然拼起來了我們查詢也有了,還有一個問題就是我們在后端用什么東西接收存起來

 

 接收

.netcroe+Efcore 自定義類接收時候報錯,不能生成該類型文件得把類加到DbContext中才能正確生成接收

    public class Db : DbContext
    {
        public CertMSDb(DbContextOptions<Db> options) : base(options)
        {
        }
        public virtual DbSet<File> Files{ get; set; }
        public virtual DbSet<Photo> Photos{ get; set; }
        public virtual DbSet<Cert> Certs{ get; set; }
        
        //我們得自己加一條不然不能直接接收我們的數據
        public virtual DbSet<ResultList> ResultLists{ get; set; }
   }

//這個類型就跟我們的取出來的值保持一致
 public class ResultList
 {
   public int Id{get;set;}
   public int Name{get;set;}
   public int File{get;set;}
   public int Photo{get;set;}
   public int Cert{get;set;}
 }

完成后使用就簡單,可以簡寫

     //一般我們使用
     var Data = _userServer.query<ResultList>();
     //或者
     var data =DbContext.set<ResultList>();
     //還有
     var data =DbContext.set<ResultList>().FromSqlRaw("sql");


     //直接使用      注意,加了s的實例后的名字
     var data =DbContext.ResultLists.FromSqlRaw("sql").ToList();  //注意后面得加上ToList()或者其他的

上述為我處理的方式簡寫版本可能寫的改的有漏了,更多可以在這上面加其他功能


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM