2012-11-20 38 views
1

對於一個項目,我們不得不使用現有的表與實體框架。這解決了1大LINQ查詢的搜索功能。目前這個功能需要3秒鐘才能得到10個結果。Linq查詢頭疼

問題是,如果有人知道要改善這個linq的要點?

這是LINQ查詢:

var result = (from o in db.Objects 
            join omsc in db.Omschrijvingen on o.Omschrijving_Identifier equals omsc.Identifier 
            join a in db.Adressen on o.Adres_Id equals a.Adres_Id 
            join oa in db.Object_Abonnement on o.Object_Id equals oa.Object_ID 
            join oaf in db.Object_Afbeeldingen on o.Object_Id equals oaf.Object_Id 
            where o.Enabled && oaf.StandaardAfbeelding == true && 
             (!iType.Any() || iType.Contains(o.Type_Id)) && 
             (iProvince < 1 || a.Provincie_Id == iProvince) && 
             (iDepartement < 1 || a.Departement_Id == iDepartement) && 
             o.Object_Logs.All(
              ol => ol.Log_Type != (int) ApplicationDefinitions.LogTypes.Deleted) && 
             (oa.Betaald && oa.Tot >= DateTime.Now) && 
             (!kenmerken.Any() || 
             db.Object_Kenmerken.Count(
              ken => 
              kenmerken.Contains(ken.Kenmerk_Id) && ken.Object_Id == o.Object_Id && 
              ken.Waarde.ToUpper() != "FALSE" && ken.Waarde != "0") == kenmerken.Count()) && 
             (search.Length < 1 || omsc.Naam.ToLower().Contains(search.ToLower()) || 
             omsc.Omschrijving.ToLower().Contains(search.ToLower()) || 
             a.Woonplaats.ToLower().Contains(search.ToLower())) 
            select new FullObject 
              { 
               Object_Id = o.Object_Id, 
               Adres_Id = a.Adres_Id, 
               DepartmentId = a.Departement_Id, 
               Department = (a.Departementen != null) ? a.Departementen.Naam : "", 
               ProviciesId = a.Provincie_Id, 
               Provicie = (a.Provicies != null) ? a.Provicies.Naam : "", 
               Contact_Id = o.Contact_Id, 
               Naam = omsc.Naam, 
               Omschrijving = omsc.Omschrijving, 
               Prijs = 
                (((db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id).Min(
                 pp => pp.Prijs_Dag) > 0) 
                  ? db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id). 
                   Min(pp => pp.Prijs_Dag) 
                  : db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id). 
                   Min(pp => pp.Prijs_Week)) > 0) 
                 ? (db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id). 
                   Min 
                   (pp => pp.Prijs_Dag) > 0) 
                   ? db.Prijs_Periode 
                    .Where(
                     pp => pp.Object_Id == o.Object_Id) 
                    .Min(pp => pp.Prijs_Dag) 
                   : db.Prijs_Periode 
                    .Where(
                     pp => pp.Object_Id == o.Object_Id) 
                    .Min(pp => pp.Prijs_Week/7) 
                 : (db.Prijs_Periode 
                   .Where(pp => pp.Object_Id == o.Object_Id) 
                   .Min(pp => pp.Prijs_Weekend) > 0) 
                   ? db.Prijs_Periode 
                    .Where(
                     pp => pp.Object_Id == o.Object_Id) 
                    .Min(pp => pp.Prijs_Weekend/3) 
                   : (db.Prijs_Periode 
                     .Where(
                      pp => pp.Object_Id == o.Object_Id) 
                     .Min(pp => pp.Prijs_Midweek) > 0) 
                    ? db.Prijs_Periode 
                      .Where(
                       pp => 
                       pp.Object_Id == o.Object_Id) 
                      .Min(pp => pp.Prijs_Midweek/14) 
                    : (db.Prijs_Periode 
                      .Where(
                       pp => 
                       pp.Object_Id == o.Object_Id) 
                      .Min(pp => pp.Prijs_Langweekend) > 
                     0) 
                      ? db.Prijs_Periode 
                       .Where(
                        pp => 
                        pp.Object_Id == o.Object_Id) 
                       .Min(
                        pp => 
                        pp.Prijs_Langweekend) 
                      : 0, 
               SPrijs = (((db.Prijs_Periode 
                   .Where(
                    pp => 
                    pp.Object_Id == o.Object_Id && 
                    pp.Aanbieding == false) 
                   .Min(pp => pp.Prijs_Dag) > 0) 
                   ? db.Prijs_Periode 
                     .Where(
                      pp => 
                      pp.Object_Id == o.Object_Id && 
                      pp.Aanbieding == false) 
                     .Min(pp => pp.Prijs_Dag) 
                   : db.Prijs_Periode 
                     .Where(
                      pp => 
                      pp.Object_Id == o.Object_Id && 
                      pp.Aanbieding == false) 
                     .Min(pp => pp.Prijs_Week)) > 0) 
                   ? (db.Prijs_Periode 
                    .Where(
                     pp => 
                     pp.Object_Id == o.Object_Id && 
                     pp.Aanbieding == false) 
                    .Min(pp => pp.Prijs_Dag) > 0) 
                    ? db.Prijs_Periode 
                      .Where(
                       pp => 
                       pp.Object_Id == o.Object_Id && 
                       pp.Aanbieding == false) 
                      .Min(pp => pp.Prijs_Dag) 
                    : db.Prijs_Periode 
                      .Where(
                       pp => 
                       pp.Object_Id == o.Object_Id && 
                       pp.Aanbieding == false) 
                      .Min(pp => pp.Prijs_Week/7) 
                   : (db.Prijs_Periode 
                    .Where(
                     pp => 
                     pp.Object_Id == o.Object_Id && 
                     pp.Aanbieding == false) 
                    .Min(pp => pp.Prijs_Weekend) > 0) 
                    ? db.Prijs_Periode 
                      .Where(
                       pp => 
                       pp.Object_Id == o.Object_Id && 
                       pp.Aanbieding == false) 
                      .Min(pp => pp.Prijs_Weekend/3) 
                    : (db.Prijs_Periode 
                      .Where(
                       pp => 
                       pp.Object_Id == o.Object_Id && 
                       pp.Aanbieding == false) 
                      .Min(pp => pp.Prijs_Midweek) > 0) 
                      ? db.Prijs_Periode 
                       .Where(
                        pp => 
                        pp.Object_Id == o.Object_Id && 
                        pp.Aanbieding == false) 
                       .Min(pp => pp.Prijs_Midweek/14) 
                      : (db.Prijs_Periode 
                       .Where(
                        pp => 
                        pp.Object_Id == o.Object_Id && 
                        pp.Aanbieding == false) 
                       .Min(pp => pp.Prijs_Langweekend) > 
                      0) 
                       ? db.Prijs_Periode 
                         .Where(
                          pp => 
                          pp.Object_Id == o.Object_Id && 
                          pp.Aanbieding == false) 
                         .Min(
                          pp => 
                          pp.Prijs_Langweekend) 
                       : 0, 
               Personen = 
                (db.Object_Kenmerken.Any(
                 iok => 
                 iok.Kenmerk_Id == iAantalPersonenId && 
                 iok.Object_Id == o.Object_Id)) 
                 ? db.Object_Kenmerken.Where(
                  iok => 
                  iok.Kenmerk_Id == iAantalPersonenId && 
                  iok.Object_Id == o.Object_Id).Select(
                   iok => EntitiesFunctions.ParseInt(iok.Waarde)). 
                   FirstOrDefault() 
                 : 0, 
               Slaapkamers = 
                (db.Object_Kenmerken.Any(
                 iok => 
                 iok.Kenmerk_Id == iAantalSlaapkamersId && 
                 iok.Object_Id == o.Object_Id)) 
                 ? db.Object_Kenmerken.Where(
                  iok => 
                  iok.Kenmerk_Id == iAantalSlaapkamersId && 
                  iok.Object_Id == o.Object_Id).Select(
                   iok => EntitiesFunctions.ParseInt(iok.Waarde)). 
                   FirstOrDefault() 
                 : 0, 
               UrlKey = omsc.UrlKey, 
               Title = omsc.Title, 
               Plaats = a.Woonplaats, 
               Enabled = o.Enabled, 
               GoogleMap_Url = o.GoogleMap_Url, 
               InkoopPrijs = o.InkoopPrijs, 
               Type_Id = o.Type_Id, 
               Website = o.Website, 
               Adressen = o.Adressen, 
               Thumb = oaf.Tumbnial 
              } 
           ) 
        .Where(item => (item.Prijs >= minPrice || minPrice == 0) && 
            (item.Prijs <= maxPrice || maxPrice == 0) && 
            (bOffersOnly == false || item.Prijs < item.SPrijs) && 
            (item.Personen >= personen || personen == 0) && 
            (item.Slaapkamers == slaapkamers || slaapkamers == 0)) 
        .Distinct(); 

