背景
本文中的测试方法或测试数据,如有不正确的地方,望不吝指正。
这篇文章主要是记录Lucene7.5版本创建索引过程中各个阶段所花的时间,以及后续的优化过程。测试电脑的配置如下,硬盘为SSD硬盘:
测试是把本地的文件数据录入Lucene,方便后续的检索。所有测试都是单线程操作。准备的测试数据每条有31个字段,共394794条数据,分为两次测试,一次是以文件中不存字段信息,只将值按照某种格式组装起来,解析为数组进行操作,一次是使用json的格式来处理数据。Lucene的配置只做了如下调整,其它全部是默认,分词器选择的是IK分词器:
config.setRAMBufferSizeMB(100);
indexWriter.forceMerge(10);
数组解析
本地数据封装最开始使用的是按照某种格式拼接为字符串的形式,最开始选用的是string的split方法进行处理,发现它的性能实在是不敢恭维。后面换成stringtokenizer方法进行处理,发现性能也好不了多少,下面是测试对比数据,单位(毫秒):
测试方法 | 总数据量 | 第1次耗时 | 第2次耗时 | 第3次耗时 | 第4次耗时 |
---|---|---|---|---|---|
String的split | 394794 | 15309 | 15448 | 15484 | 15513 |
stringtokenizer | 394794 | 11319 | 11368 | 12149 | 12258 |
处理的代码如下:
//下面这个是字符串分割用的测试方法
String[] values = content.split("```");
//下面这个是用StringTokenizer的测试方法
List<String> values = new ArrayList<>();
StringTokenizer stringTokenizer = new StringTokenizer(content, "```");
while( stringTokenizer.hasMoreElements() ){
values.add(stringTokenizer.nextToken());
}
从上面的数据可以初步看出使用stringtokenizer的处理方式也没有提升很多,这个性能还不是我想要的。于是考虑使用json的方式来处理,看看性能怎么样。
JSON处理方式
同样的字段数转换为json的方式进行存储到文件,再对文件进行处理。开源的json序列化工具也有好几个,在网上找到这篇文章各种JSON性能对比,我选择它(jsoniter)和我们熟悉的fastjson进行比较测试。
测试方法 | 总数据量 | 第1次耗时 | 第2次耗时 | 第3次耗时 | 第4次耗时 |
---|---|---|---|---|---|
fastjson的parseObject方式 | 394794 | 19674 | 19762 | 19866 | 19908 |
JsonIterator的deserialize方式 | 394794 | 9696 | 9860 | 9887 | 9975 |
代码如下:
//下面这个是fastjson
JSONObject object = JSON.parseObject(content);
//下面这个是JsonIterator
Any any = JsonIterator.deserialize(content);
从上面的数据可以看出JsonIterator更胜一筹,所以后续的测试就在它的基础之上进行。
各阶段耗时
下面先列出完整过程中各个阶段所花费的时间,每个阶段是依次进行的,比如第一阶段:文件读取是把后续步骤注释掉执行测试的,第二阶段json所化的时间是第一阶段和第二阶段之和,异常类推:
阶段 | 总数据量 | 第1次耗时 | 第2次耗时 | 第3次耗时 | 第4次耗时 |
---|---|---|---|---|---|
文件读取 | 394794 | 5312 | 4302 | 4854 | 4662 |
json解析 | 394794 | 9099 | 8596 | 8268 | 9056 |
创建doc | 394794 | 26266 | 25894 | 2582 | 2619 |
addDocument | 394794 | 133558 | 12863 | 13165 | 126503 |
addDocuments | 394794 | 125862 | 14525 | 146823 | 145100 |
创建doc是指:创建各个Document的各个Field,测试数据是31个字段,因为要涉及到范围查找和存值,所以构造完成之后的Document有60来个Field。addDocument和addDocuments是Lucene提供的两个接口,第一个的形参是一个Document,而addDocuments的形参是Document的一个List。
结论:通过上面的数据发现在创建Document对象和addDocument两个阶段耗时是比较严重的。下一步再研究研究这两个阶段有没有提升的空间。
2019-01-06
JsonIterator在使用过程中发现对这样对字符串解析会出错:
"/*!40100 SET @@SQL_MODE=\'\' */;"
大家在使用前,先看看自己的数据中是否有这样的字符串。貌似是“\”导致的。还没去确定。