开源Elasticsearch FAQ

更新时间:
复制 MD 格式

本文列举了一些开源Elasticsearch(ES)相关的常见问题,例如,如何配置索引线程池大小,如何重新分配索引分片,如何批量删除索引等。

常见问题概览

如何配置索引线程池大小?

YML参数配置中,指定thread_pool.write.queue_size参数的大小即可。具体操作步骤,请参见配置YML参数配置线程池大小

重要

对于6.x以下版本的Elasticsearch集群,需要使用thread_pool.index.queue_size参数。

出现内存溢出OOM(OutOfMemory)的错误,如何处理?

通过以下命令清理缓存,然后观察具体原因,根据原因升配集群或调整业务。

curl -u elastic:<password> -XPOST "localhost:9200/<index_name>/_cache/clear?pretty"

变量名

说明

<password>

阿里云Elasticsearch实例的密码,为您在创建Elasticsearch实例时设置的密码,或初始化Kibana时指定的密码。

<index_name>

索引名称。

如何手动对shard进行操作?

使用reroute API,或通过Cerebro进行操作。具体操作步骤,请参见Cluster reroute APICerebro

Elasticsearch的缓存清除策略有哪些?

Elasticsearch支持以下三种缓存清除策略:

  • 清除全部缓存

    curl localhost:9200/_cache/clear?pretty
  • 清除单一索引缓存

    curl localhost:9200/<index_name>/_cache/clear?pretty
  • 清除多索引缓存

    curl localhost:9200/<index_name1>,<index_name2>,<index_name3>/_cache/clear?pretty

如何重新分配索引分片(reroute)?

当出现分片丢失、分片错误等分片问题时,您可以执行以下命令进行reroute操作。

curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
    "commands" : [ {
        "move" :
            {
              "index" : "test", "shard" : 0,
              "from_node" : "node1", "to_node" : "node2"
            }
        },
        {
          "allocate" : {
              "index" : "test", "shard" : 1, "node" : "node3"
          }
        }
    ]
}'

索引查询时,提示statusCode: 500的错误,如何处理?

建议您通过第三方插件进行查询(例如Cerebro):

  • 查询正常:说明该错误大概率是由于索引名称不规范引起的。规范的索引名称只包含英文、下划线和数字,您可以通过修改索引名称来修复此问题。

  • 查询不正常:说明索引或集群本身存在问题。请确保集群中存在该索引,且集群处于正常状态。

如何修改自动创建索引auto_create_index参数?

执行以下命令修改。

PUT /_cluster/settings
{
    "persistent" : {
        "action": {
          "auto_create_index": "false"
        }
    }
}
重要

auto_create_index参数的默认值为false,表示不允许自动创建索引。一般建议您不要调整该值,否则会引起索引太多、索引MappingSetting不符合预期等问题。

OSS快照大概需要多久?

在集群的分片数、内存、磁盘和CPU等正常的情况下,80 GB的索引数据进行OSS快照,大约需要30分钟。

创建索引时,如何设置分片数?

建议您将单个分片存储索引数据的大小控制在30 GB以内,不要超过50 GB,否则会极大降低查询性能。根据上述建议,最终分片数量 = 数据总量/30 GB。

适当提升分片数量可以提升建立索引的速度。分片数过多或过少,都会降低查询速度,具体说明如下:

  • 分片数过多会导致需要打开的文件比较多。由于分片是存储在不同机器上的,因此分片数越多,各个节点之间的交互也就越多,导致查询效率降低。

  • 分片数过少会导致单个分片索引过大,降低整体的查询效率。

自建Elasticsearch迁移数据,使用elasticsearch-repository-oss插件遇到如下问题,如何解决?

问题:ERROR: This plugin was built with an older plugin structure. Contact the plugin author to remove the intermediate "elasticsearch" directory within the plugin zip

解决方案:将elasticsearch改名为elasticsearch-repository-oss, 然后复制到plugins目录下。

如何调整Kibana可视化展示数据的时区?

您可以在Kibana中,通过转换时区来调整服务器时间,如下图(以6.7.0版本为例)。调整服务器时间1选择时区如下图所示。选择时区

ElasticsearchTerm查询适用于哪种类型的数据?

Term为单词级别的查询,这些查询通常用于结构化的数据,例如number、date、keyword等,而不是text。

说明

全⽂文本查询之前要先对文本内容进行分词,而单词级别的查询直接在相应字段的反向索引中精确查找,单词级别的查询一般用于数值、日期等类型的字段上。

使用ES的别名(aliases)功能需要注意哪些问题?

需要将别名里索引的分片控制在1024个以内。

在查询过程中,出现报错too_many_buckets_exception,如何处理?

