5

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

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

tAdoCommand通过将记录写入制表符分隔的文本文件并使用对象执行,我设法缩短到大约 1 分钟

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

但我不喜欢这样的开销。

我认为必须有更好的方法。

编辑:

一些附加信息:

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

编辑:

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

4

16 回答 16

9

既然您说过 800K 记录数据在数据库的生命周期内不会改变,我建议将文本文件作为表链接,并完全跳过插入。

如果硬要拉进数据库,那么1分钟80万条记录就超过13000条/秒。我认为您不会在 MS Access 中击败它。

如果您希望它对用户响应更快,那么您可能需要考虑加载一些最小的数据集,并设置一个后台线程以在它们工作时加载其余部分。

于 2009-02-06T20:31:51.837 回答
5

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

在这个线程慢 MSAccess 磁盘写入中可能有一些可能感兴趣的建议

于 2009-02-06T20:29:13.730 回答
4

跳过文本文件并使用 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 文件的链接表的连接字符串,因此参数可能略有不同。

于 2009-02-06T22:21:59.883 回答
3

换个安排怎么样...

是否可以选择复制具有您需要的此表的现有 Access 数据库文件,然后删除除此大表之外的所有其他数据(不知道 Access 是否具有类似“ SQL Server 中的截断表)?

于 2009-02-06T20:57:35.497 回答
3

我会用另一个数据库替换 MS Access,对于您的情况,我认为Sqlite是最佳选择,它不需要任何安装到客户端计算机,它是非常快速的数据库和最好的嵌入式数据库解决方案之一。

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

  1. 您可以从Sqlite网站下载数据库引擎 Dll并使用免费的 Delphi 组件来访问它,如Delphi SQLite 组件SQLite4Delphi

  2. 使用内置引擎的DISQLite3,您不必将 dll 与您的应用程序一起分发,它们有免费版本;-)

如果您仍然需要使用 MS Access,请尝试直接使用带有 SQL Insert 语句的 TAdoCommand,而不是使用 TADOTable,这应该比使用 TADOTable.Append 更快;

于 2009-02-07T10:41:18.113 回答
3

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

因此,使用该文件开始真正的填充 - Access 不会请求任何(或很少)额外的磁盘空间。如果 MS Access 有办法自动执行此操作,请不要记住,但它可以帮助很多......

于 2010-09-14T18:46:24.387 回答
2

正如有人提到的,您不会在一分钟内导入 800,000 条记录;这已经非常快了。

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

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

于 2010-09-14T19:45:27.497 回答
1

您正在以一种方式寻找正确的方向。使用单个语句进行批量插入比尝试遍历数据并逐行插入要快。作为基于文件的数据库,Access 在迭代写入中会非常慢。

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

于 2009-02-06T20:30:37.223 回答
1

获取SQL Server Express(免费)并从 Access an external table 连接到它。SQL express 比 MS Access 快得多。

于 2009-02-06T20:31:37.640 回答
1

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

如果你要填写的数据发生变化,那么在服务器上保持一个 ODBC 访问数据库(MDB 文件)同步,使用一些代码来查看主数据库中的变化并将它们复制到访问数据库中。

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

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

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

-亚当

于 2009-02-06T21:03:56.280 回答
0

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

于 2009-02-06T20:34:30.460 回答
0

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

于 2009-02-06T21:02:07.313 回答
0

如果它来自dbase,您可以直接复制数据和索引文件并直接附加而不加载吗?应该非常有效(来自为您带来 FoxPro 的人。)我想它也会使用现有的索引。

至少,它应该是一个非常有效的单命令导入。

于 2009-02-06T22:00:18.647 回答
0

800,000 条记录从一次创作到另一次创作的变化有多大?是否可以预先填充记录,然后在创建新数据库时更新外部数据库中已更改的记录?

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

于 2009-02-07T09:07:07.570 回答
0

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

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

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

如果直到运行时才能设置表链接,也许您可​​以通过 ADO 以编程方式构建表链接,然后以编程方式构建追加查询,然后调用追加查询。

于 2009-02-09T07:36:49.163 回答
-3

嗨最好的方法是从 txt 文件批量插入,因为他们说您应该将记录插入 txt 文件,然后将 txt 文件批量插入表中,时间应该小于 3 秒。

于 2010-09-14T10:34:55.910 回答