爲了更清楚:

我們需要得到以下對象:

public class FullObject 
     { 
      public int Object_Id { get; set; } 
      public int? Adres_Id { get; set; } 
      public int Contact_Id { get; set; } 
      public string Naam { get; set; } 
      public string Omschrijving { get; set; } 
      public decimal? Prijs { get; set; } 
      public decimal? SPrijs { get; set; } 
      public int Personen { get; set; } 
      public int Slaapkamers { get; set; } 
      public string UrlKey { get; set; } 
      public string Title { get; set; } 
      public string Plaats { get; set; } 
      public int ProviciesId { get; set; } 
      public string Provicie { get; set; } 
      public int? DepartmentId { get; set; } 
      public string Department { get; set; } 
      public bool Enabled { get; set; } 
      public string GoogleMap_Url { get; set; } 
      public decimal? InkoopPrijs { get; set; } 
      public int Type_Id { get; set; } 
      public string Website { get; set; } 
      public List<Data.Object_Kenmerken> ItemKenmerken { get; set; } 
      public Data.Adressen Adressen { get; set; } 
      public string Thumb { get; set; } 
     } 

我們必須對以下過濾器東西

int[] iType 
string search 
int[] kenmerken 
int iProvince 
int iDepartement 
decimal minPrice 
decimal maxPrice 
int personen 
int slaapkamers 
bool bOffersOnly 

