我有一个可能包含大约 300 万条记录的文件。在整个程序运行过程中,该文件的某些记录需要多次更新。如果我需要从该文件中提取特定记录,以下哪个更有效:
- 索引 VSAM 搜索
- 使用 COBOL 搜索所有索引的平面文件
- 将所有数据缓冲到工作存储中并编写一个循环来处理搜索
我有一个可能包含大约 300 万条记录的文件。在整个程序运行过程中,该文件的某些记录需要多次更新。如果我需要从该文件中提取特定记录,以下哪个更有效:
显然,如果您可以将所有数据缓冲到内存中(并且如果主机系统可以支持足够大的页面工作集以允许所有数据实际保留在 RAM 中而无需分页,那么这可能是最快的可能的做法。
但是,要非常小心考虑由虚拟内存分页子系统引起的“隐藏磁盘 I/O”!如果请求的“内存中”数据实际上不是“内存中”,则会发生页面错误,并且您的进程将停止在其轨道上,直到检索到该页面。(如果发生“页面窃取”,那么您就有麻烦了。您的“内存中”策略只是变成了一种可能非常低效(!)的基于磁盘的策略。如果密钥是随机分布的,那么您的进程有一个巨大的工作集,它正在随机访问。 如果所有的内存实际上都没有在内存中,并且会留在内存中,那么你就有麻烦了。
如果您正在对一个大文件进行更新,请考虑在处理之前对 updates-delta 文件进行排序,以便相同键的所有出现都是相邻的。您现在可以编写 COBOL 程序来利用这一点(当然,abend
如果检测到失序记录!)。 如果“此”记录中的键与“上一个”记录中的键相同,则无需重新读取该记录。(而且,你实际上不需要写旧记录,直到键确实发生变化。)由于索引文件访问方法呈现出一系列键,因此每个键可能“接近”先前请求的键,因此某些必要的索引-树页面将已经在内存中。显然,您需要对此进行基准测试,但排序文件所花费的时间可能远远少于索引查找所花费的时间。(这实际上可能相当大。)
Mike 的答案有一个关于“隐藏 I/O”的重要问题(取决于机器、配置、数据量)......
如果您很可能需要更新许多记录,那么 Mike 建议的选项是最有用的选项。
如果您很可能需要更新的记录不多(我猜您可能低于 2%),另一种方法可能会更快(需要基准!):
REWRITE
REQRITE
所有记录(如果您有完整的记录REWRITE
就足够了,否则您需要READ
先获得完整的记录)性能通常是:“了解您的数据和可能的程序流程,然后尝试最好的 2-3 方法,进行基准测试并做出决定”。