//创建三个分片,没有副本的collection2
http://10.xx.xx.xx:8180/solr/admin/collections?action=CREATE&name=collection2&numShards=3&replicationFactor=1
//更新schema.xml
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
<field name="_version_" type="long" indexed="true" stored="true"/>
<field name="_root_" type="string" indexed="true" stored="false"/>
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="title" type="text_general" indexed="true" stored="true" multiValued="true"/>
<field name="subject" type="text_general" indexed="true" stored="true"/>
<field name="description" type="text_general" indexed="true" stored="true"/>
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
<uniqueKey>id</uniqueKey>
<copyField source="title" dest="text"/>
<copyField source="subject" dest="text"/>
<copyField source="description" dest="text"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
</schema>
//更新zookeeper配置文件
/opt/solr-4.10.3/example/scripts/cloud-scripts/zkcli.sh -zkhost 127.0.0.1:2181 -cmd upconfig -confdir /opt/solrhome1/collection1/conf -confname mysolrconf
进入solr管理页面,对collection,点击“RELOAD”重新加载配置。
进入管理页面Documents,复制进去,点击submit document即可增加索引
<doc>
<field name="id">1</field>
<field name="title">boco</field>
<field name="subject">boco</field>
<field name="description">boco</field>
<field name="text">boco</field>
</doc>
/opt/tomcat1/bin/startup.sh
/opt/tomcat2/bin/startup.sh
/opt/tomcat3/bin/startup.sh
(1)、_x.fdt
通常在搜索打分完毕后,IndexSearcher会返回一个docID序列,但是仅仅有docID我们是无法看到存储在索引中的document,这时候就需要通过docID来得到完整Document信息,这个过程就需要对fdx/fdt文件进行读操作。
fdx/fdt文件就是Lucene的正向文件。有一个比喻:如果fdt是一本书的正文,那么fdx则是书的目录。显然fdt文件大于fdx。
通过docID读取到document需要完成Segment、Block、Chunk、document四级查询。Segment、Block、Chunk的查找都是二分查找,速度很快,但是Chunk中定位document则是顺序查找,所以Chunk的大小直接影响着读取的性能。
fdt文件的基本单位是Chunk。
当你在程序中存储某个域时(使用Field.Store.YES选项),该域会被写入两个文件:.fdx与.fdt。
(2)、_x.fdx
fdx的基本单位是Block。一个Block由三个部分组成,fdx文件结构。最顶层的ChunkIndex跟倒数第三层的BlockCunks不是一个东西。
· BlockChunks表示当前Block中Chunk的个数;
· <DocBases>表示当前Block中每个Chunk的doc个数,可以看作一个数组;
· <StartPointers>表示当前Block中每个Chunk在fdt文件中的起始位置,其结构与<DocBases>相同。
(3)、_x.fnm
.fnm文件存储了段中相关文档的所有field信息。包括“该域是否被索引?该域是否允许使用项向量?”等。
此文件中的field不一定按字母顺序排列,每个field都有一个fieldNo编号,它会在其他索引文件中被用到,用来节省空间。
(4)、segments_x
x为IndexWriter的写入次数,从1开始计数。
(5)、.si是记录段文件的元数据的信息,主要有如下的几个属性
数据类型 描述
Header 记录一个头部编码,包含一个字符串去校验文件和版本号,它可以被解析和验证通过一个特定的方法,CodecHeader --> Magic,CodecName,Version Magic ->Uint32(32位无符号整数写成四个字节,高位字节),标识开始的头部CodecName->String 通过这个字符串校验文件Version ->Uint32(32位无符号整数写成四个字节,高位字节),记录文件的版本号
SegSize Int32
SegVersion String
Diagnostics, Attributes Map<String,String>
Files Set<String>
IsCompoundFile Int8
1,SegVersion段的版本号,是段文件创建时的编码版本。
2,SegSize是指包含在这个段文件里文档数(Document)的总数
3,IsCompoundFile记录着这个段在写入时,是否被作为一个复合索引文件,
如果是-1的话,则为正常的段索引文件,为1的话就是复合索引文件
4,Checksum,检验和,包含所有段文件中的所有字节的CRC32 checksum,
通常用于验证索引文件的完整性。
5,Diagnostics,诊断映射,它会私下被IndexWriter写入记录,作为一个Debug时的一个辅助工具,每个段文件都有一个对应的诊断映射,它包含一些元数据,包括一些lucene当前的版本号,操作系统,Java版本,以及它是怎么被创建的,是合并(merge),还是被刷新(flush),还是被多个索引合并(addindex)
6,Attributes,codec-private属性的键-值映射。
7,对于这个段来说,它被组成由多个文件
SegmentInfos这个类,几乎涵盖了段文件里所有的详细信息,提供了大量的方法用于在文件系统上操作段文件,segments_N往往是最活跃的文件,因为最新的段文件,常常面临着频繁的添加操作,这个文件包含了每个段的名字和细节编解码器和一些删除的元数据信息。
另外一个文件segments.gen,这个文件包含了以_N开头的在当前的段文件的记录,
这个文件仅仅作为一个备份,以防Directy不能准确的定位所写入的当前段文件是那一些以_N开头的,通常仅包含一个int32位的header信息。
文件:
segments.gen: GenHeader, Generation, Generation
segments_N: Header, Version, NameCounter, SegCount, <SegName, SegCodec, DelGen, DeletionCount, FieldInfosGen, UpdatesFiles>SegCount, CommitUserData, Checksum
数据类型:
Header---->CodecHeader
GenHeader, NameCounter, SegCount, DeletionCount --> Int32
Generation, Version, DelGen, Checksum, FieldInfosGen --> Int64
SegName, SegCodec --> String
CommitUserData --> Map<String,String>
UpdatesFiles --> Set<String>
介绍:
Version数量,记录着这个索引所有被添加或删除文档的个数。
NameCounter ,通常用于生成新的段文件名称
SegName ,段名称,通常被用于所有组成段文件的前缀名称
DelGen ,记录着所有段删除文件的数量,如果这个数是-1,则意味
着没有删除任何记录,除此之外,任何一个大于0的数字,则意味着
索引已经通过LiveDocsFormat进行了删除存储
DeletionCount,记录某一个段删除文档的数量
Checksum,校验和,上文有描述
SegCodec,是段文件的编码和解码后的名称
CommitUserData,用来提交一个用户提供不透明的Map结构的数据
FieldInfosGen ,域信息文件,记录段更新的次数,-1无更新,大于0的数字
则代表这更新的次数。
UpdatesFiles,存储在段过被更新过的文件。
hadoop dfs -copyToLocal /demo/data/index/segments_c .
hadoop fs -rm -r -skipTrash /demo/data/index
hadoop fs -rm -r -skipTrash /demo/data/tlog
segment_N文件存储的是当前正处于激活状态的索引文件的信息,也就是当前操作的索引文件的维护信息。 在这里N=3,N的最大值可以设定的,一般默认是10,就是说内存中到10个segment文件就合并一次。
索引merge的频率(mergeFactor),其实就是optimize,对索引和搜索都有影响,merge是把所有的段合并成一个,将需要删除或是被替换的索引标记为deleted,然后再创建新的文档替换掉需要被替换的,有点像整理磁盘碎片的动作,会创建一个全新的索引结构便于提高搜索的效率,mergeFactor设大索引效率高,搜索效率低,同时mergeFactor越大消耗的内存越多,所以需要综合考虑不同的场景的需求以及硬件设备环境来设定mergeFactor参数。