【Python实战】解决TB级别大文件自然数排序难题:解决方案详解及完整代码示例

📌 一、问题背景

  • 输入数据: 一个大小为 100TB 的文本文件,每行一个自然数。
  • 可用资源: 内存限制为 16GB
  • 目标: 对这 100TB 的数据进行升序排序并输出到文件。
  • 由于数据量远大于内存容量,无法一次性加载全部数据进行排序,因此需要采用分治 + 外排序的方法来解决。


    🧩 二、解决方案概述

    整个流程分为四个核心步骤:

    1. 查找最大值: 遍历原始文件找到最大数值,用于后续合理划分区间。
    2. 分片(Partitioning): 按照数值范围将大文件拆分成多个小文件。
    3. 排序(Internal Sorting): 将每个小文件加载进内存排序后写入磁盘。
    4. 多路归并(K-way Merge): 使用最小堆算法合并所有已排序的小文件,生成最终有序结果。

    🛠️ 三、具体实现步骤详解

    ✅ 步骤 1:查找最大值

    def find_max_number(file_path):
        max_num = 0
        with open(file_path, 'r') as f:
            for line in f:
                num = int(line.strip())
                if num > max_num:
                    max_num = num
        return max_num
    

    🔍 说明:

    这一步是为了动态设置数值区间的大小,确保分区均匀,避免出现某些分区过大或为空的情况。


    ✅ 步骤 2:按数值区间分片

    def partition_file(max_num):
        range_size = max_num // NUM_PARTITIONS + 1
        partition_files = [
            open(os.path.join(PARTITION_DIR, f'partition_{i}.txt'), 'w')
            for i in range(NUM_PARTITIONS)
        ]
    
        with open(INPUT_FILE, 'r') as f:
            for line in f:
                num = int(line.strip())
                idx = num // range_size
                if idx >= NUM_PARTITIONS:
                    idx = NUM_PARTITIONS - 1
                partition_files[idx].write(line)
    
        for fp in partition_files:
            fp.close()
    

    🔍 说明:

    使用 num // range_size 计算该数字属于哪个分区,从而将原始数据分散到多个文件中,便于后续排序。


    ✅ 步骤 3:内部排序每个小文件

    def sort_partitions():
        for i in range(NUM_PARTITIONS):
            input_path = os.path.join(PARTITION_DIR, f'partition_{i}.txt')
            output_path = os.path.join(PARTITION_DIR, f'sorted_partition_{i}.txt')
    
            with open(input_path, 'r') as f:
                nums = list(map(int, f.readlines()))
            nums.sort()
    
            with open(output_path, 'w') as f:
                for num in nums:
                    f.write(str(num) + '\n')
    

    🔍 说明:

    每个小文件的数据量控制在 1GB 左右,可以轻松加载进内存进行排序。


    ✅ 步骤 4:多路归并排序(K-way Merge)

    def merge_sorted_partitions():
        heap = []
        pointers = []
    
        for i in range(NUM_PARTITIONS):
            path = os.path.join(PARTITION_DIR, f'sorted_partition_{i}.txt')
            fp = open(path, 'r')
            line = fp.readline()
            if line:
                heapq.heappush(heap, (int(line.strip()), i))
            pointers.append(fp)
    
        with open(OUTPUT_FILE, 'w') as out_file:
            while heap:
                val, idx = heapq.heappop(heap)
                out_file.write(str(val) + '\n')
    
                next_line = pointers[idx].readline()
                if next_line:
                    heapq.heappush(heap, (int(next_line.strip()), idx))
    
        for fp in pointers:
            fp.close()
    

    🔍 说明:

    使用 最小堆 来高效地从多个有序文件中取出当前最小值,逐步构建最终有序序列。这是大数据归并的经典做法。


    📈 四、时间复杂度与性能分析

    步骤 时间复杂度 说明
    查找最大值 O(N) 遍历一次文件
    分片 O(N) 每个数字只处理一次
    排序各分片 O(n log n) × K 每个分片排序
    多路归并 O(N log K) 使用堆结构高效归并

    整体效率高,适合处理超大规模数据。


    🧪 五、测试脚本:生成 1GB 测试数据

    为了验证程序是否正常工作,我们可以先生成一个 1GB 的测试文件:

    import random
    
    TARGET_SIZE_BYTES = 1 * 1024 * 1024 * 1024  # 1GB
    CHUNK_SIZE = 100000
    
    with open('input.txt', 'w') as f:
        total = 0
        while total < TARGET_SIZE_BYTES:
            data = '\n'.join(str(random.randint(0, 10**9)) for _ in range(CHUNK_SIZE)) + '\n'
            f.write(data)
            total += len(data.encode())
            print(f"\r已写入: {total // (1024 * 1024)} MB", end='')
    

    📦 六、总结

    通过这篇文章,我们了解了如何使用 Python 对一个 1TB 的自然数文件 进行排序,主要涉及以下关键技术点:

  • 外排序思想(External Sort)
  • 分片(Partitioning)
  • 内存排序
  • 多路归并(K-way Merge)
  • 最小堆(优先队列)
  • 这套方案不仅适用于 1TB 文件排序,也可以扩展到更大的数据集和分布式系统中。


    📚 七、参考资料 & 延伸阅读

  • External sorting – Wikipedia
  • Python 官方文档:heapq / mmap / multiprocessing
  • CSDN 热门博文推荐:《MapReduce 实现大数据排序》《基数排序原理详解》

  • 💬 八、结语

    如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、评论支持一下作者!

    如需获取完整代码打包版本、带进度条优化版、日志记录功能、甚至封装成命令行工具,请在评论区留言,我可以继续为你完善!


    GitHub / Gitee 示例项目地址(可选):
    👉 https://github.com/phil-zhan/external-sort


    作者:风千叶

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【Python实战】解决TB级别大文件自然数排序难题:解决方案详解及完整代码示例

    发表回复