0

我有一个可能包含大约 300 万条记录的文件。在整个程序运行过程中,该文件的某些记录需要多次更新。如果我需要从该文件中提取特定记录,以下哪个更有效:

  1. 索引 VSAM 搜索
  2. 使用 COBOL 搜索所有索引的平面文件
  3. 将所有数据缓冲到工作存储中并编写一个循环来处理搜索
4

2 回答 2

5

显然,如果您可以将所有数据缓冲到内存中(并且如果主机系统可以支持足够大的页面工作集以允许所有数据实际保留在 RAM 中而无需分页,那么这可能是最快的可能的做法。

但是,要非常小心考虑由虚拟内存分页子系统引起的“隐藏磁盘 I/O”!如果请求的“内存中”数据实际上不是“内存中”,则会发生页面错误,并且您的进程将停止在其轨道上,直到检索到该页面。(如果发生“页面窃取”,那么您就有麻烦了。您的“内存中”策略只是变成了一种可能非常低效(!)的基于磁盘的策略。如果密钥是随机分布的,那么您的进程有一个巨大的工作集,它正在随机访问。 如果所有的内存实际上都没有在内存中,并且会留在内存中,那么你就有麻烦了。

如果您正在对一个大文件进行更新,请考虑在处理之前对 updates-delta 文件进行排序,以便相同键的所有出现都是相邻的。您现在可以编写 COBOL 程序来利用这一点(当然,abend如果检测到失序记录!)。 如果“此”记录中的键与“上一个”记录中的键相同,则无需重新读取该记录。(而且,你实际上不需要旧记录,直到键确实发生变化。)由于索引文件访问方法呈现出一系列键,因此每个键可能“接近”先前请求的键,因此某些必要的索引-树页面将已经在内存中。显然,您需要对此进行基准测试,但排序文件所花费的时间可能远远少于索引查找所花费的时间。(这实际上可能相当大。)

于 2016-06-24T17:13:24.573 回答
4

Mike 的答案有一个关于“隐藏 I/O”的重要问题(取决于机器、配置、数据量)......

如果您很可能需要更新许多记录,那么 Mike 建议的选项是最有用的选项。

如果您很可能需要更新的记录不多(我猜您可能低于 2%),另一种方法可能会更快(需要基准!):

  • 通过索引 VSAM 搜索读取每个键
  • 将更改的记录存储在内存中(大发生表),如果您只会更改一些值并且记录很大,那么只将所有可能的更改值+键存储在表中,而不需要实际REWRITE
  • 在进行 VSAM 搜索之前:如果您已经读取了密钥,请查看您的发生表,从那里获取值或获取新值
  • ...
  • 在程序结束时:检查您的发生和REQRITE所有记录(如果您有完整的记录REWRITE就足够了,否则您需要READ先获得完整的记录)

性能通常是:“了解您的数据和可能的程序流程,然后尝试最好的 2-3 方法,进行基准测试并做出决定”。

于 2016-06-24T19:37:29.253 回答