从文本文件加载数据然后将其存储到数据库中的最快方法

     2023-05-07     126

关键词:

【中文标题】从文本文件加载数据然后将其存储到数据库中的最快方法【英文标题】:Fastest way to load data from text file then store it into database 【发布时间】:2011-02-11 13:56:22 【问题描述】:

我有问题。

我正在开发一个项目,但我被困在这部分:

我想从文本文件加载数据并将其存储到数据库访问 事情是每个文本文件中的数据大约 12.000 行数据 每个文本文件大约需要 10 分钟来处理它..

注意:在存储数据之前,我将每一行数据与文本文件分开并将其放入字符串中,然后检查数据是否已经在数据库中。 如果在数据库内部我更新它。如果没有,那么我使用插入语句..

我正在使用 C# 来开发这个程序? 有没有最快的方法来加载和存储这些数据?

更新:

这是我的代码,希望它有助于理解我的问题:

    using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Data.OleDb;

namespace DAF

    public partial class FrontForm : Form
    
        public Boolean status;

        public FrontForm()
        
            InitializeComponent();

            //define location of the database
            string connection = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\PC\Desktop\Graduation Project\Research\DAF\Data\DAFLogisticDepartment.mdb";

            //define location of the text file data
            DirectoryInfo di = new DirectoryInfo(@"C:\Users\PC\Desktop\Graduation Project\Research\DAF\Data\");
            FileInfo[] fiarr = di.GetFiles("*.txt");


            //define connection to database
            OleDbConnection con = new OleDbConnection(connection);
            String query;
            OleDbDataReader rdr = null;

            con.Open();
            //get all table from database
            OleDbCommand cmd = con.CreateCommand();
            DataTable dt = con.GetSchema("tables");
            DataRow[] dttable = dt.Select();
            con.Close();

            //read each new textfile inside the folder
            foreach (FileInfo fri in fiarr)
            
                StreamReader sr = new StreamReader(fri.FullName, System.Text.Encoding.Default);
                String line;
                String tabledbs, dbsName;

                while ((line = sr.ReadLine()) != null)
                
                    String VRSD, locationID, truckID, yearIn, yearOut, weekIn, weekOut, dayIn, dayOut, timeIn, timeOut, route;
                    int plantID;

                    //process each line of data and put into each variable
                    VRSD = line.Substring(0, 4).Trim();
                    plantID = Convert.ToInt32(line.Substring(4, 1).Trim());
                    locationID = line.Substring(5, 4).Trim();
                    truckID = line.Substring(24, 5).Trim();
                    yearIn = line.Substring(32, 4).Trim();
                    weekIn = line.Substring(36, 2).Trim();
                    dayIn = line.Substring(38, 1).Trim();
                    timeIn = line.Substring(39, 8).Trim();
                    yearOut = line.Substring(47, 4).Trim();
                    weekOut = line.Substring(51, 2).Trim();
                    dayOut = line.Substring(53, 1).Trim();
                    timeOut = line.Substring(54, 8).Trim();
                    route = line.Substring(64, 2).Trim();

                    //make database name
                    dbsName = plantID + locationID;

                    con.Open();
                    //check if the table exist in database
                    for (int i = 0; i < dttable.Length - 9; i++)
                    
                        tabledbs = dttable[i]["TABLE_NAME"].ToString();
                        ArrayList indexlist = new ArrayList();

                        if (tabledbs == dbsName)
                        
                            //if the table exist, status = true
                            status = true;
                            break;
                        
                    
                    con.Close();

                    con.Open();

                    if (status == true)
                    

                        try
                                
                            //if the data not in the system, insert statement
                            query = @"insert into " + plantID + locationID + " values('" + VRSD.ToString() + "'," + plantID + ",'" + locationID + "','" + truckID + "','" + yearIn + "','" + weekIn + "','" + dayIn + "','" + timeIn + "','" + yearOut + "','" + weekOut + "','" + dayOut + "','" + timeOut + "')";
                            cmd = new OleDbCommand(query, con);
                            rdr = cmd.ExecuteReader();
                            con.Close();
                        
                        catch
                        
                            //if the data in the system, update statement
                            query = @"update " + dbsName + " set YearIn='" + yearIn + "', YearOut='" + yearOut + "', WeekIn='" + weekIn + "', WeekOut='" + weekOut + "', DayIn='" + dayIn + "', DayOut='" + dayOut + "', TimeIn='" + timeIn + "', TimeOut='" + timeOut + "' where LocationID='" + locationID + "' and PlantID=" + plantID + "";
                            cmd = new OleDbCommand(query, con);
                            rdr = cmd.ExecuteReader();
                            con.Close();
                        

                    
                    else
                    
                        //create new table
                        string attribute = "VRSD String,PlantID Integer, LocationID String, TruckID String," +
                                            "YearIn String, WeekIn String, DayIn String, TimeIn String," +
                                            "YearOut String, WeekOut String, DayOut String, TimeOut String";

                        query = @"CREATE TABLE " + plantID + locationID + "(" + attribute + ")";
                        cmd = new OleDbCommand(query, con);
                        cmd.ExecuteNonQuery();

                        //insert the data
                        query = @"insert into " + plantID + locationID + " values('" + VRSD.ToString() + "'," + plantID + ",'" + locationID + "','" + truckID + "','" + yearIn + "','" + weekIn + "','" + dayIn + "','" + timeIn + "','" + yearOut + "','" + weekOut + "','" + dayOut + "','" + timeOut + "')";
                        cmd = new OleDbCommand(query, con);
                        rdr = cmd.ExecuteReader();
                        con.Close();
                    

                    status = false;
                
                sr.Close();

                //after the text file load into database, the text file moved to history folder
                MessageBox.Show(fri.FullName.ToString(), "File Manager", MessageBoxButtons.OK);
                fri.MoveTo(@"C:\Users\PC\Desktop\Graduation Project\Research\DAF\Data\History\" + fri.Name.ToString() + ".txt");
            
        

        private void button2_Click(object sender, EventArgs e)
        
            StandardReport sr = new StandardReport();
            sr.Show();
        

        private void FrontForm_Load(object sender, EventArgs e)
        

        
    

【问题讨论】:

10分钟有这么糟糕吗?您需要执行多少文件以及多久执行一次?你能并行化你正在做的任务吗?您是否对此进行了概要分析以查看时间被占用的地方? 事情是这样的:我的老板每周要加载 6 个文本文件。每个文本文件包含超过 12.000 行数据。每次我的老板运行程序时,程序都会加载每个文本文件,检查数据库的每一行数据是否存在。如果存在,它会更新它,如果不存在,它会插入到 dbs.. 每个文本文件大约需要 10 分钟。如果有 6 个文本文件,则需要 1 小时.. 我添加了我的代码.. 希望你能帮助我.. :) @Yohanes 还有一个问题,您希望插入的文本文件的格式是什么?少量数据样本会有所帮助。 您有 12k 行,x6...您希望其中大部分是新行还是现有行? 【参考方案1】:

这里最大的时间杀手将是您正在使用的数据库连接的绝对数量 - 尝试构建一个内存中的命令列表(与从文件中读取数据相比,每个对象几乎不需要时间),然后一次你已经建立了你的列表,通过一个连接执行它们。打开每个连接都需要时间,而且您这样做的次数远远超过需要的次数。编辑 - 实际上注意到您每个文件每行打开/关闭 2 个连接!


目前(为了清楚起见伪代码):

For each file (x6)

   Load file from stream

   For each line in file (x12k)

     Read data from line

     Open database connection (happens 72k times)
     Check whether table exists
     Close connection

     Open connection (x72k)
     Try to insert record
     If inserting fails, update existing record
     Close connection

     Next line

   Close filestream

Next file

建议:(并强烈建议您考虑动态添加表的含义,这通常不是一个好的解决方案,但如果强加给您,您可能别无选择)

Create an in-memory list of commands 
  (or list of custom objects with property for each command type, create 
  table,insert,update)    

For each file (x6)

   Load file from stream

   For each line in file (x12k)

      Read data from line (all happens 72k times, but no external connections per line)

      Write your create table command
      Write your insert command
      Write your update command
      Add to relevent command lists

   Next Line

   Close filestream

Next File

Open database connection (x1)

For each command in your list
   Apply suitable logic as to whether command needs to execute
   Execute command if applicable
Next command

Close database connection

【讨论】:

所以你建议,我将所有数据都临时存储,然后一次性将它们全部放入数据库中?我仍然很困惑如何在一个连接中将所有数据放入/插入数据库中。你能给我一些例子吗?谢谢!! :) 添加了一个粗略的例子来演示【参考方案2】:

