Экспорт большого количества каналов в SQL

Стартовая страница Форумы Разработка и интеграция Экспорт большого количества каналов в SQL

  • В этой теме 1 ответ, 2 участника, последнее обновление 9 лет назад сделано Mikhail.
Просмотр 2 сообщений - с 1 по 2 (из 2 всего)
  • Автор
    Записи
  • #7146
    Kazam
    Участник

    Всем привет.
    При увеличении количества входных каналов, прямое подключение к серверу Rapid Scada для получения значений, перестает быть эффективным.
    Итого дано: около 4000 входных каналов. 600 каналов управления.
    Задача: положить значения и свойства каналов в SQL.

    Что придумал:

    В методе OnServerStart: получаем таблицы КП, Unit, ParamTable

    В методе OnCurDataCalculated: получаем текущий срез и пишем его в DataTable, который в свою очередь, через расширение:

    public static class DataTableExtensions
        {
            public static void WriteToCsvFile(this dataTable, string filePath)
            {
                StringBuilder fileContent = new StringBuilder();
    
                foreach (var col in dataTable.Columns)
                {
                    fileContent.Append(col.ToString() + ";");
                }
    
                fileContent.Replace(";", System.Environment.NewLine, fileContent.Length - 1, 1);
    
                foreach (DataRow dr in dataTable.Rows)
                {
    
                    foreach (var column in dr.ItemArray)
                    {
                        if (column.GetType() == typeof(DateTime))
                        {
                            fileContent.Append("" + String.Format("{0:yyyy-MM-dd HH:mm:ss.000}", column) + ";");
                        }
                        else
                        {
                            if (String.IsNullOrEmpty(column.ToString()))
                            {
                                fileContent.Append(" ;");
                            }
                            else
                            {
                                fileContent.Append("" + string.Format("{0:F12}", column).Replace(',', '.') + ";");
                            }
    
                        }
    
                    }
    
                    fileContent.Replace(";", System.Environment.NewLine, fileContent.Length - 1, 1);
                }
    
                System.IO.File.WriteAllText(filePath, fileContent.ToString());
    
            }
        }

    Пишем в CSV файл.

    Ну а далее с CSV файлом делаем, что хотим.
    Например пишем в PostgreSQL.
    вот что получилось:

    public override void OnCurDataCalculated(int[] cnlNums, SrezTableLight.Srez curSrez)
            {
                // the method executes after current data calculation (approximately every 100 ms)
                // метод выполняется после вычисления дорасчётных каналов текущего среза (примерно каждые 100 мс)
                dt.Rows.Clear();
                int cnlCnt = curSrez.CnlNums.Length;
                for (int i = 0; i < cnlCnt; i++)
                {
                    DataRow dr = dt.NewRow();
                    dr["cnlnum"] = Convert.ToInt32(curSrez.CnlNums[i]);
                    dr["value"] = curSrez.CnlData[i].Val;
                    dr["datetime"] = DateTime.Now;
                    dt.Rows.Add(dr);
                }
    
                dt.WriteToCsvFile(day_filename);
    
                using (NpgsqlConnection conn_table = new NpgsqlConnection(conn_param))
                {
                    conn_table.Open();
                    NpgsqlCommand comm = new NpgsqlCommand(sql, conn_table);
    
                    var result = comm.ExecuteNonQuery();
                    conn_table.Dispose();
                }
            }

    Отдельно о SQL запросе: string sql = @»CREATE TEMP TABLE incnls_temp (cnlnum DOUBLE PRECISION, datetime TIMESTAMP, value DOUBLE PRECISION);
    copy incnls_temp (cnlnum, datetime, value) FROM ‘c:\\scada\\current\\current.csv’ DELIMITER ‘;’ CSV HEADER;
    UPDATE incnls SET value = incnls_temp.value, datetime = incnls_temp.datetime FROM incnls_temp WHERE incnls.cnlnum = incnls_temp.cnlnum;
    DROP TABLE incnls_temp
    «;
    Создаем копию таблицы входных каналов в SQL, пишем в нее данные, далее делаем Update в основной таблице и дропаем временную.

    Что это дает: при пакетной обработке каналов получаем существенное увеличение производительности, в отличие от классического подхода InsertCommand.

    #7151
    Mikhail
    Модератор

    Спасибо. Если замените DataTable на другие структуры, будет ещё быстрее, т.к. DataTable — сложный и медленный класс.

Просмотр 2 сообщений - с 1 по 2 (из 2 всего)
  • Для ответа в этой теме необходимо авторизоваться.