为Lucene选择快速唯一标识符(UUID)

大多数使用Apache Lucene的搜索应用程序都会为每个索引文档分配唯一的ID(即主键)。 尽管Lucene本身不需要这样做(它可能不太在乎!),但应用程序通常需要它以后通过其外部ID替换,删除或检索该文档。 大多数在Lucene之上构建的服务器,例如Elasticsearch和Solr ,都需要一个唯一的ID,如果不提供,则可以自动生成一个ID。

有时,您的ID值已经预先定义,例如,如果外部数据库或内容管理系统分配了ID ,或者您必须使用URI ,但是如果您可以自由分配自己的ID,那么哪种方法最适合Lucene?

一个明显的选择是Java的UUID类,该类生成版本4的通用唯一标识符 ,但事实证明,这是性能上最糟糕的选择:它比最快的速度慢4倍。 要了解原因,需要对Lucene如何找到术语有所了解。

BlockTree术语词典

术语词典的目的是存储在索引期间看到的所有唯一术语,并将每个术语映射到其元数据( docFreqtotalTermFreq等 )以及totalTermFreq (文档,偏移量,投递和有效载荷)。 当请求一个术语时,术语词典必须在磁盘索引中找到它并返回其元数据。

默认编解码器使用BlockTree术语词典 ,该词典以排序的二进制顺序存储每个字段的所有术语,并将这些术语分配到共享公共前缀的块中。 默认情况下,每个块包含25到48个词。 它使用内存中的前缀三叉戟索引结构( FST )将每个前缀快速映射到相应的磁盘块,并在查找时首先根据请求的术语的前缀检查索引,然后在-disk块并扫描以查找术语。

在某些情况下,当段中的术语具有可预测的模式时,术语索引可以知道请求的术语不能存在于磁盘上。 这种快速匹配测试可以带来可观的性能提升,尤其是当索引很冷(操作系统的IO缓存不缓存页面)时,因为它避免了昂贵的磁盘搜寻。 由于Lucene是基于段的,因此单个id查找必须访问每个段直到找到匹配项,因此快速排除一个或多个段可能是一个大胜利。 保持细分受众群的数量尽可能少也很重要!

鉴于此,完全随机的id(例如UUID V4 )应该会表现最差,因为它们击败了术语索引快速匹配测试,并且需要对每个段进行磁盘搜索。 具有可预测的每段模式的ID(例如顺序分配的值或时间戳)应发挥最佳作用,因为它们将使术语索引快速匹配测试的收益最大化。

测试性能

我创建了一个简单的性能测试器来验证这一点。 完整的源代码在这里 。 该测试首先将1亿个ID索引到具有7/7/8段结构(7个大段,7个中段,8个小段)的索引中,然后搜索200万个ID的随机子集,记录最佳时间5次。 我在Ubuntu 14.04上使用Java 1.7.0_55,以及3.5 GHz Ivy Bridge Core i7 3770K。

由于Lucene的术语从4.0开始是完全二进制的 ,因此存储任何值的最紧凑的方法是二进制形式,其中每个字节使用所有256个值。 然后,一个128位ID值需要16个字节。

我测试了以下标识符来源:

  • 顺序ID(0、1、2,...),采用二进制编码。
  • 零填充的顺序ID(00000000、00000001等),采用二进制编码。
  • 纳米时间,二进制编码。 但是请记住, 纳米时间是棘手的 。
  • 使用此实现从时间戳,nodeID和序列计数器派生的UUID V1 。
  • UUID V4 ,使用Java的UUID.randomUUID()随机生成。
  • 片状ID ,使用此实现 。

对于UUID和Flake ID,除了标准(16或36基)编码之外,我还测试了二进制编码。 请注意,我仅使用一个线程测试了查找速度,但是在添加线程时,结果应该线性扩展(在足够并行的硬件上)。

图表

用二进制编码的零填充顺序ID最快,比非零填充顺序ID快很多。 UUID V4(使用Java的UUID.randomUUID() )慢了约4倍。

但是对于大多数应用程序来说,顺序编号是不实际的。 第二快的是UUID V1 ,以二进制编码。 令我惊讶的是,这比Flake ID快得多,因为Flake ID使用相同的原始信息源(时间,节点ID,序列),但是以不同的方式对位进行混洗以保留总体顺序。 我怀疑问题在于,在获取不同文档之间的数字之前,必须在片状ID中遍历的通用前导数字的数目,因为64位时间戳的高位在先,而UUID V1则在低位位首先是64位时间戳。 当一个字段中的所有术语共享一个公共前缀时,术语索引也许可以优化这种情况。

