refer to 参考网址
How To
文章目录
- How To
- General recommendations(一般性建议)
- Recipes(秘诀)
- Tune for indexing speed(调整indexing速度)
- Use bulk requests
- Use multiple workers/threads to send data to Elasticsearch
- Increase the refresh interval
- Disable refresh and replicas for initial loads
- Disable swapping
- Give memory to the filesystem cache
- Use auto-generated ids
- Use faster hardware
- Indexing buffer size
- Disable `_field_names`
- Additional optimizations
- Tune for search speed(优化搜索速度)
- Give memory to the filesystem cache
- Use faster hardware
- Document modeling
- Search as few fields as possible
- Pre-index data
- Consider mapping identifiers as keyword
- Avoid scripts
- Search rounded dates
- Force-merge read-only indices
- Warm up global ordinals(预热全局序数)
- Warm up the filesystem cache(预热文件系统缓存)
- Use index sorting to speed up conjunctions(使用索引排序加速连词)
- Use `preference` to optimize cache utilization(使用preference优化缓存利用率)
- Replicas might help with throughput, but not always(副本可能有助于提高吞吐量,但并不总是如此)
- Turn on adaptive replica selection
- Tune your queries with the Profile API
- Tune for disk usage
- Disable the features you do not need
- Don’t use default dynamic string mappings
- Watch your shard size
- Disable _all
- Disable _source
- Use best_compression
- Force Merge
- Shrink Index
- Use the smallest numeric type that is sufficient
- Use index sorting to colocate similar documents(使用索引排序将相似文档合并在一起)
- Put fields in the same order in documents(在文档中按相同顺序放置字段)
具有默认值的 Elasticsearch,旨在提供一个良好的箱外体验。全文搜索、高亮显示、聚合和索引都应该在没有用户改变任何东西的情况下工作。
然而,一旦您更好地理解了如何使用弹性搜索,就可以进行许多优化来提高用例的性能。
本节提供了关于哪些更改应该和不应该更改的指南。
General recommendations(一般性建议)
Don’t return large result sets(不要返回大结果集)
ElasticSearch被设计为一个搜索引擎,这使得它能够很好地返回与查询匹配的top文档。但是,对于属于数据库域的工作负载(例如检索与特定查询匹配的所有文档)来说,这样做并没有那么好。如果你需要这样做,一定要利用Scroll API。
Avoid large documents(避免大文档)
考虑到默认的http.max_content_length设置为100MB,Elasticsearch将拒绝对大于此设置的任何文档进行索引。您可能会决定增加特定的设置,但Lucene仍然有约2GB的限制。
即使不考虑硬限制,大型文档通常也不实用。大型文档对网络、内存使用和磁盘的压力更大,即使对于不请求_source的搜索请求也是如此,因为ElasticSearch在所有情况下都需要获取文档的_id,由于文件系统缓存的工作方式,对于大型文档来说,获取此字段的成本更大。索引该文档可以大量内存,该内存是文档原始大小的倍数。邻近搜索(短语查询)和高亮显示也变得更加昂贵,因为它们的成本直接取决于原始文档的大小。
有时重新考虑信息的单位应该是什么是有用的,例如,你想使书籍可搜索并不一定意味着文档应该由一整本书组成。最好使用章节甚至段落作为文档,然后在这些文档中有一个属性来标识它们属于哪本书。这不仅避免了大文档的问题,还使搜索体验更好。例如,如果用户搜索两个单词foo和bar,则不同章节之间的匹配可能非常差,而同一段落中的匹配可能很好。
Recipes(秘诀)
This section includes a few recipes to help with common problems:
- Mixing exact search with stemming
- Getting consistent scoring
Mixing exact search with stemming(混合精确搜索与词干分析)
在构建搜索应用程序时,词干分析通常是必需的,因为对于skiing查询来说,需要匹配包含ski或skis的文档。但如果用户想专门搜索skiing呢?这样做的典型方法是使用多字段,以便以两种不同的方式索引相同的内容:
PUT index
{
"settings": {
"analysis": {
"analyzer": {
"english_exact": {
"tokenizer": "standard",
"filter": [
"lowercase"
]
}
}
}
},
"mappings": {
"_doc": {
"properties": {
"body": {
"type": "text",
"analyzer": "english",
"fields": {
"exact": {
"type": "text",
"analyzer": "english_exact"
}
}
}
}
}
}
}
PUT index/_doc/1
{
"body": "Ski resort"
}
PUT index/_doc/2
{
"body": "A pair of skis"
}
POST index/_refresh
在这样的设置下,搜索Ski在body字段将返回两个文档:
GET index/_search
{
"query": {
"simple_query_string": {
"fields": [ "body" ],
"query": "ski"
}
}
}
或
curl -X GET "localhost:9200/index/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"simple_query_string": {
"fields": [ "body" ],
"query": "ski"
}
}
}'
另一方面,在body.exact上搜索ski只会返回文档1,因为body.exact的分析链不执行词干分析。
GET index/_search
{
"query": {
"simple_query_string": {
"fields": [ "body.exact" ],
"query": "ski"
}
}
}
或
curl -X GET "localhost:9200/index/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"simple_query_string": {
"fields": [ "body.exact" ],
"query": "ski"
}
}
}'
这不是一件容易向最终用户公开的事情,因为我们需要有一种方法来确定他们是否在寻找一个完全匹配的,并相应地重定向到适当的字段。另外,如果只有部分查询需要精确匹配,而其他部分仍应考虑词干,该怎么办?
幸运的是,query_string和simple_query_string查询有一个解决这个问题的特性:quote_field_suffix。这将告诉elasticsearch,出现在引号之间的单词将被重定向到其他字段,请参见以下内容:
GET index/_search
{
"query": {
"simple_query_string": {
"fields": [ "body" ],
"quote_field_suffix": ".exact",
"query": "\"ski\""
}
}
}
或
curl -X GET "localhost:9200/index/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"simple_query_string": {
"fields": [ "body" ],
"quote_field_suffix": ".exact",
"query": "\"ski\""
}
}
}'
在上面的例子中,由于ski位于引号之间,所以它是在body.exact字段上搜索的,这是由于quote-field-suffix参数造成的,因此只匹配了document1。这允许用户根据自己的喜好将精确搜索和词干搜索混合起来。
Getting consistent scoring(获得一致评分)
ElasticSearch使用shards和replicas,这一事实在获得稳定评分方面增加了挑战。
Scores are not reproducible(评分不可复现)
假设同一个用户连续运行同一个请求两次,并且文档不会以相同的顺序返回两次,这是一个相当糟糕的体验,不是吗?不幸的是,如果您有副本(index.number_of_replicas大于0),则可能会发生这种情况。原因是elasticsearch以循环方式选择查询应该转到的碎片,因此如果连续运行同一个查询两次,则很可能会转到同一碎片的不同副本。
为什么会有问题?索引统计是得分的重要组成部分,由于文档被删除,这些索引统计在同一个shard的副本中可能会有所不同。正如您可能知道的,当文档被删除或更新时,旧文档不会立即从索引中删除,它只是被标记为已删除,并且只有在下次合并此旧文档所属的段时才会从磁盘中删除。但出于实际原因,索引统计时会考虑那些已删除的文档。因此,假设主碎片刚刚完成了一次大合并,删除了大量已删除的文档,那么它可能具有与副本(仍有大量已删除文档)完全不同的索引统计信息,因此得分也不同。
解决此问题的建议方法是使用一个字符串来标识记录的用户(例如用户id或会话id)作为首选项。这确保了给定用户的所有查询总是会命中相同的碎片,因此在查询中分数保持更一致。
这种解决方法还有另一个好处:当两个文档具有相同的分数时,默认情况下它们将按其内部lucene doc id(与id或uid无关)进行排序。但是,这些doc id在同一个shard的副本中可能不同。因此,通过始终命中相同的碎片,我们将获得具有相同分数的文档的更一致的顺序。
Relevancy looks wrong(相关度看起来不对)
如果您注意到具有相同内容的两个文档得到不同的分数,或者一个完全匹配的文档没有排在第一位,那么问题可能与分片有关。默认情况下,elasticsearch会让每个碎片负责生成自己的分数。然而,由于索引统计是得分的一个重要贡献者,因此只有碎片具有相似的索引统计时,这才起作用。假设由于默认情况下文档被均匀地路由到碎片,那么索引统计信息应该非常相似,并且评分将按预期工作。但是,如果您:
- 在索引时使用路由
- 查询多个索引
- 或者索引中的数据太少
然后很有可能搜索请求中涉及的所有碎片都没有类似的索引统计信息,相关性可能很差。
如果您有一个小数据集,解决此问题的最简单方法是将所有内容索引到一个具有单个碎片的索引中(index.number_of_shard:1)。然后所有文档的索引统计都将是相同的,并且分数将是一致的。
否则,解决此问题的建议方法是使用dfs_query_then_fetch搜索类型。这将使elasticsearch对所有涉及的shard执行一次初始往返,询问它们相对于查询的索引统计信息,然后协调节点在要求shard执行查询阶段时合并这些统计信息并将合并后的统计信息与请求一起发送,因此碎片可以使用这些全局统计数据而不是自己的统计数据来进行评分。
在大多数情况下,这种额外的往返旅行应该非常便宜。但是,如果查询包含大量field/term或 fuzzy queries,请注意,单独收集统计信息可能并不便宜,因为为了查找统计信息,必须在term词典中查找所有term。
Tune for indexing speed(调整indexing速度)
Use bulk requests
批量请求将产生比单个文档索引请求更好的性能。为了知道批量请求的最佳大小,您应该在具有单个碎片的单个节点上运行基准测试。首先尝试一次索引100个文档,然后是200个,然后是400个,等等。在每次基准测试运行中,成倍增加批量请求中的文档数量。当索引速度开始趋于平稳时,您就知道您达到了对数据的批量请求的最佳大小。在同样情况下最好是较少的文档而不是较多的文档。请注意,太大的 bulk requests同时发送时,可能会给集群带来内存压力,因此建议避免每个请求超过几十兆字节,即使较大的请求看起来性能更好。
Use multiple workers/threads to send data to Elasticsearch
发送批量请求的单个线程不太可能最大化 Elasticsearch 集群的索引能力。为了使用集群的所有资源,您应该从多个线程或进程发送数据。除了更好地利用集群的资源外,这应该有助于降低每个fsync的成本。
一定要注意TOO_MANY_REQUESTS
(429)响应代码(Java客户端EsRejectedExecutionException
异常),这是Elasticsearch告诉你无法跟上当前索引速率的方式。当它发生时,你应该暂停索引一会儿,然后再尝试,理想的是随机指数退避。
与调整批量请求大小类似,只有测试才能确定最佳工作线程数。这可以通过逐步增加工人数量来测试,直到集群上的I/O或CPU饱和。
Increase the refresh interval
默认index.refresh_interval值为1s,这会强制Elasticsearch每秒创建一个新段。增大此值(例如30s)将允许较大的段冲洗并降低将来的合并压力。
Disable refresh and replicas for initial loads
如果您需要一次加载大量数据,则应通过设置index.refresh_interval为-1和index.number_of_replicas为0 来禁用刷新。这将使索引暂时处于危险之中,因为任何分片的丢失都会导致数据丢失,但是同时索引会更快,因为文档只会被索引一次。初始加载完成后,您可以设置index.refresh_interval并index.number_of_replicas返回其原始值。
Disable swapping
您应该通过disabling swapping
来确保操作系统没有换出Java进程。
Give memory to the filesystem cache
文件系统缓存将用于 Buffer I / O操作。您应确保至少将运行Elasticsearch的计算机的一半内存分配给文件系统缓存。
Use auto-generated ids
为具有显式ID的文档建立索引时,Elasticsearch需要检查具有相同ID的文档是否已存在于同一分片中,这是一项昂贵的操作,并且随着索引数据量的增长而变得更加昂贵。通过使用自动生成的ID,Elasticsearch可以跳过此检查,这使索引更快。
Use faster hardware
如果索引是受I / O约束的,则应研究为文件系统高速缓存提供更多内存(请参见上文)或购买速度更快的驱动器。特别是,已知SSD驱动器的性能要比旋转磁盘好。最好使用本地存储,例如NFS或SMB的远程文件系统应该避免使用。还要注意虚拟存储,例如Amazon的Elastic Block Storage
。虚拟存储上运行的Elasticsearch也可以很好地工作,并且很有吸引力,因为它安装起来如此之快且简单,但是与专用本地存储相比,本质上在持续运行方面还很慢。如果您在EBS上存储索引数据 ,请确保使用预配置的IOPS,否则操作可能会很快受到限制。
通过配置RAID 0阵列,跨多个SSD划分索引。请记住,由于任何一个SSD的故障都会破坏索引,因此会增加故障的风险。但这通常是正确的权衡:优化单个分片以实现最佳性能,然后在不同节点之间添加副本,以便为任何节点故障提供冗余。您还可以使用快照和备份索引防范风险。
Indexing buffer size
如果您的节点只做繁重的索引,请确保indices.memory.index_buffer_size
足够大,最多可以给每个shard提供512 MB索引缓冲区,从而进行繁重的索引(超出索引性能通常不会改善)。Elasticsearch接受该设置(占Java堆的百分比或绝对字节大小),并将其用作所有活动分片上的共享缓冲区。非常活跃的分片自然会比执行轻量级索引的分片更多地使用此缓冲区。
默认值10%通常足够大:例如,如果给JVM 10GB的内存,它将为索引缓冲区提供1GB的内存,这足以容纳两个大量建立索引的分片。
Disable _field_names
该_field_names
字段引入了一些索引时间开销,如果您永远不需要运行exists查询,则可以禁用它。
Additional optimizations
Tune中概述的许多磁盘使用策略也可以提高索引速度。
Tune for search speed(优化搜索速度)
Give memory to the filesystem cache
Elasticsearch严重依赖于文件系统缓存,以加快搜索速度。通常,您应确保至少有一半的可用内存分配给文件系统缓存,以便Elasticsearch可以将索引的热区保留在物理内存中。
Use faster hardware
如果您的搜索受I / O限制,则应该为文件系统缓存提供更多内存(请参见上文)或购买速度更快的驱动器。特别是,已知SSD驱动器的性能要比旋转磁盘好。最好使用本地存储,例如NFS或SMB的远程文件系统应该避免使用。。还要注意虚拟存储,例如Amazon的Elastic Block Storage
。虚拟存储上运行的Elasticsearch也可以很好地工作,并且很有吸引力,因为它安装起来如此之快且简单,但是与专用本地存储相比,本质上在持续运行方面还很慢。如果您在EBS上存储索引数据 ,请确保使用预配置的IOPS,否则操作可能会很快受到限制。
如果搜索是受CPU限制的,则应研究购买速度更快的CPU。
Document modeling
文档应建模,以使搜索时操作尽可能便宜。
特别是,joins应避免。nested会使查询变慢几倍,而父子关系会使查询变慢数百倍。因此,如果可以通过对文档非规范化来解决的问题,不要采用joins的操作问题,则可以大大提高速度。
Search as few fields as possible
query_string或 multi_match查询目标的字段越多,它的速度就越慢。提高多个字段搜索速度的常用技术是在索引时间将其值复制到单个字段中,然后在搜索时使用此字段。这可以通过copy-to映射指令自动执行,而不必更改文档的来源。这是一个包含电影的索引的示例,该索引通过将两个值都索引到name_and_plot 字段中来优化对电影的名称和情节进行搜索的查询。
PUT movies
{
"mappings": {
"_doc": {
"properties": {
"name_and_plot": {
"type": "text"
},
"name": {
"type": "text",
"copy_to": "name_and_plot"
},
"plot": {
"type": "text",
"copy_to": "name_and_plot"
}
}
}
}
}
Pre-index data
您应该在查询中利用模式来优化索引数据的方式。例如,如果您所有的文档都有一个price字段,并且大多数查询range在固定的范围列表上运行 聚合,则可以通过将范围预索引到索引中并使用terms 聚合来使此聚合更快。
例如,如果文档看起来像:
PUT index/_doc/1
{
"designation": "spoon",
"price": 13
}
搜索请求如下所示:
GET index/_search
{
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 10 },
{ "from": 10, "to": 100 },
{ "from": 100 }
]
}
}
}
}
然后可以price_range在索引时间通过一个字段来丰富文档,该字段应映射为keyword:
PUT index
{
"mappings": {
"_doc": {
"properties": {
"price_range": {
"type": "keyword"
}
}
}
}
}
PUT index/_doc/1
{
"designation": "spoon",
"price": 13,
"price_range": "10-100"
}
然后搜索请求可以聚合该新字段,而不是对该字段运行 range聚合price。
GET index/_search
{
"aggs": {
"price_ranges": {
"terms": {
"field": "price_range"
}
}
}
}
Consider mapping identifiers as keyword
一些数据是数字的这一事实并不意味着它应该始终映射为数字字段。ElasticSearch索引数字的方式可以优化range查询,而keyword字段在term查询方面更好。通常,存储标识符(如ISBN)的字段或另一个数据库标识记录的任何数字字段很少用于范围查询或聚合。这就是为什么将它们映射为关键字而不是整数或长的原因。
Avoid scripts
通常,应避免使用脚本。如果绝对需要它们,则应首选painless和expressions引擎。
Search rounded dates
对日期字段的查询使用now通常不可缓存,因为匹配的范围一直在变化。但是,就用户体验而言,切换到舍入日期通常是可以接受的,并且具有更好地利用查询缓存的好处。
例如下面的查询:
PUT index/_doc/1
{
"my_date": "2016-05-11T16:30:55.328Z"
}
GET index/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"my_date": {
"gte": "now-1h",
"lte": "now"
}
}
}
}
}
}
可以替换为以下查询
GET index/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"my_date": {
"gte": "now-1h/m",
"lte": "now/m"
}
}
}
}
}
}
在这种情况下,我们四舍五入为分钟,因此,如果当前时间为16:31:29,则范围查询将匹配my_date字段值介于15:31:00和之间的所有内容16:31:59。而且,如果多个用户在同一分钟内运行包含此范围的查询,则查询缓存可以帮助加快速度。用于舍入的时间间隔越长,查询缓存可以提供的帮助越多,但是请注意,过于激进的舍入也会损害用户体验。
note:
可能很想将范围划分为较大的可缓存部分和较小的不可缓存部分,以便能够利用查询缓存,如下所示:
GET index/_search
{
"query": {
"constant_score": {
"filter": {
"bool": {
"should": [
{
"range": {
"my_date": {
"gte": "now-1h",
"lte": "now-1h/m"
}
}
},
{
"range": {
"my_date": {
"gt": "now-1h/m",
"lt": "now/m"
}
}
},
{
"range": {
"my_date": {
"gte": "now/m",
"lte": "now"
}
}
}
]
}
}
}
}
}
然而,在某些情况下,这种做法可能会使查询运行得更慢,因为bool查询引入的开销可能会破坏利用查询缓存带来的节省。
Force-merge read-only indices
只读的索引将从合并到单个段中受益 。这通常是基于时间索引的情况:只为当前时间的索引得到新的文件,而旧索引是只读的。
note:不要强行合并仍在写入的索引,而是将其合并到后台合并过程中。
Warm up global ordinals(预热全局序数)
全局序数是一种数据结构,用于在keyword字段上运行 terms聚合 。它们被延迟加载到内存中,因为Elasticsearch不知道terms聚合中将使用哪些字段,不使用那些字段。您可以通过如下所述配置映射,让Elasticsearch在refresh-time时紧急加载全局序言:
PUT index
{
"mappings": {
"_doc": {
"properties": {
"foo": {
"type": "keyword",
"eager_global_ordinals": true
}
}
}
}
}
Warm up the filesystem cache(预热文件系统缓存)
如果重新启动运行Elasticsearch的计算机,则文件系统缓存将为空,因此,操作系统需要一些时间才能将索引的热区加载到内存中,以便快速进行搜索操作。您可以使用index.store.preload 设置,通过配置文件扩展名明确告诉操作系统哪些文件应该急切地加载到内存中。
warning:如果文件系统高速缓存的大小不足以容纳所有数据,则将索引过多或文件过多的数据急切地加载到文件系统高速缓存中,会使搜索速度变慢。请谨慎使用。
Use index sorting to speed up conjunctions(使用索引排序加速连词)
索引排序可能有用,以便使连接更快,但以稍微慢一些的索引为代价。在索引排序文档中阅读有关它的更多信息。
Use preference
to optimize cache utilization(使用preference优化缓存利用率)
有多个缓存可以帮助提高搜索性能,例如filesystem cache、equest cache或query cache。然而,所有这些缓存都在节点级维护,这意味着如果连续运行同一个请求两次,有一个或多个副本,并使用默认路由算法round robin,那么这两个请求将转到不同的碎片副本,从而阻止节点级缓存提供帮助。
由于搜索应用程序的用户通常会相继运行类似的请求,例如,为了分析索引的较窄子集,使用标识当前用户或会话的首选项值可以帮助优化缓存的使用。
Replicas might help with throughput, but not always(副本可能有助于提高吞吐量,但并不总是如此)
除了提高弹性之外,Replicas还可以帮助提高吞吐量。例如,如果您有一个单碎片索引和三个节点,则需要将Replicas数设置为2,以便总共拥有3个shard Replicas,以便利用所有节点。
现在,假设您有一个2个shard的索引和两个节点。在一种情况下,副本数为0,这意味着每个节点都拥有一个分片。在第二种情况下,副本数为1,这意味着每个节点都有两个分片。哪种设置在搜索效果方面效果最好?通常,每个节点的分片总数较少的设置会更好地执行。这样做的原因是,它为每个分片提供了更多的可用文件系统缓存份额,并且文件系统缓存可能是Elasticsearch的第一性能因素。同时,请注意,在单节点故障的情况下,没有副本的安装会失败,因此在吞吐量和可用性之间要进行权衡。
那么正确的副本数是多少?如果您的集群中有num_nodes节点,则总共有 num_primaries主要分片,并且如果您希望max_failures一次最多能处理节点故障,那么适合您的副本数是 max(max_failures, ceil(num_nodes / num_primaries) - 1)。
ceil:取整函数,Number向上舍入,沿绝对值增大的方向
Turn on adaptive replica selection
当存在多个数据副本时,elasticsearch可以使用一组称为自适应副本选择的条件来根据响应时间,服务时间和包含每个碎片副本的节点的队列大小来选择最佳数据副本。这可以提高查询吞吐量并减少大量搜索应用程序的延迟。
Tune your queries with the Profile API
Tune your queries with the Profile API
您还可以使用Profile API分析查询和聚合的每个组件的成本。这可能使您可以将查询调整为便宜些,从而获得积极的性能结果并减少负载。还要注意,可以在Search Profiler中轻松查看Profile API的有效载荷,以提高可读性, Search Profiler是所有X-Pack许可证(包括免费的X-Pack Basic许可证)中均可使用的Kibana开发工具UI。
对Profile API的一些警告是:
- Profile API作为调试工具增加了搜索执行的大量开销,并且还可能产生非常冗长的输出
- 考虑到额外的开销,所产生的花费时间不是实际花费时间的可靠指标,但是可以在子句之间进行比较以获取相对时间差异
- Profile API最适合于探索查询中最昂贵的子句背后的可能原因,但并非旨在准确地衡量每个子句的绝对时间
Tune for disk usage
Disable the features you do not need
默认情况下,Elasticsearch为大多数字段编入索引并将doc值添加到大多数字段,以便可以立即搜索和汇总它们。例如,如果您有一个数字字段foo,需要运行直方图,而不必进行过滤,则可以安全地在映射中禁用对此字段的索引 :
PUT index
{
"mappings": {
"_doc": {
"properties": {
"foo": {
"type": "integer",
"index": false
}
}
}
}
}
text字段在索引中存储归一化因子,以便能够对文档进行评分。如果您只需要text 字段上的匹配功能但不关心产生的分数,则可以配置Elasticsearch不将norms写入索引:
PUT index
{
"mappings": {
"_doc": {
"properties": {
"foo": {
"type": "text",
"norms": false
}
}
}
}
}
text默认情况下,字段还会在索引中存储frequencies和positions。Frequencies用于计算分数,positions用于运行phrase queries。如果您不需要运行短语查询,可以告诉Elasticsearch不要索引positions:
PUT index
{
"mappings": {
"_doc": {
"properties": {
"foo": {
"type": "text",
"index_options": "freqs"
}
}
}
}
}
此外,如果您既不计分,也可以将Elasticsearch配置为仅对每个term的匹配文档编制索引。您仍然可以在此字段上进行搜索,但是phrase queries将引发错误,并且评分将假定term在每个文档中仅出现一次。
PUT index
{
"mappings": {
"_doc": {
"properties": {
"foo": {
"type": "text",
"norms": false,
"index_options": "freqs"
}
}
}
}
}
Don’t use default dynamic string mappings
默认的dynamic string mappings将为string字段同时索引为text和keyword。如果您只需要其中之一,这很浪费。通常,一个id字段将只需要索引, keyword而一个body字段将只需要索引为text字段。
可以通过在字符串字段上配置显式映射或配置dynamic templates把string字段映射为text 或keyword,来避免这种情况。
例如,以下模板可用于仅将字符串字段映射为keyword:
PUT index
{
"mappings": {
"_doc": {
"dynamic_templates": [
{
"strings": {
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
}
]
}
}
}
Watch your shard size
较大的分片将在存储数据方面更加有效。要增加分片的大小,可以通过创建主分片较少的索引,创建更少的索引(例如,利用Rollover API)或使用Shrink API修改现有索引来减少索引中主分片的数量。
请记住,较大的分片大小会带来缺点,例如较长的完整恢复时间。
Disable _all
该_all字段索引文档的所有字段的值,并且可以使用大量空间。如果您永远不需要同时搜索所有字段,则可以将其禁用。
Disable _source
该_source字段存储文档的原始JSON主体。如果您不需要访问它,可以将其禁用。但是,需要访问_source的API(例如update 和 reindex)将无法使用。
Use best_compression
的_source和存储的字段可以很容易地占用大量的磁盘空间。使用best_compression codec可以更积极地压缩它们。
Force Merge
Elasticsearch中的索引存储在一个或多个shard中。每个shard都是一个Lucene索引,由一个或多个segments(磁盘上的实际文件)组成。较大的segments更有效地存储数据。
该_forcemergeAPI可用于减少每个shard的segments数。在许多情况下,可以通过设置将每个分片的段数减少到一个max_num_segments=1。
Shrink Index
使用Shrink API,您可以减少索引中的分片数量。与上面的Force Merge API一起使用,可以大大减少索引的分片和分段的数量。
Use the smallest numeric type that is sufficient
为数字字段选择的类型可能会对磁盘使用产生重大影响。特别是,应该整数使用整数型(存储byte,short,integer或long)和浮点要么被存储在一个scaled_float合适的话或适合用例最小的类型:在double上使用float,或在float上使用half_float有利于节省存储空间。
Use index sorting to colocate similar documents(使用索引排序将相似文档合并在一起)
当Elasticsearch存储时_source,它将一次压缩多个文档,以提高整体压缩率。例如,文档共享相同的字段名称是很常见的,而文档共享某些字段值是很常见的,尤其是在基数较低或zipfian分布的字段上。
默认情况下,文档按添加到索引的顺序压缩在一起。如果启用了index sorting , 则它们将按排序顺序进行压缩。将具有相似结构,字段和值的文档分类在一起可以提高压缩率。
Put fields in the same order in documents(在文档中按相同顺序放置字段)
由于多个文档被压缩在一起成为一个块,因此,_source如果字段始终以相同顺序出现,则更有可能在这些文档中找到更长的重复字符串。