简体   繁体   English

如何提高数据库查询的性能?

[英]How can I improve the performance of my database queries?

I'm trying to simplify my code and make the search a little bit faster. 我正在尝试简化我的代码,并使搜索更快。 right now, depending, it's taking more than 15 Sec to fill my DataGridView. 现在,取决于我的DataGridView,它花费了15秒以上的时间。

I tried to join the 2 SQL sentence together, but failed. 我尝试将2个SQL语句连接在一起,但是失败了。 Also, I have no idea how to simplify the check of the Stock etc.. I tried to enter all the information to an array and then pass it as the DataGridView Source, rather than inserting line by line, but without effect for the search term. 另外,我也不知道如何简化对Stock等的检查。我试图将所有信息输入到数组中,然后将其作为DataGridView Source传递,而不是逐行插入,但对搜索项无效。

conn.Open();
MySqlTransaction trans = conn.BeginTransaction();

// Getting the Product
string sql = "SELECT id, typ, generation, configuration, revision"
           + " FROM product"
           + " WHERE typ = '" + comboBox_type.SelectedValue.ToString() + "'";

MySqlCommand cmd = new MySqlCommand(sql, conn, trans);
MySqlDataReader rdr = cmd.ExecuteReader();

List<KeyValuePair<int, string>> productList = new List<KeyValuePair<int, string>>();

while (rdr.Read())
{
   string produkt = rdr[1] + "-" + string.Format("{0:X2}", rdr[2]) + string.Format("{0:X2}", rdr[3]) + string.Format("{0:X2}", rdr[4]);
   int id = Convert.ToInt32(rdr[0]);               
   productList.Add(new KeyValuePair<int, string>(id, produkt));
}
rdr.Close();

foreach (KeyValuePair<int, string> productKeyValue in productList)
{
   sql = "SELECT COUNT(c.id)"
       + " FROM component_product ctp"
       + " JOIN component c ON ctp.id = c.id"
       + " WHERE ctp.product = " + productKeyValue.Key + " AND c.`status` = 3 AND ctp.outdated = 0";

   cmd = new MySqlCommand(sql, conn, trans);
   rdr = cmd.ExecuteReader();

   int stock = Convert.ToInt32(rdr[0]);

   rdr.Close();

   int stockDiff = stock, ordered = 0, reserved = 0;

   List<string> shortage = new List<string>();
   List<string> deliveries = new List<string>();
   List<string> planing = new List<string>();

   List<CommonHelper.DeliveryEntry> pm_dict = ch.GetProductMovement(productKeyValue.Key, conn, trans);

   foreach (CommonHelper.DeliveryEntry de in pm_dict)
   {
      int amount = de.Amount;
      string strDate = CommonHelper.MaterialText.DeliveryTimestamp(de.Timestamp);
      bool confirmed = (de.Confirmed == CommonHelper.DeliveryState.Confirmed);
      stockDiff += amount;
      if (amount >= 0)
      {
         ordered += amount;
         deliveries.Add(CommonHelper.MaterialText.Deliveries(confirmed, amount, stockDiff, strDate));
         planing.Add("+" + String.Format("{0,5}", amount) + " (" + strDate + ")                                    Stand: " + stockDiff.ToString());
      }
      else
      {
         reserved += amount;
         if (stockDiff < 0)
         {
            shortage.Add(CommonHelper.MaterialText.Shortages(amount, stockDiff, strDate));
         }

         planing.Add("                           " + String.Format("{0,5}", amount) + " (" + strDate + ")            Stand: " + stockDiff.ToString());
      }
   }

   string[] rowDate = new string[] {
   productKeyValue.Value,
   stock.ToString(),
   ordered.ToString(),
   reserved.ToString(),
   string.Join(" \r\n", shortage),
   string.Join(" \r\n", deliveries),
   string.Join("\r\n", planing)
   };

   dataGridView_inventorylist.Rows.Add(rowDate);
}

You probably should consolidate your two queries with a join operation. 您可能应该使用联接操作合并两个查询。 You're allowed to use subqueries as virtual tables. 您可以将子查询用作虚拟表。

This aggregating (GROUP BY) subquery returns one row for each c.id value. 此汇总(GROUP BY)子查询为每个c.id值返回一行。

                 SELECT COUNT(*) count, c.id
                   FROM component_product ctp
                   JOIN component c ON ctp.id = c.id
                  WHERE c.status = 3
                    AND ctp.outdated = 0
                  GROUP BY c.id 

Then, you join that to your other query. 然后,将其加入其他查询。 I used LEFT JOIN so the entire query will report items that have no counts. 我使用了LEFT JOIN因此整个查询将报告没有计数的项目。 A plain JOIN suppresses rows with no counts. 一个普通的JOIN禁止不计数的行。

Try something like this: 尝试这样的事情:

 SELECT count.count,
        p.id, p.typ, p.generation, p.configuration, p.revision
   FROM product p
   LEFT JOIN (
                 SELECT COUNT(*) count, c.id
                   FROM component_product ctp
                   JOIN component c ON ctp.id = c.id
                  WHERE c.status = 3
                    AND ctp.outdated = 0
                 GROUP BY c.id 
        ) count ON p.id = count.id
  WHERE typ = '" + comboBox_type.SelectedValue.ToString() + "'";

Then, populate your grid using the rows of just this one query. 然后,仅使用此查询的行填充网格。 Get rid of the productlist collection entirely, and get rid of the loop that runs a query for every element of that collection. 完全摆脱productlist集合,并摆脱对该集合的每个元素运行查询的循环。 In other words, retrieve what you need with just one query, rather than one plus one-for-every-product. 换句话说,只用一个查询就可以检索您需要的内容,而不是每个产品都要加上一个查询。 This should resolve your performance problem. 这样可以解决您的性能问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM