2012-11-23 48 views
0

我正在用c#訪問數據庫。現在我必須對從某些表中獲得的數據進行一些計算,並將其寫入其他現有表中。這在大多數情況下效果很好,但對於複雜的操作而言,這需要花費大量的時間。現在我想知道什麼是加速我的查詢並獲得結果的好實踐。這是我做的:c#:sql請求性能問題

  1. 我得到一個數據表,其中包含3個值(lom(唯一id),laktanfang,laktende),其中包含約700行。
  2. 對於此表中的每一行,我從另一個表中執行查詢。這導致另一個數據表包含2個值(lom(唯一的id),behanddatum)
  3. 現在我檢查如果行數據的值在laktanfang和laktende之間 - >是:將行添加到數據表通過我的函數返回 - >否:
  4. 走在最後,我不得不從我的數據表

這裏得到陽性結果的數量是我目前使用的代碼。我希望這不是太混亂。

public DataTable HoleAbgeschlosseneLaktationenMitDiagnosen(DateTime daAnfang, DateTime daEnde, string[] stDiagnosen = null) 
    {    
     DataTable dtRet = new DataTable(); 
     dtRet.Columns.Add("lom", typeof(string)); 
     dtRet.Columns.Add("laktanfang", typeof(DateTime)); 
     dtRet.Columns.Add("laktende", typeof(DateTime)); 

     DataTable dtAbgänge = HoleAbgängeVonEinzeltierZugang(daEnde, daAnfang); 
     //Abgeschlossene Laktationen für abgegegangene Tiere 
     foreach (DataRow dr in dtAbgänge.Rows) 
     { 
      if (dr != null) 
      { 
       DateTime daAbgangsdatum = dr.Field<DateTime>("abgangsdatum"); 
       string stLom = dr.Field<string>("lom"); 
       DataTable dtKalbungVorAbgang = HoleLetzteKalbungFuerTier(stLom, daAbgangsdatum); 

       if (dtKalbungVorAbgang.Rows.Count > 0 && !dtKalbungVorAbgang.Rows[0].IsNull("kalbedatum")) 
       { 
        DateTime daKalbedatum = (DateTime)dtKalbungVorAbgang.Rows[0]["kalbedatum"]; 
        int inLaktation = (int)dtKalbungVorAbgang.Rows[0]["laktation"]; 

        if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daKalbedatum, daAbgangsdatum) || stDiagnosen == null) 
        { 
         DataRow drLaktAbgang = dtRet.NewRow(); 
         drLaktAbgang["lom"] = stLom; 
         drLaktAbgang["laktanfang"] = daKalbedatum; 
         drLaktAbgang["laktende"] = daAbgangsdatum; 
         dtRet.Rows.Add(drLaktAbgang); 
        } 

        if (daKalbedatum >= daAnfang && inLaktation > 1) 
        { 
         DataTable dtVorherigeKalbung = HoleLetzteKalbungFuerTier(stLom, daKalbedatum.AddDays(-1)); 
         DateTime daVorhKalbung = (DateTime)dtVorherigeKalbung.Rows[0]["kalbedatum"]; 

         if (dtVorherigeKalbung.Rows.Count > 0 && !dtVorherigeKalbung.Rows[0].IsNull("kalbedatum")) 
         { 
          if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daKalbedatum, daAbgangsdatum) || stDiagnosen == null) 
          { 
           DataRow drLaktVorhKalbung = dtRet.NewRow(); 
           drLaktVorhKalbung["lom"] = stLom; 
           drLaktVorhKalbung["laktanfang"] = daVorhKalbung; 
           drLaktVorhKalbung["laktende"] = daKalbedatum; 
           dtRet.Rows.Add(drLaktVorhKalbung); 
          } 
         } 
        } 
       } 
      }     
     }   

     DataTable dtKalbungen = HoleKalbungenFürLebendTiere(daEnde, daAnfang); 
     //Abgeschlossene Laktationen für lebende Tiere 
     foreach (DataRow dr in dtKalbungen.Rows) 
     { 
      DateTime daKalbedatumLetzte = dr.Field<DateTime>("kalbedatum"); 
      string stLom = dr.Field<string>("lom"); 
      int inLaktation = dr.Field<int>("laktation"); 

      if (inLaktation > 1) 
      { 
       DataTable dtKalbungVorErster = HoleLetzteKalbungFuerTier(stLom, daKalbedatumLetzte.AddDays(-1)); 

       if (!dtKalbungVorErster.Rows[0].IsNull("kalbedatum")) 
       { 
        DateTime daKalbedatum = (DateTime)dtKalbungVorErster.Rows[0]["kalbedatum"]; 

        if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daKalbedatum, daKalbedatumLetzte) || stDiagnosen == null) 
        { 
         DataRow drLaktKalbung = dtRet.NewRow(); 
         drLaktKalbung["lom"] = stLom; 
         drLaktKalbung["laktanfang"] = daKalbedatum; 
         drLaktKalbung["laktende"] = daKalbedatumLetzte; 
         dtRet.Rows.Add(drLaktKalbung); 
        }      

        inLaktation = (int)dtKalbungVorErster.Rows[0]["laktation"]; 

        if (daKalbedatum >= daAnfang && inLaktation > 1) 
        { 
         DataTable dtVorherigeKalbung = HoleLetzteKalbungFuerTier(stLom, daKalbedatum.AddDays(-1)); 

         if (dtVorherigeKalbung.Rows.Count > 0 && !dtVorherigeKalbung.Rows[0].IsNull("kalbedatum")) 
         { 
          DateTime daVorhKalbung = (DateTime)dtVorherigeKalbung.Rows[0]["kalbedatum"]; 

          if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daVorhKalbung, daKalbedatum) || stDiagnosen == null) 
          { 
           DataRow drLaktVorhKalbung = dtRet.NewRow(); 
           drLaktVorhKalbung["lom"] = stLom; 
           drLaktVorhKalbung["laktanfang"] = daVorhKalbung; 
           drLaktVorhKalbung["laktende"] = daKalbedatum; 
           dtRet.Rows.Add(drLaktVorhKalbung); 
          }         
         } 
        } 
       } 
      }     
     } 

     return dtRet; 
    } 

    private bool PrüfeObDiagnoseInZeitraumAufgetreten(string stLom, string[] stDiagnosen, DateTime daAnfang, DateTime daEnde) 
    { 
     SqlCommand cmd = new SqlCommand(); 
     DataTable dtDiagnosenGefunden = new DataTable(); 

     cmd.CommandText = "SELECT diagnose " + 
          "FROM b_milch_hms_diagnose " + 
          "WHERE [email protected] AND behanddatum >= @datumanfang AND behanddatum <= @datumende"; 

     if (stDiagnosen != null) 
     { 
      int i = 0; 

      foreach (string st in stDiagnosen) 
      { 
       if (st != "") 
       { 
        if (i == 0) 
         cmd.CommandText += " AND diagnose LIKE @gesuchte_diagnose" + i; 
        else 
         cmd.CommandText += " OR diagnose LIKE @gesuchte_diagnose" + i; 
        cmd.Parameters.AddWithValue("@gesuchte_diagnose" + i, st + "%"); 
       } 

       i++; 
      } 
     } 

     cmd.Parameters.AddWithValue("@lom", stLom); 
     cmd.Parameters.AddWithValue("@datumanfang", daAnfang); 
     cmd.Parameters.AddWithValue("@datumende", daEnde); 

     dtDiagnosenGefunden = w_milch.FühreSqlAus(cmd); 
     if (dtDiagnosenGefunden.Rows.Count > 0 && !dtDiagnosenGefunden.Rows[0].IsNull("diagnose")) 
      return true; 

     return false; 

    } 

我希望你能幫助我改進這個功能,以提高工作效率或至少給我一些提示。

在此先感謝

回答

1

您已經創建了一個N+1問題。解決此問題的一種方法是更改​​HoleAbgängeVonEinzeltierZugang,使其joins位於您需要的數據表b_milch_hms_diagnose表中。

1

如果您使用的是.NET 4.0,還可以嘗試使用並行foreach並查看它對循環執行時間的影響。 (這是一個更一般的建議,你可以應用於很多例子)

_dtAbgänge.Rows.AsParallel().ForEach(dr=> 
               { 
                //do work 
               });