elasticsearch创建索引的几种方式及分析

2023-11-15 15:07:57 浏览数 (3)

一.使用create index API创建索引

1.指定索引名创建索引

代码语言:javascript复制
PUT test_index

当elasticsearch返回true时,就代表着我们在elasticsearch中创建了一个名为test_index的索引已经成功,同时在创建索引时没有为该索引指定任何字段。

然后我们查看该索引的详细信息:

代码语言:javascript复制
GET test_index
代码语言:javascript复制
{
  "test_index": {
    "aliases": {},
    "mappings": {
      "dynamic_templates": [
        {
          "message_full": {
            "match": "message_full",
            "mapping": {
              "fields": {
                "keyword": {
                  "ignore_above": 2048,
                  "type": "keyword"
                }
              },
              "type": "match_only_text"
            }
          }
        },
        {
          "message": {
            "match": "message",
            "mapping": {
              "type": "match_only_text"
            }
          }
        },
        {
          "strings": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ]
    },
    "settings": {
      "index": {
        "refresh_interval": "10s",
        "indexing": {
          "slowlog": {
            "threshold": {
              "index": {
                "warn": "200ms",
                "trace": "20ms",
                "debug": "50ms",
                "info": "100ms"
              }
            },
            "source": "1000"
          }
        },
        "translog": {
          "sync_interval": "5s",
          "durability": "async"
        },
        "provided_name": "test_index",
        "max_result_window": "65536",
        "creation_date": "1700017444301",
        "unassigned": {
          "node_left": {
            "delayed_timeout": "5m"
          }
        },
        "number_of_replicas": "1",
        "uuid": "YAIUJ64oTYuQpEjMvQK_Rg",
        "version": {
          "created": "8080199"
        },
        "routing": {
          "allocation": {
            "include": {
              "_tier_preference": "data_hot,data_warm,data_cold"
            }
          }
        },
        "search": {
          "slowlog": {
            "threshold": {
              "fetch": {
                "warn": "200ms",
                "trace": "50ms",
                "debug": "80ms",
                "info": "100ms"
              },
              "query": {
                "warn": "500ms",
                "trace": "50ms",
                "debug": "100ms",
                "info": "200ms"
              }
            }
          }
        },
        "number_of_shards": "1"
      }
    }
  }
}

我们可以看到在索引的mappings中,除了动态模板自带的mapping配置之外,没有任何其他索引mapping。同时还适配了default@template模板的索引参数。

现在我们对该索引手动插入一条数据。

代码语言:javascript复制
PUT /test_index/_doc/1?pretty
{
  "name":"张三",
  "age":23,
  "remark":"热爱学习,热爱读书,热爱生活"
}

此时elasticsearch回返回以下信息,告诉我们在test_index索引中已经成功创建了一条"_id"为1的数据,该数据的"_version"也为1,在2个分片上执行成功,失败0个分片。

现在我们重新执行GET test_index,我们发现在索引的mapping中,多出了properties部分,在properties中已经有了"name","age","remark"三个字段。同时elasticsearch还对这三个字段自动映射了字段类型。

代码语言:javascript复制
{
  "test_index": {
    "aliases": {},
    "mappings": {
      "dynamic_templates": [
        {
          "message_full": {
            "match": "message_full",
            "mapping": {
              "fields": {
                "keyword": {
                  "ignore_above": 2048,
                  "type": "keyword"
                }
              },
              "type": "match_only_text"
            }
          }
        },
        {
          "message": {
            "match": "message",
            "mapping": {
              "type": "match_only_text"
            }
          }
        },
        {
          "strings": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ],
      "properties": {
        "age": {
          "type": "long"
        },
        "name": {
          "type": "keyword"
        },
        "remark": {
          "type": "keyword"
        }
      }
    }
}

此时我们可以通过查询对我们插入的数据进行检索。可以看到elasticsearch已经为我们返回了匹配到的数据。

代码语言:javascript复制
GET test_index/_search
{
  "query": {
    "term": {
      "age": {
        "value": "23"
      }
    }
  }
}

当我们使用另一种查询,使用match来查询当前数据时,我们发现elasticsearch并没有为我们返回数据。

代码语言:javascript复制
GET test_index/_search
{
  "query": {
   "match": {
     "remark": "读书"
   }
  }
}

通过排查索引mapping我们发现,elasticsearch为remark字段推断的类型为keyword,通过之前的文章,我们知道keyword是不能被分词的。所以我们通过match查询,无法查到数据。那么我们在创建索引时,应该如何操作呢?

代码语言:javascript复制
 "properties": {
        "age": {
          "type": "long"
        },
        "name": {
          "type": "keyword"
        },
        "remark": {
          "type": "keyword"
        }
      }

我们在创建索引时,对索引的字段类型进行手动的约束。

代码语言:javascript复制
PUT /test_index_new
{
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "age": { "type": "integer" },
      "remark": { "type": "text" }
    }
  }
}

我们在PUT一条相同的数据后,在对test_index_new索引进行match查询,我们发现已经可以正常查到数据。

代码语言:javascript复制
GET test_index_new/_search
{
  "query": {
   "match": {
     "remark": "读书"
   }
  }
}

使用手动创建索引的方式,主要有以下优缺点

优点:

  1. 灵活性:手动创建索引,我们可以自行设置索引的参数与mapping映射类型。包括索引的分片数,副本数,字段类型,指定字段使用的分析器等参数配置。能够更加契合特定业务场景的需求。
  2. 定制性:在创建索引时,能够基于数据的特性与查询需求,进行相应的参数优化。选择适当的字段类型,以提高读写性能与查询的匹配相关度。
  3. 版本管理:当业务需要保存多个版本的数据时,我们可以手动创建多个版本索引,对数据进行管理。同样也便于后期对不同版本的数据进行迁移或回滚等操作。

缺点:

  1. 需要手动管理索引:在索引创建时,需要使用者了解索引相关配置的含义与用法,并结合相应的工具进行使用。可能需要额外的工作量。
  2. 容易出错:手动创建索引可能会导致人为错误。当索引创建出现错误时,可能会影响索引的性能与系统业务。
  3. 需要维护:手动创建的索引需要人工进行维护,如果索引结构或者字段需求发生变化时,则需要手动调整索引设置与映射。

思考:

在特定业务场景下,我们手动创建索引能够更好的满足我们的业务需求,当业务激增时,需要手动创建的索引越来越多,是否有更便捷的方式让我们进行索引的创建呢?

2.使用索引模板自动适配索引

我们可以通过定义索引模板,来针对不同业务的索引进行索引参数的预定义与mapping映射的预定义。当索引在创建时,会通过读取模板中的"index_patterns"来对索引进行相应的模板适配。以满足不同业务场景下,不同的索引需求。

在下面的代码中,我们创建了一个名为test_template的模板,模板的优先级为1,主要适配"test"开头的索引。在索引settings中,我们设置了索引主分片数为3,副本数为1。在索引mappings中 我们约束了"name","age","remark"三个字段的字段类型。当elasticsearch返回true后,则代表着模板创建完成。

代码语言:javascript复制
PUT _template/test_template
{
  "order": 1, 
  "index_patterns": ["test*"],
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  },
  "mappings": {
    "_source": {
      "enabled": false
    },
    "properties": {
     "name": { "type": "text" },
      "age": { "type": "integer" },
      "remark": { "type": "text" }
    }
  }
}

