上亿行文本如何高效查询?
由于在开始的时候脑子里面有点想法 所以先自己动手做了一下再来问
是这样的 一个文本文件上亿行 写一个程序在里面查询对应的行
文本文件的每一行是 "Key-Value" 的形式
而Key是数字的字符串形式 是1 - 9 开头的无重复key 且在 int.MaxValue 内
现在要求给出 key 查找出key哪一行的数据 也就是 key - value 都查询出来
由于文件只用作查询 所以不用考虑增删改
我自己动手做了一下 由于现在完整文件不在我这里 我这里只有从文件切下来的200M 有八百多万行
自己写的那个程序针对这 八百万行 还算乐观 不知道对于完整的2G多的文件是啥效果
所以想请教一下 有这方面经验的人士 一般遇到这样的情况你们怎么处理
我是分了三大部
第一拆分文件:
先创建9个文本文件【1 - 9.txt】然后遍历文件每一行将取出每一样第一个字符 根据情况放入9个文本中
然后还有一个 int[9] 用做在遍历的时候保存每个文本文件当前有多少行数
然后遍历完成 将 int[9] 里面保存的每个文件的行数也写入到一个文件中 lines.txt
第二创建索引:
我定义了一个结构
[解决办法]
您可以将文件中的数据用程序导入到数据库中(e.g. mysql), 后续的查询就快多了.
自己在文本中做海量数据的查询,不应该这么搞吧?
您得到的那个举行文本数据, 按照您的想法, 可以先用程序拆成100~1000个小文件.
然后您在本地建立一个数据库(mysql), 按照您的文本字段格式, 建立一个或一个关联的表.
用程序将小文件集合中的数据录入到数据库.
查询那就块多了, 效率由数据库, 服务器性能去保证.
我觉得这么干比较靠谱.
[解决办法]
你的做法中,建议不要使用0-9分段的方法,否则某个段的数据量太大了你很不好处理,要重写,否则效率会降低。
不知道你的数据是否按Key排序,如果没有,就外排一次。然后分割成很多文件,每个文件的名称中包含该文件第一条数据的KEY值。
查询时,先根据KEY值,打开对应的文件,然后进行查找。如果这个可以文件全部加载到内存,就二分,否则顺序查找。
因为你说数据不会经常改变,所以这个方法应该比较好。
每次插入,在写入对应的文件前进行排序。
如果某个文件对应的数据段包括的数据量变大,就将它拆分成两个文件。不需要对后继的文件进行更名。
另外创建一个数据结构,保存每个文件的对应行数。查找到对应的行以后,加上它之前的所有文件的总行数就是你要的结果。每次插入或拆分后,要修改这个数据。
另外,就是做成一个Access的文件进行查询,在开发效率和使用效率方面也比这种方法要好得多啊。
[解决办法]
建索引对全部数据扫描一次,读取数据+建索引的时间>直接读取txt文件,而且多出索引的空间
后续读取,读取索引时间=直接读取txt的时间,都是顺序读取,
根据索引去查找txt文件,最好情况第一次就读取到,最坏情况要读到最后,平均时间=1/2直接读取txt时间
[解决办法]
这样做,就算建立二级索引,最坏情况(缓存不命中)要读取硬盘两次。
如果Value定长或者长度相近的话,可以考虑也存到索引表。这样建立二级索引,最坏情况(缓存不命中)只读取硬盘一次。
[解决办法]
你这个做法就可以了,分多个文件那步可以省略,直接创建索引,然后根据索引二分查找,这已经是最直接的方法了,用什么数据库也不会比这个更快了。
也许还有一种更快的方法,用空间换时间,不过索引文件要高达15G,从0到intMax每个key记录一个偏移量,直接根据key数值*4就能定位偏移量,两次磁盘操作就能取出key-value,每个key的操作时间都一样
[解决办法]
这让我想起数据库中最常用的B*索引,下面是典型的B*树索引布局:
你不妨参考它来设计你的文件索引
[解决办法]
文本?txt文件?加载到内存都是件痛苦的事情,需要配合多文件+索引来实现,否则就在一个txt里面,怎么优化都是逐行读取;
数据库是索引和指针的结合,通过索引获取数据的指针,然后读取指针位置的数据,每个数据单元又有其头,包含了数据的概要信息,你这上亿行的txt,首先要拆分开。。。。
[解决办法]
依据key算出偏移量(但是前提比较扯,先排序,补齐没有的key,对齐每一行,,,,,这样key中就隐含有偏移量信息了)
算出偏移量的时候读取或许可以利用下分区表,直接找到。
我算不算异想天开啊
[解决办法]
55 56 57
综合上述得出:key中必须包含偏移信息(前期需处理数据对齐太蛋疼了)。然后去读分区文件分表记录,找到文件记录信息,算出在key对应的数据所在的簇的范围,读取这个范围的数据。
[解决办法]
这么点数据量很难说明问题。
放1T数据试试看。
而且通过seek操作,大量随机读,估计数据量大了,性能真不好。
[解决办法]
个人认为建立一个数据,分别记录:key,value,行数;逐行对数据分析,存入数据库;把key作为数据库索引;以后只对数据库操作;
[解决办法]
[解决办法]