這是(一點點)的表結構:

http://i.stack.imgur.com/3Y0Tf.jpg

我們試圖分別得到一切,但後來我們一共12秒(和增長)得到,因爲許多對象那是在數據庫中,然後我們需要通過過濾來獲取它們。

我希望有人認爲這是一個挑戰,看到我忽視的東西。

在此先感謝。

克里斯蒂安

由於此單被關閉,我的回答:

感謝所有的答覆。

最好的是@ Daniel-Hilgarth。不要在查詢中進行計算。爲了解決這個問題,我們選擇在每15分鐘運行一次的SQL作業中進行計算,並將結果直接放入Object表中。

接下來,我們已經改變了一點點連接到數據庫邏輯。感謝@ Micheal-Samteladze。

所有這些變化給了我們以下查詢。

var result = (from o in db.Objects 
       join omsc in db.Omschrijvingen on o.Omschrijving_Identifier equals omsc.Identifier 
       where o.Enabled && 
        (!iType.Any() || iType.Contains(o.Type_Id)) && 
        (o.Prijs >= minPrice || minPrice == 0) && 
        (o.Prijs <= maxPrice || maxPrice == 0) && 
        (bOffersOnly == false || o.Prijs < o.SPrijs) && 
        (o.Personen >= personen || personen == 0) && 
        (o.Kamers == slaapkamers || slaapkamers == 0) && 
        (iProvince < 1 || o.Adressen.Provincie_Id == iProvince) && 
        (iDepartement < 1 || o.Adressen.Departement_Id == iDepartement) && 
        o.Object_Logs.All(ol => ol.Log_Type != (int) ApplicationDefinitions.LogTypes.Deleted) && 
        o.Object_Abonnement.Any(oa => oa.Betaald && oa.Tot >= DateTime.Now) && 
        (!kenmerken.Any() || o.Object_Kenmerken.Count(ken => kenmerken.Contains(ken.Kenmerk_Id) && ken.Object_Id == o.Object_Id && ken.Waarde.ToUpper() != "FALSE" && ken.Waarde != "0") == kenmerken.Count()) && 
        (search.Length < 1 || omsc.Naam.ToLower().Contains(search.ToLower()) || omsc.Omschrijving.ToLower().Contains(search.ToLower()) || o.Adressen.Woonplaats.ToLower().Contains(search.ToLower())) 
       select new FullObject 
       { 
        Object_Id = o.Object_Id, 
        Adres_Id = o.Adressen.Adres_Id, 
        DepartmentId = o.Adressen.Departement_Id, 
        Department = (o.Adressen.Departementen != null) ? o.Adressen.Departementen.Naam : "", 
        ProviciesId = o.Adressen.Provincie_Id, 
        Provicie = (o.Adressen.Provicies != null) ? o.Adressen.Provicies.Naam : "", 
        Contact_Id = o.Contact_Id, 
        Naam = omsc.Naam, 
        Omschrijving = omsc.Omschrijving, 
        Prijs = o.Prijs ?? 0, 
        SPrijs = o.SPrijs ?? 0, 
        Personen = o.Personen, 
        Slaapkamers = 0, 
        UrlKey = omsc.UrlKey, 
        Title = omsc.Title, 
        Plaats = o.Adressen.Woonplaats, 
        Enabled = o.Enabled, 
        GoogleMap_Url = o.GoogleMap_Url, 
        InkoopPrijs = o.InkoopPrijs, 
        Type_Id = o.Type_Id, 
        Website = o.Website, 
        Adressen = o.Adressen, 
        Thumb = o.Object_Afbeeldingen.FirstOrDefault(af => af.StandaardAfbeelding).Tumbnial 
       } 
      ) 
.Distinct(); 

這大約需要1個半第二,得到第10的結果,其中舊土氣最低的3

但我仍然開放的建議。

感謝

克里斯蒂安

+9

聖。 生活。 CRAP! –

+0

是的,當我需要這樣的速度時,這也是我的反應。 –

+4

我們在這裏沒有什麼可以做的。問題是這個查詢只是試圖做太多。但是,如果不知道實際應該做什麼,就很難優化它。 **老實說,這個查詢是一個很大的失敗。**它是無法維持到極致的。然而,有一件事:在那裏有許多令人難以置信的子查詢,我想知道是否有意義地完全獲取這些表並在內存中執行一些這些操作。 –

回答

0

當我查看了您的查詢,我可以找出您所查詢的數據庫對象詮釋您的查詢。

如果你在數據庫中推送你的邏輯並在LINQ中得到結果,速度會更快。

+0

感謝您的回答,如果我使用連接或數據庫邏輯來完成加載時間,它並沒有什麼不同。但它使它具有更好的可讀性。 –

+0

有兩件事我可以考慮: 1)您可以更好地執行您的SQL查詢或做數據庫優化 2)沒有其他方法可以提高查詢執行時間 –