为什么不尝试创建和使用 SSIS 包?它非常擅长这类事情,具有出色的工具,并且从代码中使用起来非常简单

http://msdn.microsoft.com/en-us/library/ms141026.aspx

http://blogs.msdn.com/b/michen/archive/2007/03/22/running-ssis-package-programmatically.aspx

【讨论】:

这对 Text 和 MS Access 有帮助吗?安装 SQL Server 对于这项任务来说似乎有点过头了。 我不知道,如果您正在使用包含 12k 多个条目的表,那么您很快就会超越 MS Access。值得认真看,留有余地更好? @Remou,是的,SSIS 可以使用多种类型的数据源和目标提供程序,包括平面文件(文本)和 JET/ACE(访问) 我知道 SSIS 可以处理很多东西,但它对于一个小错误来说是一把非常大的锤子。 请注意,包含数据的目录包含在一个名为“毕业项目”的文件夹中,该文件夹与一个列(字段)PlantID 组合在一起,看起来非常异常的数据库设计表明了一个很好的交易。例如,整个事情都可以在 VBA 中轻松完成,而且 SQL Server 可能会涉及到大学 IT 的申请,根据大学的不同,可能需要数周的时间来处理。【参考方案3】:

您可以使用 Jet 驱动程序为文本使用查询插入不匹配的记录。

