2012-11-23 120 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 
               });