报错:"type": "too_many_buckets_exception", "reason": "Trying to create too many buckets. Must be less than or equal to: [10000] but was [10001]

问题分析与解决方案:请参见控制聚合中创建的桶数。除了调整业务聚合的size大小,您还可以参见Increasing max_buckets for specific Visualizations来处理。

如何批量删除索引?

默认情况下,Elasticsearch不允许批量删除索引,需要通过以下命令手动开启。开启后,您可以通过通配符进行批量删除操作。

PUT /_cluster/settings
{
  "persistent": {
     "action.destructive_requires_name": false
  }
}

script.painless.regex.enabled参数能否修改?

此参数默认值是false,不建议修改。如果要在painless脚本中使用正则表达式,需要在elasticsearch.yml中设置script.painless.regex.enabled参数为true。由于正则表达式会消耗大量资源,官方不建议使用,因此没有打开此参数。

如何修改Elasticsearchmapping、主分片和副本分片数量?

  • 已经创建的索引修改mapping,建议通过reindex重建索引。

    说明

    mapping中支持的字段类型,请参见Data field type

  • 已经创建的索引无法修改主分片,建议通过reindex重建索引修改。

    说明

    建议您在创建索引前规划好分片数,减少后期调整。

  • 已经创建的索引修改副本数,可以参考以下命令修改:

    PUT test/_settings
    {
      "number_of_replicas": 0
    }

ES如何设置存储某个字段?

_source字段,默认情况下,ES不会单独存储字段值。如果需要独立存储某些字段,可以在索引的映射中将字段的store属性设置为true。

说明

ES_source字段包含原始JSON文档,提供了从原始文档检索任何字段的能力。通常不推荐开启字段存储,以免增加磁盘空间的使用。

以存储my_field字段为例:

PUT / my_index {
	"mappings": {
		"properties": {
			"my_field": {
				"type": "text",
				"store": true
			}
		}
	}
}

ES如何设置某个字段是否可以参与聚合?

字段是否可以聚合通常取决于字段的类型和是否有相关的字段数据(doc_valuesfielddata)可用。

  • 数字字段、日期字段和keyword类型字段,默认使用doc_values,默认情况下可以聚合。

    说明

    doc_values是专为排序、聚合和脚本操作优化的列存储格式。

  • text类型字段,默认情况下不支持聚合。如果您需要对text字段进行聚合,必须在映射中启用fielddata。

    说明

    开启fielddata会显著增加内存使用,因为它会把所有的文本数据加载到内存中。

    PUT /my_index{
      "mappings": {
        "properties": {
          "my_text_field": {
            "type": "text",
            "fielddata": true
          }
        }
      }
    }
  • 如果您不希望某个字段参与聚合,可以根据您的应用逻辑选择以下任一方式:

    • 通过设置enabled属性为false来排除整个对象字段。

    • 选择不将非聚合字段包含在文档中。

配置ES时遇到报错Unknown char_filter type [stop] for ** ,如何处理?

在配置ES时遇到报错Unknown char_filter type [stop] for ** ,表明您尝试在char_filter部分使用stop类型,但实际上stop是一个Token Filter而非Character Filter

解决方法如下:

  • 更正配置位置:如果您意图使用停用词过滤器,请将stop配置移至analyzer配置的filter部分,而非char_filter。停用词过滤器用于从Token流中移除指定的停用词列表中的词语。

    示例:

    "settings": {
     "analysis": {
       "analyzer": {
          "my_custom_analyzer": {
            "type": "custom",
            "tokenizer": "standard",
            "filter": [       // 正确位置:在filter数组内
              "lowercase",
              "stop"        // 使用stop Token Filter
            ]
          }
       },
       "filter": {          // 定义stop Token Filter的具体配置(如有必要)
          "stop": {
            "type": "stop",
            "stopwords": "_english_" // 或自定义停用词列表
          }
       }
     }
    }
    
  • 检查类型名称:确认其他配置如tokenizerchar_filter中是否正确的指定类型名称,避免类似的类型误用。

    请根据您的实际需求调整配置,确保char_filtertokenizerfilter各部分都使用了正确的组件类型。

冻结索引后磁盘空间未减少,如何释放空间?

冻结索引(freeze)只是将索引设为只读并释放堆内存以减少资源占用,索引的数据文件仍保留在磁盘上,因此磁盘空间不会减少。

