感谢有奉献精神的人
转自:http://blog.csdn.net/yuxiang1014/article/details/39931635
运行solr是个很简单的事,如何让solr高效运行你的项目,这个就不容易了。
要考虑的因素太多。这里很重要一个就是对solr的配置要了解。懂得配置文件每个配置项的含义,这样操作起来就会如鱼得水!
在solr里面主要的就是solr的主目录下面的schema.xml,solrConfig.xml。
solrconfig.xml,主要定义solr的处理程序(handler)和一些扩展程序;
schema.xml,主要定义索引的字段和字段类型。
schema.xml,这个相当于数据表配置文件,它定义了加入索引的数据的数据类型的。
主要包括types、fields和其他的一些缺省设置。
注:schema.xml里有一个uniqueKey,的配置,这里将id字段作为索引文档的唯一标识符,非常重要。
<uniqueKey>id</uniqueKey>
首先需要在types结点内定义一个FieldType子结点,包括name,class,positionIncrementGap等等一些参数,name就是这个FieldType的名称,class指向org.apache.solr.analysis包里面对应的class名称,用来定义这个类型的行为。
在FieldType定义的时候,最重要的就是定义这个类型的数据在建立索引和进行查询的时候要使用的分析器analyzer,包括分词和过滤。
例如:
<fieldType name="text" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.WhitespaceTokenizerFactory"/>
<!-- in this example, we will only use synonyms at query time
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
-->
<!-- Case insensitive stop word removal.
enablePositionIncrements=true ensures that a 'gap' is left to
allow for accurate phrase queries.
-->
<filter class="solr.StopFilterFactory"
ignoreCase="true"
words="stopwords.txt"
enablePositionIncrements="true"
/>
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/>
<filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
</analyzer>
……
</fieldType>
在index的analyzer中使用 solr.WhitespaceTokenizerFactory这个分词包,就是空格分词。
然后使用 solr.StopFilterFactory,solr.WordDelimiterFilterFactory,solr.LowerCaseFilterFactory,solr.EnglishPorterFilterFactory,solr.RemoveDuplicatesTokenFilterFactory 这几个过滤器。
在向索引库中添加text类型的索引的时候,Solr会首先用空格进行分词,然后把分词结果依次使用指定的过滤器进行过滤,最后剩下的结果才会加入到索引库中以备查询。
Solr的analysis包并没有带支持中文分词的包。
接下来的工作就是在fields结点内定义具体的字段(类似数据库中的字段),就是filed。
filed定义包括name,type(为之前定义过的各种FieldType),indexed(是否被索引),stored(是否被储存),multiValued(是否有多个值)等等。
例:
<fields>
<field name="id" type="integer" indexed="true" stored="true" required="true" />
<field name="name" type="text" indexed="true" stored="true" />
<field name="summary" type="text" indexed="true" stored="true" />
<field name="author" type="string" indexed="true" stored="true" />
<field name="date" type="date" indexed="false" stored="true" />
<field name="content" type="text" indexed="true" stored="false" />
<field name="keywords" type="keyword_text" indexed="true" stored="false" multiValued="true" />
<field name="all" type="text" indexed="true" stored="false" multiValued="true"/>
</fields>
field的定义相当重要,有几个技巧需注意一下,对可能存在多值得字段尽量设置 multiValued属性为true,避免建索引是抛出错误;如果不需要存储相应字段值,尽量将stored属性设为false。
建议建立了一个拷贝字段,将所有的全文字段复制到一个字段中,以便进行统一的检索:
<field name="all" type="text" indexed="true" stored="false" multiValued="true"/>
并在拷贝字段结点处完成拷贝设置:
<copyField source="name" dest="all"/>
<copyField source="summary" dest="all"/>
注:“拷贝字段”就是查询的时候不用再输入:userName:张三 and userProfile:张三的个人简介。
直接可以输入"张三"就可以将“名字”含“张三”或者“简介”中含“张三”的又或者“名字”和“简介”都含有“张三”的查询出来。
他将需要查询的内容放在了一个字段中,并且默认查询该字段设为该字段就行了。
除此之外,还可以定义动态字段,所谓动态字段就是不用指定具体的名称,只要定义字段名称的规则。
例如定义一个 dynamicField,name 为*_i,定义它的type为text,那么在使用这个字段的时候,任何以_i结尾的字段都被认为是符合这个定义的,例如:name_i,gender_i,school_i等。
schema.xml配置文件大体上就是这样,更多细节请参见solr wiki:http://wiki.apache.org/solr/SchemaXml
在配置方面,solrconfig.xml 文件不仅指定了 Solr 如何处理索引、突出显示、分类、搜索以及其他请求,还指定了用于指定缓存的处理方法的属性,以及用于指定 Lucene 管理索引的方法的属性。
配置取决于模式,但模式不取决于配置。solrconfig.xml文件包含了大部分的参数用来配置Solr本身的。
<dataDir>/var/data/solr</dataDir>
用来指定一个替换原先在Solr目录下默认存放所有的索引数据,可以在Solr目录以外的任意目录中。
如果复制使用后应该符合该参数。如果这个目录不是绝对路径的话,那么应该以当前的容器为相对路径。
这个参数的值用来控制合并多个索引段。
<useCompoundFile>:通过将很多 Lucene 内部文件整合到单一一个文件来减少使用中的文件的数量。这可有助于减少 Solr 使用的文件句柄数目,代价是降低了性能。除非是应用程序用完了文件句柄,否则 false 的默认值应该就已经足够。
决定低水平的 Lucene 段被合并的频率。较小的值(最小为 2)使用的内存较少但导致的索引时间也更慢。
较大的值可使索引时间变快但会牺牲较多的内存。
在合并内存中文档和创建新段之前,定义所需索引的最小文档数。
段 是用来存储索引信息的 Lucene 文件。
较大的值可使索引时间变快但会牺牲较多的内存。
控制可由 Solr ,000) 最适合于具有合并的 Document 的最大数。
较小的值 (< 10大量更新的应用程序。
该参数不允许lucene在任何索引段里包含比这个值更多的文档,但是,多余的文档可以创建一个新的索引段进行替换。
对于给定的 Document,控制可添加到 Field 的最大条目数,进而截断该文档。
如果文档可能会很大,就需要增加这个数值。然而,若将这个值设置得过高会导致内存不足错误。
unlockOnStartup 告知 Solr 忽略在多线程环境中用来保护索引的锁定机制。
在某些情况下,索引可能会由于不正确的关机或其他错误而一直处于锁定,这就妨碍了添加和更新。
将其设置为 true 可以禁用启动锁定,进而允许进行添加和更新。
<mainIndex>
<!-- lucene options specific to the main on-disk lucene index -->
<useCompoundFile>false</useCompoundFile>
<mergeFactor>10</mergeFactor>
<maxBufferedDocs>1000</maxBufferedDocs>
<maxMergeDocs>2147483647</maxMergeDocs>
<maxFieldLength>10000</maxFieldLength>
</mainIndex>
这个更新处理器主要涉及底层的关于如何更新处理内部的信息。
(此参数不能跟高层次的配置参数Request Handlers对处理发自客户端的更新相混淆)。
<updateHandler class="solr.DirectUpdateHandler2">
<!-- Limit the number of deletions Solr will buffer during doc updating.
Setting this lower can help bound memory use during indexing.
-->
缓冲更新这么多的数目,设置如下比较低的值,可以约束索引时候所用的内存
<maxPendingDeletes>100000</maxPendingDeletes>
等待文档满足一定的标准后将自动提交,未来版本可以扩展现有的标准
<!-- autocommit pending docs if certain criteria are met. Future versions may expand the available
criteria -->
<autoCommit>
<maxDocs>10000</maxDocs> <!-- maximum uncommited docs before autocommit triggered -->
触发自动提交前最多可以等待提交的文档数量
<maxTime>86000</maxTime> <!-- maximum time (in MS) after adding a doc before an autocommit is triggered -->
在添加了一个文档之后,触发自动提交之前所最大的等待时间
</autoCommit>
这个参数用来配置执行外部的命令。
一个postCommit的事件被触发当每一个提交之后
<listener event="postCommit" class="solr.RunExecutableListener">
<str name="exe">snapshooter</str>
<str name="dir">solr/bin</str>
<bool name="wait">true</bool>
<!--
<arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
<arr name="env"> <str>MYVAR=val1</str> </arr>
-->
</listener>
exe--可执行的文件类型
dir--可以用该目录做为当前的工作目录。默认为"."
wait--调用线程要等到可执行的返回值
args--传递给程序的参数 默认nothing
env--环境变量的设置 默认nothing
<query>
<!-- Maximum number of clauses in a boolean query... can affect range
or wildcard queries that expand to big boolean queries.
一次布尔查询的最大数量,可以影响查询的范围或者进行通配符的查询,借此来扩展一个更强大的查询。
An exception is thrown if exceeded.
-->
<maxBooleanClauses>1024</maxBooleanClauses>
<query>:
控制跟查询相关的一切东东。
修改这个参数可以做为索引的增长和变化。
<!-- Cache used by SolrIndexSearcher for filters (DocSets),
unordered sets of *all* documents that match a query.
在过滤器中过滤文档集合的时候,或者是一个无序的所有的文档集合中将在在SolrIndexSearcher中使用缓存来匹配符合查询的所有文档。
When a new searcher is opened, its caches may be prepopulated
or "autowarmed" using data from caches in the old searcher.
当一次搜索被打开,它可以自动的或者预先从旧的搜索中使用缓存数据。
autowarmCount is the number of items to prepopulate.
autowarmCount这个值是预先设置的数值项。
For LRUCache,
the autowarmed items will be the most recently accessed items.
在LRUCache中,这个autowarmed 项中保存的是最近访问的项。
Parameters: 参数选项
class - the SolrCache implementation (currently only LRUCache)实现SolrCache接口的类 当前仅有LRUCache
size - the maximum number of entries in the cache
在cache中最大的上限值
initialSize - the initial capacity (number of entries) of
the cache. (seel java.util.HashMap)
在cache中初始化的数量
autowarmCount - the number of entries to prepopulate from
and old cache.
从旧的缓存中预先设置的项数。
-->
<filterCache
class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="256"/>
<!-- queryResultCache caches results of searches - ordered lists of
document ids (DocList) based on a query, a sort, and the range
of documents requested. -->
查询结果缓存
<queryResultCache
class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="256"/>
<!-- documentCache caches Lucene Document objects (the stored fields for each document).
documentCache缓存Lucene的文档对象(存储领域的每一个文件)
Since Lucene internal document ids are transient, this cache will not be autowarmed. -->
由于Lucene的内部文档ID标识(文档名称)是短暂的,所以这种缓存不会被自动warmed。
<documentCache
class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<!-- Example of a generic cache.
一个通用缓存的列子。
These caches may be accessed by name
through SolrIndexSearcher.getCache().cacheLookup(), and cacheInsert().
这些缓存可以通过在SolrIndexSearcher.getCache().cacheLookup()和cacheInsert()中利用缓存名称访问得到。
The purpose is to enable easy caching of user/application level data.
这样做的目的就是很方便的缓存用户级或应用程序级的数据。
The regenerator argument should be specified as an implementation
of solr.search.CacheRegenerator if autowarming is desired. -->
这么做的的关键就是应该明确规定实现solr.search.CacheRegenerator接口如果autowarming是比较理想化的设置。
<!--
<cache name="myUserCache"
class="solr.LRUCache"
size="4096"
initialSize="1024"
autowarmCount="1024"
regenerator="org.mycompany.mypackage.MyRegenerator"
/>
-->
<!-- An optimization that attempts to use a filter to satisfy a search.
一种优化方式就是利用一个过滤器,以满足搜索需求。
If the requested sort does not include a score,
如果请求的不是要求包括得分的类型,filterCache 这种过滤器将检查与过滤器相匹配的结果。如果找到,过滤器将被用来作为文档的来源识别码,并在这个基础上进行排序。
then the filterCache
will be checked for a filter matching the query. If found, the filter
will be used as the source of document ids, and then the sort will be
applied to that.
-->
<useFilterForSortedQuery>true</useFilterForSortedQuery>
<!-- An optimization for use with the queryResultCache. When a search
is requested, a superset of the requested number of document ids
are collected. For example, of a search for a particular query
requests matching documents 10 through 19, and queryWindowSize is 50,
then documents 0 through 50 will be collected and cached. Any further
requests in that range can be satisfied via the cache.
-->
一种优化用于queryResultCache,当一个搜索被请求,也会收集一定数量的文档ID做为一个超集。举个例子,一个特定的查询请求匹配的文档是10到19,此时,queryWindowSize是50,这样,文档从0到50都会被收集并缓存。这样,任何更多的在这个范围内的请求都会通过缓存来满足查询。
<queryResultWindowSize>50</queryResultWindowSize>
<!-- This entry enables an int hash representation for filters (DocSets)
when the number of items in the set is less than maxSize. For smaller
sets, this representation is more memory efficient, more efficient to
iterate over, and faster to take intersections.
-->
<HashDocSet maxSize="3000" loadFactor="0.75"/>
<!-- boolToFilterOptimizer converts boolean clauses with zero boost
cached filters if the number of docs selected by the clause exceeds the
threshold (represented as a fraction of the total index)
-->
<boolTofilterOptimizer enabled="true" cacheSize="32" threshold=".05"/>
<!-- Lazy field loading will attempt to read only parts of documents on disk that are
requested. Enabling should be faster if you aren't retrieving all stored fields.
-->
<enableLazyFieldLoading>false</enableLazyFieldLoading>