我们现在重新创建一个名为test_template_index的索引,且什么都不指定,让我们来观察一下索引的mapping情况。

代码语言:javascript复制
PUT test_template_index

此时我们在索引mapping中发现,这个索引已经自动将我们之前在模板中为索引名是"test"打头的索引参数与mapping自动进行了适配。极大程度的方便了我们对于索引的创建与管理。

代码语言:javascript复制
{
  "test_template_index": {
    "aliases": {},
    "mappings": {
      "_source": {
        "enabled": false
      },
      "dynamic_templates": [
        {
          "message_full": {
            "match": "message_full",
            "mapping": {
              "fields": {
                "keyword": {
                  "ignore_above": 2048,
                  "type": "keyword"
                }
              },
              "type": "match_only_text"
            }
          }
        },
        {
          "message": {
            "match": "message",
            "mapping": {
              "type": "match_only_text"
            }
          }
        },
        {
          "strings": {
            "match_mapping_type": "string",
            "mapping": {
              "type": "keyword"
            }
          }
        }
      ],
      "properties": {
        "age": {
          "type": "integer"
        },
        "name": {
          "type": "text"
        },
        "remark": {
          "type": "text"
        }
      }
    },
    "settings": {
      "index": {
        "refresh_interval": "10s",
        "indexing": {
          "slowlog": {
            "threshold": {
              "index": {
                "warn": "200ms",
                "trace": "20ms",
                "debug": "50ms",
                "info": "100ms"
              }
            },
            "source": "1000"
          }
        },
        "translog": {
          "sync_interval": "5s",
          "durability": "async"
        },
        "provided_name": "test_template_index",
        "max_result_window": "65536",
        "creation_date": "1700030711762",
        "unassigned": {
          "node_left": {
            "delayed_timeout": "5m"
          }
        },
        "number_of_replicas": "1",
        "uuid": "cTiJp67xThSwpavbV3Hlog",
        "version": {
          "created": "8080199"
        },
        "routing": {
          "allocation": {
            "include": {
              "_tier_preference": "data_hot,data_warm,data_cold"
            }
          }
        },
        "search": {
          "slowlog": {
            "threshold": {
              "fetch": {
                "warn": "200ms",
                "trace": "50ms",
                "debug": "80ms",
                "info": "100ms"
              },
              "query": {
                "warn": "500ms",
                "trace": "50ms",
                "debug": "100ms",
                "info": "200ms"
              }
            }
          }
        },
        "number_of_shards": "3"
      }
    }
  }
}

使用手动创建索引的方式,主要有以下优缺点:

优点:

  1. 自动化:可以通过模板预定义索引参数与字段mapping,通过模板适配的方式来减轻手动操作的工作量。确保在同一业务场景下,创建的索引具备一致的结构与参数配置。
  2. 统一性:通过索引模板适配的方式,可以确保特定业务索引索创建的索引都遵循相同的设置于映射。能够有效的保证数据结构的一致性。在具有大量索引的elasticsearch集群中尤为重要。
  3. 简化管理:通过索引模板适配的方式能够极大程度的降低我们创建与维护索引的工作量。我们只需要维护少量索引模板即可。不需要在单独管理每个索引的配置。

缺点:

  1. 限制性:索引模板对于索引的灵活度有一定限制,由于索引模板适配这种方式是作用于具有共性的索引创建。预定义的方式无法满足特殊索引的需求。如果遇到特殊索引还需要进行额外的修改。

FAQ

索引模板创建完成后,在进行索引创建时发现,模板中的参数没有对创建的索引进行适配?

原因与排查思路:

  1. 检查模板中的"index_patterns"配置,检查通配符是否配置正确,索引模板在适配索引时,是通过"index_patterns"来判断索引是否为当前模板进行管理。
  2. 检查模板中的"order","order"代表着模板的优先级,"order"的值越大,则意味着该模板的优先级越高。在模板适配索引时,高优先级的模板优先适配。
  3. 检查其他"index_patterns"的值配置为"*"的索引模板,其优先级是否高于特定业务的索引模板。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