Как я могу улучшить производительность запросов к моей базе данных? - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь упростить мой код и сделать поиск немного быстрее.прямо сейчас, в зависимости от того, что заполнение моего DataGridView занимает более 15 секунд.

Я попытался объединить предложение 2 SQL вместе, но безуспешно.Кроме того, я понятия не имею, как упростить проверку запасов и т. Д. Я попытался ввести всю информацию в массив, а затем передать ее как источник DataGridView, а не вставлять построчно, но без эффекта для условия поиска.

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);
}

1 Ответ

0 голосов
/ 28 февраля 2019

Вам, вероятно, следует объединить два запроса с помощью операции соединения.Вам разрешено использовать подзапросы в качестве виртуальных таблиц.

Этот агрегирующий (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 

Затем вы присоединяете это к другому запросу.Я использовал LEFT JOIN, поэтому весь запрос будет сообщать об элементах, которые не учитываются.Простой JOIN подавляет строки без подсчета.

Попробуйте что-то вроде этого:

 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() + "'";

Затем заполните таблицу, используя строки только этого одного запроса.Полностью избавьтесь от коллекции productlist и избавьтесь от цикла, который выполняет запрос для каждого элемента этой коллекции.Другими словами, получите то, что вам нужно, всего одним запросом, а не одним плюс один для каждого продукта.Это должно решить вашу проблему с производительностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...