2017-05-05 191 views
4

直到現在,我沒有任何要求的功能,我做了我的程序,但後來我做了功能,花了很多時間。這是一年中的第五個月的開始,每天我的數據庫中都會有超過400個文檔(每個文檔平均有5-7個項目(表格中的5-7個新行ROBA))。 ,它需要越來越多的時間來計算一切,我需要加快它的速度SQL(火鳥)查詢太慢

現在大約需要60秒完成一切,所以我想知道是否有任何方法來加速這一點,要使用,要尋找什麼,這裏是我的功能有:

private void ucitajStanje() 
{ 
    DataTable dt1 = new DataTable(); 
    try 
    { 
     List<List_Int_Decimal> List_roba = new List<List_Int_Decimal>(); 

     using (FbConnection con = new FbConnection(connectionString_PrirucniMagacin)) 
     { 
      con.Open(); 
      using (FbCommand cmd = new FbCommand("SELECT ROBAID, KOLICINA FROM STAVKA WHERE VRDOK = 0 AND BRDOK = 1", con)) 
      { 
       FbDataReader dr = cmd.ExecuteReader(); 

       while (dr.Read()) 
       { 
        if (!(dr[0] is DBNull)) 
        { 
         List_roba.Add(new List_Int_Decimal { ROBAID = Convert.ToInt16(dr[0]), kolicina = Convert.ToDecimal(dr[1]) }); 
        } 
       } 
      } 
      con.Close(); 
     } 

     using (FbConnection con = new FbConnection(connectionString_Baza)) 
     { 
      con.Open(); 

      //Selektuje stanje u magacinu iz komercijalnog 
      using (FbDataAdapter da = new FbDataAdapter("SELECT ROBA.ROBAID, ROBA.KATBR, ROBA.NAZIV, ROBAUMAGACINU.STANJE AS STANJE_KOMERCIJALNO FROM ROBAUMAGACINU INNER JOIN ROBA ON ROBAUMAGACINU.ROBAID = ROBA.ROBAID WHERE MAGACINID = 12 AND VRSTA = 1", con)) 
      { 
       da.Fill(dt1); 
      } 

      //FIRST SLOW QUERY 


      //izracunava stanje kartice robe bez pocetnog stanja iz komercijalnog gde se dodaje na stanje 
      using (FbCommand cmd = new FbCommand("SELECT ROBAID, SUM(KOLICINA) FROM STAVKA WHERE VRDOK = 16 AND ROBAID = @Robaid AND MAGACINID = 12 OR VRDOK = 18 AND ROBAID = @Robaid AND MAGACINID = 12 OR VRDOK = 22 AND ROBAID = @Robaid AND MAGACINID = 12 GROUP BY ROBAID", con)) 
       { 
        cmd.Parameters.Add("@Robaid", FbDbType.Integer); 
        foreach (var robaid in List_roba) 
       { 
        cmd.Parameters["@Robaid"].Value = robaid.ROBAID; 

        FbDataReader dr = cmd.ExecuteReader(); 
        while (dr.Read()) 
        { 
         if (!(dr[0] is DBNull)) 
         { 
          int trenutnaRobaId = Convert.ToInt16(dr[0]); 

          var roba = List_roba.Where(r => r.ROBAID == trenutnaRobaId).FirstOrDefault(); 
          if (roba != null) 
          { roba.kolicina = roba.kolicina + Convert.ToDecimal(dr[1]); } 
         } 
        } 
        dr.Close(); 
       }      
      } 

      //SECOND SLOW QUERY 

      //izracunava stanje kartice robe bez pocetnog stanja iz komercijalnog gde se oduzima sa stanja 
      using (FbCommand cmd = new FbCommand("SELECT ROBAID, SUM(KOLICINA) FROM STAVKA WHERE VRDOK = 15 AND ROBAID = @Robaid AND MAGACINID = 12 OR VRDOK = 17 AND ROBAID = @Robaid AND MAGACINID = 12 OR VRDOK = 19 AND ROBAID = @Robaid AND MAGACINID = 12 OR VRDOK = 34 AND ROBAID = @Robaid AND MAGACINID = 12 GROUP BY ROBAID", con)) 
      { 
       cmd.Parameters.Add("@Robaid", FbDbType.Integer); 
       foreach (var robaid in List_roba) 
       { 
        cmd.Parameters["@Robaid"].Value = robaid.ROBAID; 

        FbDataReader dr = cmd.ExecuteReader(); 
        while (dr.Read()) 
        { 
         if (!(dr[0] is DBNull)) 
         { 
          int trenutnaRobaId = Convert.ToInt16(dr[0]); 
          var roba = List_roba.Where(r => r.ROBAID == trenutnaRobaId).FirstOrDefault(); 
          if (roba != null) 
          { roba.kolicina = roba.kolicina - Convert.ToDecimal(dr[1]); } 
         } 
        } 
        dr.Close(); 
       }      
      } 
      con.Close(); 
     } 
     DataTable dt2 = StaticFunctions.ToDataTable(List_roba); 

     var dt = new[] { dt1, dt2 }; 
     DataTable mergedDT = StaticFunctions.MergeAll(dt, "ROBAID"); 

     dataGridView1.DataSource = mergedDT; 

     dataGridView1.Columns["ROBAID"].Visible = false; 
     dataGridView1.Columns["KATBR"].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; 
     dataGridView1.Columns["NAZIV"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; 
     dataGridView1.Columns["STANJE_KOMERCIJALNO"].Visible = false; 
     dataGridView1.Columns["robaid"].Visible = false; 
    } 
    catch(Exception ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 
} 
+0

該表中有多少條記錄?您可以在ROBAID上創建索引。 – wannadream

+0

這是非常小的數額。我不使用FireBird,也不確定其性能。如果可以,請在ROBAID上添加索引,然後重試。 – wannadream

+0

表'ROBA'包含4890行,在'stavka'表中有312978 –

回答

4

儘量避免打電話查詢在循環(即一次又一次執行SQL ):

//FIRST SLOW QUERY 

    // Loop! 
    foreach (var robaid in List_roba) { 
    ... 
    // Antipattern: Many a time query calling 
    FbDataReader dr = cmd.ExecuteReader(); 
    ... 
    } 

相反,執行查詢只是一次,在一個去

//FIRST SLOW QUERY (Hope, much faster now) 

//DONE: Keep SQL readable 
string sql = 
    @"SELECT ROBAID, 
      SUM(KOLICINA) 
     FROM STAVKA 
     WHERE MAGACINID = 12 AND 
      VRDOK IN (16, 18, 22) 
    GROUP BY ROBAID"; 

using (FbCommand cmd = new FbCommand(sql, con)) { 
    using (FbDataReader dr = cmd.ExecuteReader()) { 
    while (dr.Read()) { 
     if (dr.IsDBNull(0)) // <- Is it really possible for Id to be null? 
     continue; 

     int trenutnaRobaId = Convert.ToInt32(dr[0]); 

     //TODO: you may want to turn List_roba into Dictionary_roba: 
     // if (Dictionary_roba.TryGeValue(trenutnaRobaId, out roba)) 
     // roba.kolicina = roba.kolicina + Convert.ToDecimal(dr[1]); 
     var roba = List_roba 
     .Where(r => r.ROBAID == trenutnaRobaId) 
     .FirstOrDefault(); 

     if (roba != null) 
     roba.kolicina = roba.kolicina + Convert.ToDecimal(dr[1]); 
    } 
    } 
} 

編輯:可以進一步提高性能,如果你把List_roba字典 (或者至少創建一個臨時字典),例如

// In general case, if ROBAID can have duplicates 
var Dictionary_roba = List_roba 
    .GroupBy(item => item.ROBAID) 
    .ToDictionary(chunk => chunk.Key, 
       chunk => chunk.First()); 

// If ROBAID is unique: 
//var Dictionary_roba = List_roba 
// .ToDictionary(item => item.ROBAID, item => item); 

... 

using (FbCommand cmd = new FbCommand(sql, con)) { 
    using (FbDataReader dr = cmd.ExecuteReader()) { 
    while (dr.Read()) { 
     if (dr.IsDBNull(0)) // <- Is it really possible for Id to be null? 
     continue; 

     int trenutnaRobaId = Convert.ToInt32(dr[0]); 

     // C# 7.0 Syntax - out var; 
     // if you don't have C# 7.0 you have to declare "roba" variable 
     if (Dictionary_roba.TryGeValue(trenutnaRobaId, out var roba)) 
     roba.kolicina = roba.kolicina + Convert.ToDecimal(dr[1]); 
    } 
    } 
} 
+0

嗯,我得到了一切,希望我需要選擇條件'cmd.Parameters [「@ Robaid」] .Value = robaid.ROBAID;'。如果我使用它,我在哪裏添加它? –

+0

@Aleksa Ristic:我建議*在一個查詢中結合*所有的'ROBAID'(這就是爲什麼我已經消除了@ Robaid參數)。然後我們掃描光標,如果我們在'List_roba'中有相應的項目,我們會更新它 –

+0

好的。它速度要快得多(現在需要2秒),但對於最後一個問題,字典和列表在性能方面有什麼區別,以及我在TODO下的那條評論行得到了什麼? –