SELECT a.* INTO NewTable FROM 
(SELECT * From [Text;DSN=Import Link Specification;FMT=Delimited;HDR=NO;IMEX=2;CharacterSet=850;DATABASE=C:\Docs].[Import.txt]) As A
LEFT JOIN OldTable ON a.Key=OldTable.Key
WHERE a.Key Is Null

编辑

我想知道为什么您没有包含所有植物和位置的主表。然后,您可以将所有文件插入到临时表中,并相应地从临时表中追加或更新。

foreach (FileInfo fri in fiarr)
    
    string s = "[Text;DSN=Test Spec;"
         + "FMT=Fixed;HDR=Yes;IMEX=2;CharacterSet=850;DATABASE=" 
         + fri.DirectoryName + "].["
         + fri.Name + "]";

    query = "INSERT INTO Temp SELECT * FROM " + s;

    cmd.ExecuteNonQuery();
    

您似乎使用的是固定长度格式,因此DSN=Test Spec 是通过以固定宽度格式导出文件然后使用“高级”按钮保存该规范来创建的 Access 规范。

【讨论】:

我想是的。一般的想法是您只需对连接执行查询。我会看看能不能用你的代码做点什么。 顺便说一句,看到它是 Access,你甚至不需要 C#,这可以在 VBA 中作为一堆查询非常简单地运行。【参考方案4】:

这里的一个问题可能是您使用 SINGLE SQL EXECUTE 语句逐行插入每条记录。

另一种解决方案是:

    将文本文件读入字符串缓冲区(20.000 行) 创建一个 DataTable 对象 在循环中,将每一行插入 DataTable 对象。 最后,使用 DataAdapter,将 DataTable 写回数据库。

【讨论】:

从 MySQL 将数值数据加载到 python/pandas/numpy 数组中的最快方法

】从MySQL将数值数据加载到python/pandas/numpy数组中的最快方法【英文标题】:Fastestwaytoloadnumericdataintopython/pandas/numpyarrayfromMySQL【发布时间】:2014-04-0602:25:55【问题描述】:我想从MySQL表中读取一些数字(双精度,即float64)数据。... 查看详情

从文本文件中读取数据并将其分配给数据框的最快方法是啥?

】从文本文件中读取数据并将其分配给数据框的最快方法是啥?【英文标题】:What\'sthefastestwayofreadingdatafromatextfileandallocatingittoadataframe?从文本文件中读取数据并将其分配给数据框的最快方法是什么?【发布时间】:2017-08-0708:31:... 查看详情

将巨大的 .Rdata 文件(R 数据帧)加载到 SQL Server 中的最快方法是啥?

】将巨大的.Rdata文件(R数据帧)加载到SQLServer中的最快方法是啥?【英文标题】:Whatisthefastestwaytoloadhuge.Rdatafiles(Rdataframes)intoSQLServer?将巨大的.Rdata文件(R数据帧)加载到SQLServer中的最快方法是什么?【发布时间】:2017-06-0900:51... 查看详情

将图像从 SD 卡加载到视图中的最快方法是啥

...方案的性能不满意。我的应用程序创建小缩略图(大约1k文件大小/64x64px)并将它们存储到SD卡上。将这些图像从SD卡加载到视图中会花费一些 查看详情

将文本文件中的数据提取到结构中