我还分别测试了10、16、36、64、256的基数,通常对于非随机ID,较高的基数更快。 我对此感到惊讶,因为我希望与BlockTree块大小(25到48)匹配的基数最好。

此测试有一些重要警告(欢迎补丁)! 一个真正的应用程序显然比简单地查找id还要做更多的工作,并且结果可能会有所不同,因为热点必须编译更多活动的代码。 在我的测试中,该索引非常热(有大量RAM可以容纳整个索引); 对于冷索引,我希望结果会更加鲜明,因为避免磁盘搜索变得非常重要。 在实际应用中,使用时间戳的id在时间上会更加分散; 我可以通过伪造更大范围的时间戳来“模拟”自己。 也许这会缩小UUID V1和Flake ID之间的差距? 我在索引编制过程中只使用了一个线程,但是具有多个索引编制线程的实际应用程序会将ID一次分散到多个段中。

我使用了Lucene的默认TieredMergePolicy ,但是有一种更聪明的合并策略可能会支持那些ID更加“相似”的合并段,从而可能会产生更好的结果。 该测试不执行任何删除/更新操作,这将在查找期间需要进行更多工作,因为如果给定的ID已被更新(除其中一个以外的所有其他ID),则该ID可能位于多个段中。

最后,我使用了Lucene的默认编解码器,但是当您愿意将RAM换成更快的查询时,我们有不错的发布格式针对主键查找进行了优化,例如去年的Google夏季代码项目和MemoryPostingsFormat 。 这些可能会提供可观的性能提升!

翻译自: https://www.javacodegeeks.com/2014/05/choosing-a-fast-unique-identifier-uuid-for-lucene.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363275.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu16.04设置静态ip

最近在课堂上,有很多同学反映在搭建环境的时候,虚拟机ip经常变,那么我们配置好的web服务可能就不能用了。下面讲一下如何在ubuntu上面设置静态ip 1:首先我们确认一下ubuntu的版本 cat /etc/issue 或者sudo lsb_release -a或者unam…

Maven常用的构建命令

Maven常用命令: Maven库: http://repo2.maven.org/maven2/ Maven依赖查询: http://mvnrepository.com/ 一,Maven常用命令: 1. 创建Maven的普通Java项目: mvn archetype:create-DgroupIdpackageName-Dartifa…

课时85.层叠性(掌握)

1.什么是层叠性? 层叠性就是CSS处理冲突的一种能力。 这个字体最终会变为红色 注意点: 层叠性只有在多个选择器选中“同一个标签”,然后又设置了“相同的属性”,才会发生层叠性。 CSS全称:Cascading StyleSheet 层叠样式表&am…

SetProcessWorkingSetSize减少内存占用

