代码之家  ›  专栏  ›  技术社区  ›  dummzeuch Stijn Sanders

如何将800000条记录插入MS Access表?

  •  5
  • dummzeuch Stijn Sanders  · 技术社区  · 17 年前

    我需要在MS Access表中插入800000条记录。我正在使用Delphi 2007和 TAdoXxxx 组件。该表包含一些整数字段、一个浮点数字段和一个只有一个字符的文本字段。其中一个整数字段上有一个主键(不是自动数),另一个整数和浮点数字段上有两个索引。

    使用插入数据 AdoTable.AppendRecord(...) 取>10分钟是不可接受的,因为每次用户开始在程序中使用新数据库时都会这样做。我无法预填充表,因为数据来自另一个数据库(无法通过访问 ADO ).

    通过将记录写入以制表符分隔的文本文件并使用 tAdoCommand 要执行的对象

    insert into table (...) select * from [filename.txt] in "c:\somedir" "Text;HDR=Yes"
    

    但我不喜欢这样的开销。

    我想一定有更好的办法。

    编辑:

    一些附加信息:

    • 选择MS Access是因为它不需要在目标计算机上进行任何额外安装,并且整个数据库包含在一个可以轻松复制的文件中。
    • 这是一个单用户应用程序。
    • 数据将只插入一次,在数据库的生命周期内不会更改。但是,该表包含一个附加字段,用作标记,表示另一个数据库中的相应记录已被用户处理。
    • 一分钟 可以接受(最多3分钟也可以),我的解决方案是可行的,但对我来说似乎太复杂了,所以我认为应该有一种更简单的方法来做到这一点。
    • 一旦插入数据,表的性能就相当好。
    • 当我开始规划/实现使用Access数据库的程序功能时,不需要该表。后来,当客户要求使用另一个功能时,才有必要使用它。(不总是这样吗?)

    编辑:

    从我到目前为止得到的所有答案来看,我似乎已经找到了将这么多数据插入Access表的最快方法。谢谢大家,我很感激你的帮助。

    16 回复  |  直到 10 年前
        1
  •  3
  •   Fabricio Araujo    15 年前

    既然你说过在数据库的生命周期内,80万条记录的数据不会改变,我建议以表的形式链接到文本文件,并完全跳过插入。

    如果你坚持把它拉进数据库,那么1分钟内有80万条记录超过13000条/秒。我不认为你会在MS Access中击败它。

    如果你想让它对用户的响应更快,那么你可能想考虑加载一些最小的数据集,并设置一个后台线程在它们工作时加载其余的数据。

        2
  •  9
  •   JosephStyons    17 年前

    没有索引会更快。你能在导入后添加它们吗?

    在这个话题中,有一些建议可能会引起人们的兴趣 Slow MSAccess disk writing

        3
  •  5
  •   Community Mohan Dere    8 年前

    跳过文本文件并使用ODBC或OLEDB直接从源表导入怎么样?这意味着更改FROM子句,以使用源表名和适当的连接字符串作为FROM子句的IN“”部分。

    编辑: 实际上,我看到你说原始格式是xBase,所以应该可以使用Jet中的xBase ISAM,而不需要ODBC或OLEDB。看起来像这样:

    INSERT INTO table (...) 
    SELECT * 
    FROM tablename IN 'c:\somedir\'[dBase 5.0;HDR=NO;IMEX=2;];
    

    您可能需要对此进行调整——我刚刚抓取了指向DBF文件的链接表的连接字符串,因此参数可能略有不同。

        4
  •  4
  •   Marc Gravell    16 年前

    你的基于文本的解决方案似乎是最快的,但如果你能得到一个大小接近末尾的预分配MS Access,你就可以更快地得到它。您可以通过填充一个典型的用户数据库、关闭应用程序(以便刷新缓冲区)并手动删除该大表的所有记录来实现这一点,但不要缩小/压缩它。

    因此,使用该文件开始真正的填充——Access不会请求任何(或很少)额外的磁盘空间。不记得MS Access是否有自动化的方法,但它可以提供很多帮助。..

        5
  •  3
  •   pfunk    17 年前

    另一种安排怎么样。..

    是否可以选择复制一个现有的Access数据库文件,该文件包含您需要的此表,然后删除其中除此大表之外的所有其他数据(不知道Access是否与SQL server中的“截断表”等效)?

        6
  •  3
  •   Mohammed Nasman    17 年前

    我会用另一个数据库替换MS Access,对于你的情况,我看到了 Sqlite 是最好的选择,它不需要在客户端机器上进行任何安装,它是一个非常快速的数据库,也是最好的嵌入式数据库解决方案之一。

    您可以在Delphi中以两种方式使用它:

    1. 您可以从以下网址下载数据库引擎Dll 亚硫酸矿 网站,并使用免费的Delphi组件访问它,就像 Delphi SQLite components SQLite4Delphi

    2. 使用 DISQLite3 它们内置了引擎,你不必在应用程序中分发dll,它们有一个免费版本;-)

    如果您仍然需要使用MS Access,请尝试直接将TAdoCommand与SQL Insert语句一起使用,而不是使用TADOTable,这应该比使用TADOTtable更快。附录;

        7
  •  2
  •   Community Mohan Dere    8 年前

    正如有人提到的,您不会在不到一分钟的时间内导入80万条记录;那是 真正地 已经快了。

    但是,如果您使用正确的方法(DAO记录集)进行插入,则可以跳过恼人的翻译为文本文件的步骤。请参阅我在StackOverflow上提出并回答的前一个问题: MS Access: Why is ADODB.Recordset.BatchUpdate so much slower than Application.ImportXML?

    即使使用DAO,也不要使用INSERT INTO;它很慢。也不要使用ADO;它很慢。但是DAO+Delphi+Recorsets+直接实例化DbEngine COM对象(而不是通过Access.Application对象)会给你带来很多速度。

        8
  •  1
  •   Yes - that Jake.    17 年前

    你朝着正确的方向看。使用单个语句进行批量插入比尝试迭代数据并逐行插入更快。Access是一个基于文件的数据库,在迭代写入中会非常慢。

    问题是Access正在处理它如何在内部优化写入,并且实际上没有任何方法可以控制它。您可能已经达到了INSERT语句的最大效率。为了提高速度,您可能应该评估是否有办法在每次启动应用程序时将800000条记录写入数据库。

        9
  •  1
  •   Diodeus - James MacFarlane    17 年前

    得到 SQL Server Express (免费)并从Access外部表连接到它。SQL express比MS Access快得多。

        10
  •  1
  •   Adam Davis    17 年前

    我会预先填充数据库,并将文件本身交给他们,而不是填充现有的(但空的)数据库。

    如果必须填充的数据发生了更改,则使用一些代码在服务器上保持ODBC访问数据库(MDB文件)同步,以查看主数据库中的更改并将其复制到访问数据库。

    当用户请求一个新的数据库时,压缩MDB,将其传输给他们,然后打开它。

    或者,您可以找到直接打开并将数据插入数据库的代码。

    或者,您也可以找到另一种格式(csv除外),这种格式可以更快地导入。

    -亚当

        11
  •  0
  •   MatthewMartin muthu    17 年前

    还要检查复制文件需要多长时间。这将是写入数据速度的下限。在像SQL这样的数据库中,通常需要一个大容量加载实用程序才能接近这个速度。据我所知,MS从未创建过像bcp那样直接写入MS Access表的工具。专门的ETL工具还将优化围绕插入的一些步骤,例如SSIS在内存中进行转换的方式,DTS也有一些优化。

        12
  •  0
  •   Tmdean    17 年前

    也许您可以使用锁定模式打开表的ADO记录集 adLockBatchOptimistic 和光标位置 adUseClient ,将所有数据写入记录集,然后进行批量更新( rs.UpdateBatch ).

        13
  •  0
  •   dkretz    17 年前

    如果它来自dbase,你能复制数据和索引文件并直接附加而不加载吗?应该相当高效(来自给你带来FoxPro的人)。我想它也会使用现有的索引。

    至少,它应该是一个非常高效的单一命令Import。

        14
  •  0
  •   Toby Allen mercator    17 年前

    从一个创建到下一个创建,这80万条记录有多大变化?在创建新数据库时,是否可以预先填充记录,然后只更新外部数据库中已更改的记录?

    这可以让您更快地创建新的数据库文件。

        15
  •  0
  •   Walter Mitty    17 年前

    你的磁盘转得有多快?如果是7200RPM,那么3分钟内800000行仍然是每转37行。我不认为你会做得更好。

    同时,如果目标是简化流程,那么表链接怎么样?

    你说你不能通过ADO访问源数据库。您能在MS Access中设置一个表链接到源数据库中的表或视图吗?然后,通过表链接执行一个简单的追加查询,就可以将数据从源数据库复制到目标数据库。我不确定,但我认为这会很快。

    如果在运行时之前无法设置表链接,也许可以通过ADO以编程方式构建表链接,然后以编程方式生成追加查询,然后调用追加查询。

        16
  •  -3
  •   tiphooo    15 年前

    夏威夷群岛 正如他们所说,最好的方法是从txt文件批量插入 您应该将记录插入txt文件,然后将txt文件批量插入表中 该时间应小于3秒。