需求分析:
我们需要将超大文本进行入库操作,需要进行拆分拆分操作,该系列分为三篇讲解:
- 一、文件拆分 - 将大文件拆分小文件,代码操作也能实现,但是没有Linux自带的命令效率高;
- 二、读写入库 - 将拆分后的小文件,通过读和写协程进行,边读边写入库,批量插入数据库(无序);
- 三、水平拆分 - 超大入库单表需要水平拆分,否则影响性能(2kw+),通过SQL命令操作,效率高;
二、读写入库
文件整体读取
文件整体读取就是将文件一次性读取到,理解上是将文件的内容第一次就读取完了
使用场景 :
- 针对小文件比较适用(大文件读取空间和时间的消耗也很大)
- 对于只读类型的文件也比较适用(文件也不能太大)
文件分片读取
对文件一部分一部分逐步的读取,直到文件完全读取完
PS : 每次读取文件的大小是根据设置的 分片 大小 ,所以对于读取文本类型的文件时(例如 : 日志文件)
不一定是按照你的期望逐行输出,因为不会处理文本尾部的换行符,而是按照分片大小读取内容
使用场景 :
- 读取超大的文件
- 读二进制类型的文件(比如:音视频文件或者资源类型文件等)
文件逐行读取
对文件一行一行的读取,直到读到文件末尾
使用场景 :
- 读取超大的文件很合适(例如 : 超大文本文件等)
- 读取的文件最好是有换行的(如果使用单行文件组成的大文件,需要注意)
- 对需要分析的内容大文件
- 统计某些数据出现的次数
- 查询某些数据是否存在
- 查找指定行的数据
超大txt文件的处理
针对超大txt文件,特点是有换行符,但是逐行读取入库操作还是很慢,还需要改进方案;
要想提高数据写入的速度,我们一方面要做并发的数据库写入,一方面又要尽量减少操作的次数,一次性插入尽可能多的记录;
- 主要的性能瓶颈其实是主协程对文本的读取速度,可以事先对文件进行分割操作,然后并发地做数据读入;
- 主协程逐条读取文本大数据,将数据封装后丢入全局数据管道;
- 开辟10条数据库写入协程,每个写入协程使用一个独立的数据库连接;
- 数据写入协程各自独立地从全局数据管道中获取数据,每满1000条就做一次数据库写入操作;
总结
- 面试中常见的类似超大文件读取的问题,通常我们采用分片读取或者逐行读取的方案即可
- 大文件的上传也可以采用类似的解决方案 , 每次读取文件的部分内容上传(写入)网络接口中,直至文件读取完毕
普通的小文件并且对内容没有太多操作的,可以采用整体读取,速度相对较快 - 对文件内容有操作的采用分片读取和逐行读取更合适
- 二进制类型文件采用分片读取或者整体读取的方案比较合适
- 文件读取不仅是本地文件,要读去网络上的文件(各种文档,音视频,图片,和其他各种类型文件)时要访问到文件获取 io.ReadCloser 或者 io.Reader 后可以采用三种方式将文件内容读取到
func ReadAll(r io.Reader) ([]byte, error) 文件完整读取
func Copy(dst Writer, src Reader) (written int64, err error) 文件读取并写入
type Reader interface {
Read(p []byte) (n int, err error)
}
通过Reader 接口的 Read 方法读取
本文含有隐藏内容,请 开通VIP 后查看