】将文本文件中的数据提取到结构中【英文标题】:Pulldatafromtextfileintoastruct【发布时间】:2013-10-1207:39:23【问题描述】:我目前在尝试使用结构从文本文件中提取数据然后将其存储到向量中时遇到问题。但无论我做什么,除非... 查看详情

将大型数据集加载到 R 中的最快方法和最快格式是啥 [重复]

】将大型数据集加载到R中的最快方法和最快格式是啥[重复]【英文标题】:WhatisthefastestwayandfastestformatforloadinglargedatasetsintoR[duplicate]将大型数据集加载到R中的最快方法和最快格式是什么[重复]【发布时间】:2015-10-3111:01:21【问题... 查看详情

从 API 获取数据,然后将其发送到 EJS 文件

】从API获取数据,然后将其发送到EJS文件【英文标题】:FetchingdatafromanAPIthensendingittoanEJSfile【发布时间】:2019-12-3115:45:02【问题描述】:我正在尝试将使用fetch-api提取的json对象发送到EJS文件,该文件在有人访问网站时加载。问... 查看详情

oracle 将文本文件中的数据加载到表中

】oracle将文本文件中的数据加载到表中【英文标题】:Loadingdatafromatextfiletoatableinoracle【发布时间】:2010-09-2010:30:41【问题描述】:我有2个问题。除了使用SQL加载器之外,还有其他方法可以将数据从.txt文件加载到Oracle中的表吗?... 查看详情

归档数据,然后将其加载到 viewdidload

...信息,然后在下一次加载时恢复它们。无法弄清楚为什么文本似乎没有被保存-所以下次我在模拟器中加载应用程序时显然不会加载 查看详情

将数据连续写入文件的 C 最快方法 [关闭]

】将数据连续写入文件的C最快方法[关闭]【英文标题】:Cfastestwaytocontinouslywritedatatofile[closed]【发布时间】:2020-05-0114:01:58【问题描述】:我有一个由一些数据包统计信息组成的字符串,例如数据包长度等。我想将其存储到csv文... 查看详情

使用 Azure 数据工厂从 blob 存储中仅读取一个文件并加载到数据库中

】使用Azure数据工厂从blob存储中仅读取一个文件并加载到数据库中【英文标题】:UsingAzureDataFactorytoreadonlyonefilefromblobstorageandloadintoaDB【发布时间】:2020-09-0807:35:18【问题描述】:我只想从blob存储容器中读取一个文件,并在文件... 查看详情

通过消除重复将数据从文本文件加载到mysql数据库

】通过消除重复将数据从文本文件加载到mysql数据库【英文标题】:Loadingdatafromtextfiletomysqldatabasebyeliminatingduplicates【发布时间】:2011-12-1405:56:49【问题描述】:我想将数据从文本文件加载到数据库,如果数据已经存在,我需要在... 查看详情

从外部 .json 文件加载默认数据并存储到 MongoDB

】从外部.json文件加载默认数据并存储到MongoDB【英文标题】:Loaddefaultdatafromexternal.json-fileandstoreintoMongoDB【发布时间】:2021-10-2802:13:39【问题描述】:如果设置了环境变量TEST,我想从外部test_data.json文件加载JSON数据。我能够加载... 查看详情

平面文件到 SSIS 中的 Netezza 加载

...述】:我可以通过SSIS将管道分隔的平面文件加载到Netezza数据库的最快方法吗?目前加载60MB数据需要一分钟。【问题讨论】:您能告诉我们更多关于您的SSIS工作的信息吗?您是否使用NetezzaOLE-DB驱动程序作为目标?【参考方案1】... 查看详情

将数据加载到 Cassandra 列族的最快方法是啥

...描述】:我创建了一个Cassandra列族,我需要为此列族从CSV文件加载数据。csv文件有一个15Gb的卷。我正在使用CQL\'COPYFROM\'命令,但这 查看详情

设置项目:用户输入一个值,然后将其存储在文本文件或数据库中

...设置项目:用户输入一个值,然后将其存储在文本文件或数据库中【英文标题】:SetupProject:userentersavaluethenstoreitinatextfileordatabase【发布时间】:2016-02-2702:53:11【问题描述】:正如标题所说,我该怎么做?我在google上搜索了一些tu... 查看详情

jvm类加载机制

概述虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。类的加载指的是将类的.class文件中的二进制数据读入到内存中... 查看详情

将数据从 AWS Redshift 导入到 BI Tool 的最快方法

...万行。我正在办公室检索本地数据。我正在尝试将该数据加载到BI工具中的内存中。使用JDBC连接导入该数据需要很长时间(12分钟 查看详情