一个历史es业务, index 只有一个sharding, 多达400G,不方便后期水平扩容,并且单节点经常有大查询,,单个索引的查询效率变得越来越慢。查询超时的情况。
计划按月份对索引进行拆分,并限制查询的时间范围,以减少查询时的数据量和聚合操作。
一个月之前的历史数据不会更新,
1、历史数据每个月拆分一个索引,根据机器数量拆分sharding 数量。 控制索引大小在20-40G
2、双写, 数据写入历史索引, 并且写到按月拆分的新索引上。
3、等历史数据拆分赶上 按月双写的新索引(比如从10月12号开始双写, 历史数据拆分索引,到10月分的索引就可以了)
4、建立索引别名,包含按月拆分的索引, 这样就可以通过别名查询历史数据。
5、在进行查询时,根据业务需求,我们将根据时间范围指定查询的别名。减少聚合。
6、定时任务创建别名、索引,过期索引删除。
例如拆分center.work 2023年7月份数据数据到索引 center.work_202307
put center.work_202307/_settings
{"index":{"number_of_replicas":0}}
POST _reindex?slices=auto
{
“conflicts”: “proceed”,
“source”: {
“index”: “center.work”,
“size”: 10000,
“query”: {
“range”: {
“gmtCreate”: {
“lt”: “1690819200000”,
“gte”: “1688140800000”
}
}
}
},
“dest”: {
“index”: “center.work_202307”,
“op_type”: “create”
}
}
GET /center.work/_search
{
"query": {
"bool": {
"filter": {
"range": {
"gmtCreate": {
"lt": "1690819200000",
"gte": "1688140800000"
}
}
}
}
}
}
GET /center.work_202307/_search
put center.work_202307/_settings
{“index”:{“number_of_replicas”:1}}
POST _reindex?slices=auto&refresh&wait_for_completion=false
{
# 只查询1w条记录到 新索引。在source 外和source内 不一样。
"size": 10000,
"source": {
"conflicts": "proceed", # 指示 _reindex 继续处理有关版本冲突的下一个文档。 需要注意的是,其他错误类型的处理不受“冲突”参数的影响
"index": "old_index",
# 同时也允许多个索引 合并到一个索引上,和上面的重复配置
"index": ["old_index_1", "old_index_2"],
"size": 5000 # 默认情况下 _reindex 使用1000 的滚动批次,更改这个值提高速度。
# 可以做条件筛选
"query": {
"term": {
"user": "kimchy"
}
}
},
"dest": {
"index": "new_index"
# 有下面三个选项
"version_type": "internal", # 覆盖任何具有相同类型和 ID 的文件。
"version_type": "external", # 创建任何丢失的文档,并更新目标索引中版本比源索引中版本旧的任何文档
"op_type": "create", # 仅创建丢失的文档,如果文档已经存在,会引起版本冲突报错,中止reindex 进程。
}
}
1)slices大小的设置可以手动指定,或者设置slices设置为auto,auto的含义是:针对单索引,slices大小=分片数;针对多索引,slices=分片的最小值。
2)当slices的数量等于索引中的分片数量时,查询性能最高效。slices大小大于分片数,非但不会提升效率,反而会增加开销。
3)如果这个slices数字很大(例如500),建议选择一个较低的数字,因为过大的slices 会影响性能。
效果
实践证明,比默认设置reindex速度能提升10倍+
wait_for_completion=false
es中的请求超时时间默认是1分钟,当重建索引的数据量太大时,经常会出现超时。
GET _tasks?detailed=true&actions=*reindex
GET /_tasks/r1b2WoRbTwKZ516z6NEs5s:46629
POST _tasks/r1b2WoRbTwKZ516z6NEs5s:46629/_cancel
下面的例子是,修改flag 为tag
POST test/_doc/1?refresh
{
"text": "words words",
"flag": "foo"
}
POST _reindex
{
"source": {
"index": "test"
},
"dest": {
"index": "test2"
},
"script": {
"source": "ctx._source.tag = ctx._source.remove(\"flag\")"
}
}
GET test2/_doc/1
{
"found": true,
"_id": "1",
"_index": "test2",
"_type": "_doc",
"_version": 1,
"_seq_no": 44,
"_primary_term": 1,
"_source": {
"text": "words words",
"tag": "foo"
}
}
一个别名可以绑定多个索引,一个索引也可以绑定多个别名。
POST _aliases
{
"actions" : [
{ "add" : { "index" : "pro_index", "alias" : "pro_index_alias" } }
]
}
POST /_aliases
{
"actions" : [
{ "add" : { "indices" : ["test1", "test2"], "alias" : "alias1" } }
]
}
POST /_aliases
{
"actions" : [
{ "add" : { "index" : "test*", "alias" : "all_test_indices" } }
]
}
注意:在这种情况下,别名是一个点时间别名,它将对所有匹配的当前索引进行别名,当添加/删除与此模式匹配的新索引时,它不会自动更新。
POST /_aliases
{
"actions" : [
{ "remove" : { "index" : "product", "alias" : "product_real" } }
]
}
把 product 的别名重命名为 product_real (原子操作)
POST /_aliases
{
"actions" : [
{ "remove" : { "index" : "product", "alias" : "product_template" } },
{ "add" : { "index" : "product", "alias" : "product_real" } }
]
}
给test 添加了两个别名一个 alias_1 查询所有test数据。
一个alias_2 查询"user.id": “kimchy” 的数据。
PUT /test
{
"aliases": {
"alias_1": {},
"alias_2": {
"filter": {
"term": { "user.id": "kimchy" }
}
}
}
}
POST /_aliases
{
"actions" : [
{
"add" : {
"index" : "employee",
"alias" : "emp1",
"filter" : { "term" : { "type" : "normal" } }
}
},
{
"add" : {
"index" : "employee",
"alias" : "emp2"
}
}
]
}
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-reindex.html
https://blog.csdn.net/w1014074794/article/details/120483334
https://blog.csdn.net/wlei0618/article/details/125363206
https://www.elastic.co/guide/en/elasticsearch/reference/current/aliases.html