如需释放磁盘空间,可以通过以下方式操作:

  • 直接删除冻结状态的索引

    冻结状态的索引可以直接删除,无需先解冻。执行以下命令删除指定的冻结索引:

    DELETE /<frozen_index_name>

    <frozen_index_name>替换为实际的冻结索引名称。删除索引会永久移除索引的所有数据和元数据,磁盘空间随之释放。

  • 删除部分文档后强制合并

    如果只需要释放部分空间而非删除整个索引,先解冻索引,使用_delete_by_query删除不需要的文档,再执行_forcemerge强制合并segment以回收磁盘空间:

    POST /<index_name>/_delete_by_query
    {
      "query": {
        "match": {
          "<field>": "<value>"
        }
      }
    }
    POST /<index_name>/_forcemerge?only_expunge_deletes=true

    _delete_by_query会将文档标记为已删除但不立即释放磁盘空间,_forcemerge会合并segment并物理删除已标记的文档,从而真正释放磁盘空间。

如何判断当前配置的 Elasticsearch 预处理管道是 default_pipeline 还是 final_pipeline?

Elasticsearch 的 Ingest Pipeline 支持两种索引级别的管道配置:default_pipelinefinal_pipeline,两者在作用阶段和优先级上有所不同。

  • default_pipeline:在文档索引前执行的预处理管道。如果索引请求中未通过 pipeline 参数指定其他管道,则使用该管道处理文档。索引请求可以通过 pipeline 参数覆盖 default_pipeline 的设置。

  • final_pipeline:在所有其他管道(包括 default_pipeline 和请求中指定的 pipeline)执行完成后执行的管道。final_pipeline 无法被覆盖,始终作为最后一步执行。

执行以下命令查看索引当前配置的管道类型:

GET <index_name>/_settings?filter_path=**.default_pipeline,**.final_pipeline

返回结果示例:

{
  "<index_name>": {
    "settings": {
      "index": {
        "default_pipeline": "my_default_pipeline",
        "final_pipeline": "my_final_pipeline"
      }
    }
  }
}

如果返回结果中包含 default_pipeline 字段,说明该索引配置了默认预处理管道;如果包含 final_pipeline 字段,说明配置了最终处理管道。未返回的字段表示该索引未配置对应类型的管道。

说明

也可以通过 GET <index_name>/_settings 查看索引的完整配置,在返回的 settings.index 中查找 default_pipelinefinal_pipeline 字段。

如何使用 Elasticsearch scroll 查询进行大量数据检索?

scroll 查询适用于需要检索大量数据的场景(如全量数据导出或批量处理),通过保持搜索上下文来分批获取数据。scroll 不适用于实时搜索场景,实时查询建议使用常规 search API。使用步骤如下:

  1. 发起初始 scroll 查询,指定 scroll 上下文保持时间(如 1 分钟):

    POST /<index_name>/_search?scroll=1m
    {
      "size": 1000,
      "query": {
        "match_all": {}
      }
    }

    从返回结果中获取 _scroll_id,用于后续的数据拉取。

  2. 使用 _scroll_id 获取下一批数据:

    POST /_search/scroll
    {
      "scroll": "1m",
      "scroll_id": "<上一步返回的_scroll_id>"
    }
  3. 重复执行步骤 2,每次使用最新返回的 _scroll_id,直到返回结果中的 hits.hits 数组为空,表示数据已全部检索完毕。

  4. 检索完成后,清除 scroll 上下文以释放集群资源:

    DELETE /_search/scroll
    {
      "scroll_id": "<_scroll_id>"
    }
说明

scroll 参数指定的是每次 scroll 请求之间的最大等待时间,而非整个查询的超时时间。每次执行 scroll 请求都会刷新该超时计时器。size 参数控制每批返回的文档数量,建议根据单条文档大小合理设置,避免单次返回数据量过大。

如何在 Kibana 中找到角色管理入口或修改索引 Mapping?

角色管理

通过阿里云 Elasticsearch 控制台的可视化控制台入口登录 Kibana 后,在左侧导航栏选择 Stack Management > Security > Roles,即可进行角色的创建、编辑和删除操作。

修改索引 Mapping

非日志增强版 Elasticsearch 实例不支持在阿里云 Elasticsearch 控制台直接修改索引 Mapping,需要通过 Kibana 操作。登录 Kibana 后,在左侧导航栏选择 Stack Management > Index Management,找到目标索引后,通过 Dev Tools 执行 PUT mapping 请求添加字段。示例如下:

PUT /<index_name>/_mapping
{
  "properties": {
    "new_field": {
      "type": "keyword"
    }
  }
}
重要

Elasticsearch 仅支持向已有索引新增字段,不支持修改或删除已有字段的类型。如需修改已有字段类型,需要创建新索引并通过 reindex 迁移数据,具体操作可参考本文「如何修改 Elasticsearch 的 mapping、主分片和副本分片数量?」章节。