# question **Repository Path**: doomthr/question ## Basic Information - **Project Name**: question - **Description**: No description available - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-12 - **Last Updated**: 2023-03-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 分析 1. 首先用了一个自己以前写的用于排序用的最大堆 `MaxHeap`,内部采用数组 `Array` 来存放元素。我这个 `MaxHeap` 有 3 个构造方法,其中将数组元素作为参数传入的构造方法是效率最高的,因为他节省了动态申请内存空间的时间。 2. 使用 `BufferedReader` 进行文本读取,读取出来后解析 `json` 并放入最大堆中,每读取够 600000 行数据(防止 `OOM`,这个值还可以优化),则将 `MaxHeap` 中通过 `extractMax()` 方法取出元素,并依次写入文件中,这样保证了每一个拆分后的文件都是有序的,拆分完成后得到的文件个数为 `fileCount`。 3. 文件拆分工作完成后,创建和文件数量相等的 `BufferedReader` 进行读取,首先从每个 `BufferedReader` 读取一个元素并放入新的 `MaxHeap` 中,放入的同时,设置好每一个元素的对应的文件索引 `index`,这样就得到了 `fileCount` 个元素,然后使用 `extractMax()` 取出这些当中最小的元素,即为所有元素中最小的元素,当索引为 `index` 的元素被选中为最小元素时,再从元素所在文件中读取一个新的元素放入 `MaxHeap` 中,依次类推。当从 `MaxHea` 中取出的元素为 10000 时(防止 `OOM`,这个值还可以优化),使用 `jdbc` 批量插入数据库中。这样数据库就存入了 一亿 条有序数据。 ## 备注 1. `JSON` 文件太大,需要将 `testjson.txt` 放入项目根目录。启动使用 `-Xmx128m` 参数控制内存大小。直接运行 `Question` 的 `main()` 方法或者运行测试类 `QuestionTest` 的 `testBigData()` 方法即可。 2. 开始采用了 `MyBatis` 进行数据批量录入,发现时间花费比较久,后来采用 `jdbc` 能节省一半的时间。 3. `MaxHeap` 的新增和取出的时间复杂度为 `O(logn)`,还算效率比较高的一种数据结构。 4. `JSON` 解析用了 `fastjson`,如果用 `Java` 原声解析可能还会节省点内存。 5. 应该还有很大的优化空间。 在我电脑上连接嗨送服务器数据库的执行结果: ```console 开始时间:Mon Aug 10 21:02:54 CST 2020 开始拆分文件... 文件拆分排序完毕,一共拆分了167个文件。耗时:253秒 开始录入数据库... 获取连接成功 已经插入了10000000行数据 已经插入了20000000行数据 已经插入了30000000行数据 已经插入了40000000行数据 已经插入了50000000行数据 已经插入了60000000行数据 已经插入了70000000行数据 已经插入了80000000行数据 已经插入了90000000行数据 已经插入了100000000行数据 数据库录入完毕。耗时:1955秒 结束时间:Mon Aug 10 21:39:42 CST 2020 全部执行完毕。耗时:2208秒 ``` 总共耗时:36 分钟 48 秒