知识卡片
Unix工具批处理:排序与内存聚合的权衡
内容
同一个”统计最受欢迎URL”的任务,可以用Unix管道(sort | uniq -c | sort -rn | head)实现,也可以用一段Ruby脚本在内存哈希表里累加计数实现,两者看起来功能等价,但底层执行策略截然不同:哈希表方案的性能取决于作业的工作集(需要随机访问的内存大小)——只要不同URL的数量能装进内存,哈希聚合就很快;一旦工作集超出可用内存,哈希表方案就会失效,而排序方案的优势在于能高效利用磁盘:数据块可在内存中排序后写成段文件,再把多个有序段合并成更大的有序文件,这正是[[SSTable按键排序换来高效合并与稀疏内存索引]]背后同一套原理(归并排序对磁盘的顺序访问模式极为友好)。GNU Coreutils的sort命令能自动在数据超出内存时溢出到磁盘、并利用多核并行排序,这意味着看似简陋的Unix命令链天然可以伸缩到远超内存容量的大数据集,而不必自己操心内存管理。发散:这提醒我们,”聚合”这个操作在工程实现上其实有两条完全不同的路径——是否依赖有序性,决定了它对内存的敏感程度。
参考来源
- 位置:《数据密集型应用系统设计》第十章《批处理》"简单日志分析""排序 VS 内存中的聚合"(源文件:_epub-src/ch10_split_000.html)
- 结论依据:原文对比Unix管道的排序方案与Ruby脚本的内存哈希表方案,指出前者依赖工作集大小、后者依赖磁盘顺序I/O,并说明GNU sort能自动溢出磁盘并行排序,直接支撑本卡片结论。
- 原始内容:Ruby脚本在内存中保存了一个URL的哈希表……如果作业的工作集大于可用内存,则排序方法的优点是可以高效地使用磁盘……GNU Coreutils(Linux)中的sort程序通过溢出至磁盘的方式来自动应对大于内存的数据集。