系统启动起来以后,内存占用越来越大,使用析构函数、GC.Collect什么的也不见效果,后来查了好久,找到了个办法,就是使用 SetProcessWorkingSetSize函数。这个函数是Windows API 函数。下面是使用的方法:[Syst…

Spring Boot 与消息 (JMS、AMQP、RabbitMQ)

RabbitMQ教程 - 鸟哥的专栏 - CSDN博客 一、概述 大多应用中,可通过消息服务中间件来提升系统异步通信、扩展解耦能力消息服务中两个重要概念:消息代理(message broker)和目的地(destination) 当消息发送者发送消息以后&#xff0…

JavaOne 2014 –有关提交的一些初步分析

这些天时间不多了。 并行发生的事情如此之多,当然,最重要的Java会议就是一切。 JavaOne 2014已经关闭了CfP门,投票正在进行中。 程序委员会几乎没有什么可以谈论的,但是去年跳过了这种分析之后,现在是我该寻求许可的时…

【译】XNA Shader 程序设计(二)

XNA Shader 程序设计 教程2 - 漫反射 大家好,今天我们将在教程一的基础上继续学习,在光照算式中加上漫反射光。 漫反射光 环境光计算等式为: I Aintensity * Acolor 漫反射基于这个等式,添加了一道有方向的光线: I A…

A股滚动净利润增速最高排名

最近2年(共8个季度)的滚动净利润都在增长,且平均增速超过10%。 计算举例:滚动净利润增速 ((2018Q1 到 2018Q4的净利润之和) / (2017Q4 到 2018Q3的净利润之和) -1) * 100%。 预测下季度:依据以往的增速,进…

Java 8 Friday:让我们弃用那些旧版库

在Data Geekery ,我们喜欢Java。 而且,由于我们真的很喜欢jOOQ的流畅的API和查询DSL ,我们对Java 8将为我们的生态系统带来什么感到非常兴奋。 Java 8星期五 每个星期五,我们都会向您展示一些不错的教程风格的Java 8新功能&#…

Educational Codeforces Round 10

652A - Gabriel and Caterpillar 20171128 按题意模拟即可 #include<stdlib.h> #include<stdio.h> #include<math.h> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int h1,h2,a,b,ans1; int main()…

内存不足:杀死进程或牺牲孩子

现在是早上6点。 我清醒地总结了导致我太早醒来的电话的事件序列。 这些故事开始时&#xff0c;我的电话警报响了。 困倦而脾气暴躁的我检查了电话&#xff0c;看我是否真的疯了以至于无法在凌晨5点设置唤醒警报。 不&#xff0c;这是我们的监视系统&#xff0c;表明Plumbr服务…

将Array、Dictionary等集合类的序列化和反序列化

Objective-C的集合类序列化到文件中或者从文件中反序列化其实很简单&#xff0c;请看下面的示例代码&#xff1a; NSArray *array [NSArray arrayWithObjects:"Hefeweizen", "IPA", "Pilsner", "Stout", nil];NSDictionary *dictiona…

职场交流:一位软件工程师的7年总结

2009年05月13日15:06  来源&#xff1a;1、分享第一条经验&#xff1a;“学历代表过去、能力代表现在、学习力代表未来。”其实这是一个来自国外教育领域的一个研究结果。相信工作过几年、十几年的朋友 对这个道理有些体会吧。但我相信这一点也很重要&#xff1a;“重要的道理…

JavaFX 8u20天的未来过去(始终在最前面)

自从我发布有关JavaFX的主题以来已经有很长时间了。 因此&#xff0c;如果您仍在追随&#xff0c;那就太棒了&#xff01; 介绍 在这篇博客文章中&#xff0c;我想写一篇关于从JavaFX 8 update 20开始的非常酷的功能的博客&#xff0c;该功能使您的应用程序始终位于其他应用程…

cocos creator实战-(三)简单例子摇杆控制角色移动

&#xff08;待完善&#xff0c;给玩家加上摄像机跟随效果&#xff09; 1、stick监听cc.Node.EventType.TOUCH_MOVE事件&#xff0c;获取tick移动的坐标和朝向&#xff0c;限制移动的范围 2、根据stick的朝向&#xff0c;每帧更新player的位置和方向 // 摇杆代码 joy_stick.jsc…

php构造数组,并把多数组插入php文件

晚上做的一点东西&#xff0c;发出来大家共享下&#xff01; Code<?php //php 链接数据库mysql_connect("localhost", "root", "hicc") or die("Could not connect: " . mysql_error());mysql_select_db("babyker");$re…

针对新手的Java EE7和Maven项目–第6部分

从前面的部分恢复 第1 部分 &#xff0c; 第2 部分 &#xff0c; 第3 部分 &#xff0c; 第4 部分 &#xff0c; 第5部分 在上一篇文章&#xff08;第5部分&#xff09;中&#xff0c;我们发现了如何使用Arquillian&#xff08;我们的EJB服务&#xff09;进行单元测试&#xf…

Starter pom

以下图片是引用书籍内容&#xff1a; 比如你在用boot写一个web项目&#xff0c;在maven中你会导入&#xff1a; <!-- 导入spring boot的web支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-we…

在 CentOS/Fedora 下安装 JAVA 环境

介绍 本文介绍如何在 CentOS 7&#xff08;6/6.5&#xff09;、 Fedora、RHEL 上安装 Java。Java是一个流行的软件平台&#xff0c;允许您运行Java应用程序。 本文涵盖了以下Java版本的安装&#xff1a; OpenJDK 8Oracle Java 8先决条件 在开始之前&#xff0c;您应该有一个能够…

ActiveMQ –经纪人网络解释–第5部分

在前面的第4部分中&#xff0c;我们已经看到了如何使用网络连接器在队列中平衡远程使用者的负载。 在第5部分中&#xff0c;我们将看到如果在某个主题上有并发远程持久订阅者&#xff0c;则相同的配置将如何工作。 考虑以下配置…。 图1&#xff1a;经纪人网络–主题上的负载…