- 作者:老汪软件技巧
- 发表时间:2024-10-12 15:02
- 浏览量:
1. 索引的定义
索引是具有相同结构的文档的集合,类似于关系型数据库中的一个表,由唯一索引名称标定,索引名不能用大写字母。一个集群中有多个索引,不同的索引代表不同的业务类型数据。
在 6.X之前的版本中,索引类似于SQL数据库,而type(类型)类似于表。但6.X之后版本中,父子文档索引不再使用多类型机制,而改为使用Join类型。
# 创建索引
PUT index_001
{
"settings": {
"number_of_shards": 2, # 两个主分片
"number_if_repicas": 1 # 一个副本分片
},
"mappings": { # 映射
"properties": {
"column1":{ # 字段1
"type": "text",
"analyzer": "ik_smart"
},
"column2":{
"type": "keyword", # keyword类型用于聚合、排序和精准匹配
"index": "false"
},
"column3":{
"properties": {
"子字段1": {
"type": "keyword"
},
"子字段2": {
"type": "keyword"
}
}
}
}
}
}
2. 索引设置
设置主分片大小的参数是index.number_of_shards,只在创建索引时生效,不支持动态修改。默认主分片大小为1,且每个索引的分片数量上限默认为1024。此限制是一个安全限制,可防止索引分片数过多导致集群不稳定。
在业务层面扩充节点后确实需要扩展主分片数,该怎么办?在非业务核心时间通过reindex操作迁移实现。
动态设置的实战场景举例如下。
PUT index_001/_settings
{
"number_of_replicas": 3, # 设置副本数参数为index.number_of_replicas
"refresh_interval": "1s" # 设置刷新频率参数
"max_result_window": 50000 # 搜索结果的最大窗口大小,如果每页显示50条数据,则最多可以翻到1000页
}
默认刷新频率参数值为1s,即每秒刷新一次。这1s决定了es是近实时的搜索引擎,而非准实时搜索引擎。如果业务层面对实时性的要求不高,可以考虑将该值调大。因为如果采用1s,则每秒都会生成一个新的分段,会影响写入性能。
增大窗口大小可能对es集群的性能产生影响。需要权衡性能和查询范围间的关系。
3. 索引映射和别名
可以将索引映射理解成MySQL中的表结构Schema,包括如下主要内容。
索引别名所起的作用类似于windows的快捷方式
4. 索引操作
新增索引
#方式一:详细定义索引设置、映射、别名。
#方式二:只定义索引名,而settings、mappings取默认值
PUT myindex
删除索引
#方式一:删除索引。
DELETE myindex
#方式二:清空数据,保留索引
POST myindex/delete_by_query
{
"query":{
"match_all":{}
}
}
方式一为物理删除,效率更高、更快;方式二为逻辑删除。
方式一立马能释放磁盘空间;方式二不会立即释放磁盘空间。
使用DELETE命令可以从索引层面删除索引及数据,并释放空间。而使用delete_by_query命令是通过查询来删除数据,数据不会立即被删除,而是形成新的数据分段,待段合并时才能被物理删除。
查询索引
# 获取索引的基础信息。只涉及对索引的查询,不会对索引进行修改
GET myindex
# 若加上_search,则获取的是在该索引下的数据的信息
GET myindex/_search
修改索引
#如果创建索引的时候没有指定别名,那么可以通过如下方式添加别名。
POST /_aliases
{
"actions": [
{
"add": {
"index": "myindex", #索引名
"alias":"myIndex_alias" # 别名
}
}
]
}
索引别名
在很多业务场景下,单一索引可能无法满足要求:
这两个问题都可以借助索引别名来解决。使用别名会很方便、灵活、快捷,且使业务代码松耦合。
# 创建索引时起别名
PUT myindex
{
"aliases": {
"myindex_alias": {}
}
}
多索引检索
POST index_0921,index_0922/_search # 用逗号分隔索引名
POST index_*/_search # 用通配符
使用别名能透明的更换别名使用的索引
PUT index1
PUT index2
POST /_aliases
{
"actions":[
{
"add":{
"index":"index1",
"alias":"index_alias"
}
},
{
"add":{
"index":"index2",
"alias":"index_alias"
}
},
]
}
# 使用别名进行检索,自动把搜索操作应用到两个索引上
POST index_alais/_search
别名常见问题
# 批量插入可以使用别名吗
POST myindex/_bulk
{
"index":{},
{"title": "001"}
}
# 如果非要指定别名来插入数据,则需要提前设置is_write_index。
POST /_aliases
{
"actions":[
{
"add":{
"index":"myindex",
"alias":"myindex_alias",
"is_write_index":true
}
}
]
}
# 如何通过索引别名查找实际索引名称。
GET _cat/aliases?v
对相同索引别名的物理索引建议有一致的映射,以提升检索效率。
充分发挥别名在检索方面的优势,但在写入和更新时还得使用物理索引。
5. 索引模版
问题1:数据量非常大,需要进行索引生命周期管理,具体要按日期划分索引,且要求多个索引的Mapping一致,而每次手动创建或者脚本创建都很麻烦,怎么办?
问题2:实际业务中应用了多个索引,想让这些索引中相同名字的字段类型完全一致,以便实现跨索引检索,怎么办?
传统方式不能解决多索引的快速定义和高效管理等问题。因此,索引模板应运而生。
模版定义
普通模版
PUT _index_template/template_1 # 生成一个叫template_1的模版
{
"index_patterns": [ # 要匹配的索引集合,te开头的和bar开头的
"te*",
"bar*"
],
"template": {
"aliases": {
"alias1": {}
},
"settings": {
"number_of_shards": 1
},
"mappings": {
"_source": {
"enabled": false
},
"properties": {
"host_name": {
"type": "keyword"
},
"create_at": {
"type": "date",
"format": "EEE MMM dd HH:mm:ss Z yyyy"
}
}
}
}
}
组件模版:将原有普通模板定义的mappings、settings等以组件的方式分隔,以便最小化更新模板。
PUT _component_template/my_mapping_template
{
"template":{
"mappings":{
"properties":{
"@timestamp":{
"type": "date"
},
"host_name":{
"type":"keyword"
}
}
}
}
}
PUT _component_template/my_settings_template
{
"settings":{
"number_of_shards":3
},
"aliases":{
"mydata":{}
}
}
PUT _index_template/mydata_template
{
"index_patterns":[
"mydata*"
],
"priority":500,
"composed_of":[
"my_mapping_template",
"my_settings_template"
],
"version":1,
"_meta":{
"description":"my custom template"
}
}
由上可知,模板名称为mydata_template,包含两个核心组件——my_mapping_template、my_settings_template。
当业务层面需要更新映射时,只需要更新my_mapping_template组件模板即可,改动范围更小、操作更精细化
索引模版基础操作
# 新增模版
PUT _index_template/my_template
# 删除模版
DELETE _index_template/my_template
# 查询模版
GET _index_template/my_template
# 修改模版
按创建模版的方式去修改模版,生成具有相同名称的新模版,覆盖原模版。新模版只对新创建的索引生效。
动态模版
需求:1.如果默认不显示指定映射,则数值类型的值会被映射为long,但实际业务数值都比较小,会存储浪费,将默认值改成integer。2:date_*开头的字符将统一匹配为date日期类型。
PUT _index_template/sample_dynamic_template
{
"index_patterns":[
"sample*" # sample开头的索引都要匹配该模版
],
"template":{
"mappings":{
"dynamic_templates":[
{
"hadle_integers":{ # 动态模版名,可自定义
"match_mapping_type":"long",
"mapping":{
"type":"integer"
}
}
},
{
"handle_date":{
"match": "date_*",
"mapping":{
"type":"date"
}
}
}
]
}
}
}
# 看看效果
PUT sampleindex/_doc/1
{
"ivalue":123,
"date_currenttime":"1574494620000"
}
GET sampleindex/_mapping
索引模版应用的常见问题
1)模板和索引在应用上的区别是什么?
索引针对的是单一索引,类似MySQL中的表。而模板针对一至多个索引,或者说是针对具有相同表结构的一类索引。
2)如果想更新映射,那么可以通过更新模板来实现吗?
一旦创建了映射,除几个特定的类型以外,其他类型都不支持更新,除非进行reindex操作。
所以,一旦创建了索引,对索引模板的更新将不会影响该索引。更新模板仅适用于新创建的索引。更新为动态模板仅会影响索引中的新字段。索引模板是一个很高效的工具,可全局设置多个索引且批量生效,避免不必要的重复工作。
相比之下,映射和别名的优势如下。
因此,当新系统准备选择es存储核心数据时,需要优先注意数据建模,并且在数据建模的过程中要综合考虑模板、别名、映射、设置的优势,才能保证模型的健壮性。