0

在我的办公室,我们有一个遗留的会计系统,它将所有数据存储在具有固定宽度记录的纯文本文件(TXT 扩展名)中。每个数据文件都被命名为例如 FILESALE.TXT。我的目标是将这些数据带入我们的 MySQL 服务器,以供许多其他无法与旧版软件交互的程序只读使用。每个文件本质上是一个表。

我总共需要访问大约 20 个文件,大约 1gb 的总数据。每行可能有 350-400 个字符宽并且有 30-40 列。拉入数据后,没有一个 MySQL 表比 100mb 大得多。

遗留会计系统可以修改文本文件中的任何行,删除旧行(它有一个已删除的记录标记——0x7F),并随时添加新行。

几年来,我每 5 分钟运行一次 cron 作业:

  1. 检查每个数据文件的最后修改时间。
  2. 如果文件没有被修改,跳过它。否则:
  3. 解析数据文件,清理所有问题(仅非常简单的检查),然后输出我需要的列的制表符分隔文件(我只是忽略了一些列)。
  4. 截断表并将新数据导入我们的 MySQL 服务器,如下所示:

    START TRANSACTION;
    TRUNCATE legacy_sales;
    LOAD DATA INFILE '/tmp/filesale.data' INTO TABLE legacy_sales;
    COMMIT;
    

cron 脚本并行运行每个文件检查和解析,因此整个更新过程并不需要很长时间。最大的表(不经常更改)需要大约 30 秒来更新,但大多数表需要不到 5 秒的时间。

这一直工作正常,但存在一些问题。我猜它会混淆数据库缓存,所以每次我必须 TRUNCATE 和 LOAD 一个表时,其他使用 MySQL 数据库的程序一开始很慢。此外,当我切换到并行运行更新时,数据库可能会在几秒钟内处于稍微不一致的状态。

这整个过程似乎效率低下!有没有更好的方法来解决这个问题?关于可能值得研究的优化或程序的任何想法?遇到类似情况的人有什么巧妙的技巧吗?

谢谢!

4

3 回答 3

2

几个想法:

  • 如果文本文件中的行具有修改时间戳,您可以更新脚本以跟踪其运行时间,然后仅处理自上次运行以来已修改的记录。

  • 如果文本文件中的行有一个可以作为主键的字段,您可以为每一行维护一个指纹缓存,由该 id 键控。使用它来检测行何时更改,并跳过未更改的行。即,在读取文本文件的循环中,计算整行的 SHA1(或其他)哈希,然后将其与缓存中的哈希进行比较。如果它们匹配,则该行没有改变,所以跳过它。否则,更新/插入 MySQL 记录并将新的哈希值存储在缓存中。缓存可以是 GDBM 文件、memcached 服务器、MySQL 表中的指纹字段等等。这将使未更改的行在 MySQL 上保持不变(因此仍被缓存)。

  • 在事务中执行更新以避免不一致。

于 2013-03-05T22:01:39.477 回答
0

我想到了两件事,我不会详细说明,但请随时提出问题:

  1. 一种将文件处理卸载到应用程序服务器然后只填充 mySQL 表的服务,您甚至可以通过检查重复记录而不是截断整个表来构建智能。

  2. 将处理卸载到另一个 mysql 服务器并复制/传输它。

于 2013-03-05T21:47:51.863 回答
0

我同意亚历克斯的建议。如果可以的话,只更新修改过的字段,并使用分组的事务和多个插入进行批量更新。事务的另一个好处是更新速度更快

如果您担心停机时间,请不要截断表,而是插入新表。然后重命名它。

为了提高性能,请确保您对字段进行了正确的索引。

查看数据库特定的性能提示,例如 _delayed_inserts in mysql 提高性能 _ 可以优化缓存 _ 即使您没有唯一的行,您可能(或可能不)能够 md5 行

于 2013-03-06T03:49:59.770 回答