索引段和合并
Lucene 索引存储在段中,Solr 提供了几个参数来控制如何编写新段以及何时合并段。
Lucene 索引是“一次性写入”文件:一旦一个段被写入永久存储(磁盘),它将永远不会被更改。这意味着索引实际上由几个文件组成,每个文件都是完整索引的子集。为了防止索引的永久碎片化,段会定期合并。
solrconfig.xml 中的 <indexConfig>
solrconfig.xml
中的 <indexConfig>
部分定义了 Lucene 索引编写器的底层行为。
默认情况下,Solr 附带的示例 solrconfig.xml
中的设置已注释掉,这意味着使用了默认值。在大多数情况下,默认值都是可以的。
<indexConfig>
...
</indexConfig>
写入新段
以下元素可以在 <indexConfig>
元素下定义,并定义何时将新段写入(“刷新”)到磁盘。
ramBufferSizeMB
一旦累积的文档更新超过此内存空间(以兆字节为单位),则会刷新待处理的更新。这还可以创建新段或触发合并。通常,使用此设置优于 maxBufferedDocs
。如果在 solrconfig.xml
中同时设置了 maxBufferedDocs
和 ramBufferSizeMB
,那么当达到任一限制时,都会发生刷新。默认值为 100
MB。
<ramBufferSizeMB>100</ramBufferSizeMB>
合并索引段
以下设置定义了合并段的时间。
mergePolicyFactory
定义合并段的方式。
Solr 中的默认设置是使用 `TieredMergePolicy`,该策略合并大小大致相等的段,但每个层级允许的段数有限。
其他可用的策略包括 `LogByteSizeMergePolicy` 和 `LogDocMergePolicy`。有关这些策略的更多信息,请参阅 MergePolicy javadocs。
<mergePolicyFactory class="org.apache.solr.index.TieredMergePolicyFactory">
<int name="maxMergeAtOnce">10</int>
<int name="segmentsPerTier">10</int>
<double name="forceMergeDeletesPctAllowed">10.0</double>
<double name="deletesPctAllowed">33.0</double>
</mergePolicyFactory>
控制段大小
用户对 `TieredMergePolicy`(或 `LogByteSizeMergePolicy`)配置进行的最常见调整是“合并因子”,用于更改一次合并的段数,以及在 `TieredMergePolicy` 的情况下,合并段的最大大小。
对于 `TieredMergePolicy`,可以通过设置 `maxMergeAtOnce`(默认值为 `10`)、`segmentsPerTier`(默认值为 `10`)和 `maxMergedSegmentMB`(默认值为 `5000`)选项来控制。
LogByteSizeMergePolicy
有一个 `mergeFactor` 选项(默认值为 `10`)。
要了解这些选项为何重要,请考虑使用 `LogByteSizeMergePolicy` 对索引进行更新时会发生什么情况:文档始终添加到最近打开的段中。当一个段填满时,将创建一个新段,后续更新将放置在那里。
如果创建新段会导致最低级别段的数量超过 `mergeFactor` 值,那么所有这些段将合并在一起以形成一个大段。因此,如果合并因子为 `10`,则每次合并都会创建一个大段,该大段大约是其十个组成部分的十倍。当有 10 个这样的较大段时,它们又会合并成一个更大的单段。此过程可以无限期地继续下去。
使用 `TieredMergePolicy` 时,该过程是相同的,但不是使用单个 `mergeFactor` 值,而是使用 `segmentsPerTier` 设置作为决定是否应进行合并的阈值,而 `maxMergeAtOnce` 设置确定应在合并中包含多少个段。
选择最佳合并因子通常是索引速度与搜索速度之间的权衡。索引中段越少,搜索速度通常越快,因为需要查找的地方越少。它还可以减少磁盘上的物理文件数量。但为了保持段数较低,合并会更频繁地发生,这会增加系统负载并减慢对索引的更新速度。
相反,保留更多段可以加速索引,因为合并发生的频率较低,更新不太可能触发合并。但搜索在计算上会变得更加昂贵,并且可能会更慢,因为必须在更多索引段中查找搜索词。更快的索引更新还意味着更短的提交周转时间,这意味着更及时的搜索结果。
控制已删除文档的百分比
当文档被删除或更新时,文档会被标记为已删除,但直到该段合并后才会从索引中删除。使用默认的 TieredMergePolicy
时,有两个参数可以调整,它们会影响索引中已删除文档的数量。
forceMergeDeletesPctAllowed
-
可选
默认值:
10.0
当发出外部
expungeDeletes
命令时,任何已删除文档超过此百分比的段都将合并到一个新段中,并且与已删除文档关联的数据将被清除。0.0
的值将使 expungeDeletes 的行为与optimize
基本相同。 deletesPctAllowed
-
可选
默认值:
33.0
在正常段合并期间,尽最大努力确保索引中已删除文档的总百分比低于此阈值。有效设置在 20% 到 50% 之间。选择 33% 作为默认值,因为当此设置接近 20% 时,系统负载会大幅增加。
自定义合并策略
如果内置合并策略的配置选项不能完全满足你的用例,你可以通过创建自定义合并策略工厂(在配置中指定)或配置合并策略包装器(使用 wrapped.prefix
配置选项来控制它所包装的工厂将如何配置)来对其进行自定义
<mergePolicyFactory class="org.apache.solr.index.SortingMergePolicyFactory">
<str name="sort">timestamp desc</str>
<str name="wrapped.prefix">inner</str>
<str name="inner.class">org.apache.solr.index.TieredMergePolicyFactory</str>
<int name="inner.maxMergeAtOnce">10</int>
<int name="inner.segmentsPerTier">10</int>
</mergePolicyFactory>
上面的示例显示了 Solr 的SortingMergePolicyFactory
被配置为按"timestamp desc"
对合并段中的文档进行排序,并包装在TieredMergePolicyFactory
周围,该工厂配置为通过SortingMergePolicyFactory
的wrapped.prefix
选项定义的inner
前缀使用值maxMergeAtOnce=10
和segmentsPerTier=10
。有关使用SortingMergePolicyFactory
的更多信息,请参阅segmentTerminateEarly 参数。
mergeScheduler
合并调度器控制合并如何执行。默认的ConcurrentMergeScheduler
使用单独的线程在后台执行合并。备选方案SerialMergeScheduler
不使用单独的线程执行合并。
ConcurrentMergeScheduler
具有以下可配置属性。这些属性的默认值会根据底层磁盘驱动器是否为旋转磁盘而动态设置。有关更多详细信息,请参阅ConcurrentMergeScheduler 的动态默认值。
maxMergeCount
-
可选
默认值:无
允许的最大同时合并数。如果需要合并,但我们已经运行了这么多线程,则索引线程将阻塞,直到合并线程完成。请注意,Solr 一次只会运行最小的
maxThreadCount
合并。 maxThreadCount
-
可选
默认值:无
应该同时运行的最大同时合并线程数。这必须小于
maxMergeCount
。 ioThrottle
-
可选
默认值:无
布尔值(
true
或false
)用于显式控制 I/O 限制。默认情况下,启用限制,CMS 将在合并时限制 I/O 吞吐量,以便为其他(搜索、索引)留出一些空间。
<mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
<mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler">
<int name="maxMergeCount">9</int>
<int name="maxThreadCount">4</int>
</mergeScheduler>
mergedSegmentWarmer
在将 Solr 用于近实时用例时,可以在合并提交之前配置合并段预热器以预热新合并段上的读取器。这对于近实时搜索不是必需的,但将在合并完成后打开新的近实时读取器时减少搜索延迟。
<mergedSegmentWarmer class="org.apache.lucene.index.SimpleMergedSegmentWarmer"/>
复合文件段
每个 Lucene 段通常由十几或更多个文件组成。Solr 可配置为使用文件扩展名 .cfs
(代表“复合文件段”)将 Lucene 段的所有文件捆绑到单个复合文件中。
CFS 段可能会因各种原因而导致轻微的性能下降,具体取决于运行时环境。例如,文件系统缓冲区通常与打开的文件描述符相关联,这可能会限制每个索引可用的总缓存空间。
在允许每个进程打开的文件数量有限的系统上,CFS 可以避免达到该限制。还可以使用 Linux/Unix ulimit
命令或其他操作系统的类似命令调整操作系统的打开文件限制。
CFS:新段与合并段
要配置是否应为新写入的段使用 CFS,请参见上面描述的 许多 合并策略 实现都支持 |
段信息屏幕
管理 UI 中的段信息屏幕可让你查看此核心底层 Lucene 索引中各个段的可视化,其中包括每个段的大小信息(以字节和文档数表示)以及有关这些段的其他基本元数据。最明显的是已删除文档的数量,但你可以将鼠标悬停在段上以查看其他数字详细信息。
此信息可能对人们做出有关其数据最优 合并设置 的决策有所帮助。
索引锁
lockType
LockFactory 选项指定要使用的锁定实现。
有效的锁定类型选项集取决于你已配置的 DirectoryFactory。
以下列出的值受 StandardDirectoryFactory
(默认值)支持
-
native
(默认)使用NativeFSLockFactory
指定本机操作系统文件锁定。如果第二个 Solr 进程尝试访问该目录,它将失败。当多个 Solr Web 应用程序尝试共享单个索引时,请勿使用。另请参阅 NativeFSLockFactory javadoc。 -
simple
使用SimpleFSLockFactory
指定用于锁定的普通文件。另请参阅 SimpleFSLockFactory javadoc。 -
single
(专家)使用SingleInstanceLockFactory
。适用于只读索引目录的特殊情况,或者当不可能有多个进程尝试修改索引(即使是按顺序)时。此类型将防止同一 JVM 内的多个内核尝试访问同一索引。如果不同 JVM 中的多个 Solr 实例修改索引,此类型不会防止索引损坏。 -
hdfs
使用HdfsLockFactory
支持将索引和事务日志文件读写到 HDFS 文件系统。有关使用此功能的更多详细信息,请参阅 Solr on HDFS 部分。
<lockType>native</lockType>
其他索引设置
还有一些其他参数可能对您的实现配置很重要。这些设置会影响对索引进行更新的方式或时间。
deletionPolicy
控制在回滚的情况下如何保留提交。默认值为 SolrDeletionPolicy
,它采用以下参数
maxCommitsToKeep
-
可选
默认值:无
要保留的最大提交数。
maxOptimizedCommitsToKeep
-
可选
默认值:无
要保留的最大优化提交数。
maxCommitAge
-
可选
默认值:无
要保留的任何提交的最大年龄。这支持
DateMathParser
语法。
<deletionPolicy class="solr.SolrDeletionPolicy">
<str name="maxCommitsToKeep">1</str>
<str name="maxOptimizedCommitsToKeep">0</str>
<str name="maxCommitAge">1DAY</str>
</deletionPolicy>