複雜查詢還是直接寫sql吧

法宝發表於2024-08-08

今日改了一個linq,為了查詢最佳化。

主要思路是把子查詢改為連線查詢。

改完後,本地執行是很快的;但是釋出到伺服器,加上網路時間,就有點不如意了。

所以感覺,非常複雜的查詢還是直接用sql寫好。

更改前後

更改前是這樣的。

            void setPropety(List<SEO_Cust_RechargeModel> _list)
            {
                SEO_Set_MealBusiness sEO_Set_MealBusiness = new SEO_Set_MealBusiness();
                SEO_CustBusiness sEO_CustBusiness = new SEO_CustBusiness();
                //SEO_Cust_ProductBusiness sEO_Cust_ProductBusiness = new SEO_Cust_ProductBusiness();
                var domain = new Seo_Domain.SEO_DomainBusiness().GetIQueryable();
                var keywords = new SEO_KeyWordBusiness().GetIQueryable();
                var newsfeed = new Seo_NewsFeed.SEO_NewsFeedBusiness().GetIQueryable();
                var zengzhibus = new SEO_ZengZhiFwBusiness();
                _list.ForEach(x =>
                {
                    x.SetMeal_Name = sEO_Set_MealBusiness.GetTheData(x.setmeal_id)?.set_meal_name;
                    x.Cust_Nmae = sEO_CustBusiness.GetTheData(x.cust_id)?.user_name;
                    x.domainnum = domain.Where(xx => xx.cust_recharge_id == x.Id).Count();
                    x.keywordnum = keywords.Where(xx => xx.recharge_id == x.Id).Count();
                    x.newsfeednum = newsfeed.Where(xx => xx.recharge_id == x.Id).Count();
                    x.zengzhinum = zengzhibus.GetIQueryable().Count(y => y.recharge_id == x.Id);
                    x.pinpainum = new SEO_PinPai_KeyWordBusiness().GetIQueryable().Where(xx => xx.recharge_id == x.Id).Count();
                    x.SEOUser_Name = Base_UserBusiness.GetTheUser(x.seo_user_id)?.RealName;
                });
            }

更改後是這樣的。

            void setPropetyByJoin(List<SEO_Cust_RechargeModel> _list)
            {
                //5個count
                var queryCount = from r in _list
                                 join dm in new SEO_DomainBusiness().GetIQueryable() on r.Id equals dm.cust_recharge_id into dmg
                                 join kw in new SEO_KeyWordBusiness().GetIQueryable() on r.Id equals kw.recharge_id into kwg
                                 join nf in new SEO_NewsFeedBusiness().GetIQueryable() on r.Id equals nf.recharge_id into nfg
                                 join zz in new SEO_ZengZhiFwBusiness().GetIQueryable() on r.Id equals zz.recharge_id into zzg
                                 join pp in new SEO_PinPai_KeyWordBusiness().GetIQueryable() on r.Id equals pp.recharge_id into ppg
                                 select new
                                 {
                                     rId = r.Id,
                                     dmCount = dmg.Count(),
                                     kwCount = kwg.Count(),
                                     nfCount = nfg.Count(),
                                     zzCount = zzg.Count(),
                                     ppCount = ppg.Count(),
                                 };
                var lct = queryCount.ToList();

                //連線其他表
                var queryJoin = from r in _list
                                join c in queryCount.Distinct() on r.Id equals c.rId
                                join sm in new SEO_Set_MealBusiness().GetIQueryable() on r.setmeal_id equals sm.Id into rSmG
                                join cst in new SEO_CustBusiness().GetIQueryable() on r.cust_id equals cst.Id into rCstG
                                join bu in new Base_UserBusiness().GetIQueryable() on r.seo_user_id equals bu.UserId into rBuG
                                join pr in new SEO_ProductBusiness().GetIQueryable() on r.product_id equals pr.Id into rPrG
                                from rSm in rSmG.DefaultIfEmpty()
                                from rCst in rCstG.DefaultIfEmpty()
                                from rBu in rBuG.DefaultIfEmpty()
                                from rPr in rPrG.DefaultIfEmpty()
                                select new
                                {
                                    r = r,
                                    c = c,
                                    agent_id = rCst?.agent_id ?? "",
                                    xs_user_id = rCst?.xs_user_id ?? "",
                                    SetMeal_Name = rSm == null ? "" : rSm.set_meal_name,
                                    Cust_Nmae = rCst == null ? "" : rCst.user_name,
                                    SEOUser_Name = rBu == null ? "" : rBu.RealName,
                                    pro_name = rPr == null ? "-" : rPr.pro_name,
                                    aftersale_user_id = rCst.aftersale_user_id, 
                                };

                //二次連線的
                var queryJoin2 = from m in queryJoin
                                 join ag in new SEO_AgentBusiness().GetIQueryable() on m.agent_id equals ag.Id into mAgG
                                 join buAfter in new Base_UserBusiness().GetIQueryable() on m.aftersale_user_id equals buAfter.UserId into mBuAfterG
                                 from mAg in mAgG.DefaultIfEmpty()
                                 from mBuAfter in mBuAfterG.DefaultIfEmpty()
                                 select new
                                 {
                                     r = m.r,
                                     c = m.c,
                                     agent_id = m.agent_id,
                                     xs_user_id = m.xs_user_id,
                                     SetMeal_Name = m.SetMeal_Name,
                                     Cust_Nmae = m.Cust_Nmae,
                                     SEOUser_Name = m.SEOUser_Name,
                                     pro_name = m.pro_name,
                                     SEOAfterSale_Name = m.aftersale_user_id.IsNullOrEmpty() || m.aftersale_user_id == "0" ?
                                                        "-" :
                                                        mBuAfter?.RealName??"-",
                                     SEOSale_Name = (m.xs_user_id.IsNullOrEmpty() || m.xs_user_id == "0") ? 
                                                    mAg?.inst_value??"-" : 
                                                    m.SEOUser_Name,
                                 }; 

                //迴圈賦值
                queryJoin2.Select(m =>
                {
                    //Count的
                    m.r.domainnum = m.c.dmCount;
                    m.r.keywordnum = m.c.kwCount;
                    m.r.newsfeednum = m.c.nfCount;
                    m.r.zengzhinum = m.c.zzCount;
                    m.r.pinpainum = m.c.ppCount;
                    //單個屬性
                    m.r.SetMeal_Name = m.SetMeal_Name;
                    m.r.Cust_Nmae = m.Cust_Nmae;
                    m.r.SEOUser_Name = m.SEOUser_Name;
                    m.r.pro_name = m.pro_name;
                    m.r.SEOAfterSale_Name = m.SEOAfterSale_Name;
                    m.r.SEOSale_Name = m.SEOSale_Name; 
                    return 1;
                }).ToList();
            }

可以明顯的看到:

子查詢看起來簡單;但是執行效率低。

連線查詢編寫起來複雜,特別是用linq寫,就更復雜了。

還有第二波問題:

改完一波,我才發現,原來的作者在ViewModel里弄了一些有get訪問器的屬性。

而有幾個get訪問器,在裡面操作了資料庫。也相當於子查詢。

於是又改了一波。

另外重要的

另外重要的,感覺是資料表的設計。

因為,感覺,雖然不知道是什麼業務;有些欄位的獲取應該不用關聯這麼多表吧?應該是可以簡化的。

相關文章