文章目录
-
- 如何处理关联关系
- 避免过多字段
- 避免正则/通配符/前缀查询
- 避免空值引起的聚合不准
- [为索引的Mapping加入Meta 信息](#为索引的Mapping加入Meta 信息)
如何处理关联关系
-
Object: 优先考虑反范式(Denormalization)
-
Nested: 当数据包含多数值对象,同时有查询需求
-
Child/Parent:关联文档更新非常频繁时
避免过多字段
-
一个文档中,最好避免大量的字段
- 过多的字段数不容易维护
- Mapping 信息保存在Cluster State 中,数据量过大,对集群性能会有影响
- 删除或者修改数据需要reindex
-
默认最大字段数是1000,可以设置
index.mapping.total_fields.limit
限定最大字段数。·
思考:什么原因会导致文档中有成百上千的字段?
生产环境中,尽量不要打开 Dynamic,可以使用Strict控制新增字段的加入
- true :未知字段会被自动加入
- false :新字段不会被索引,但是会保存在_source
- strict :新增字段不会被索引,文档写入失败
对于多属性的字段,比如cookie,商品属性,可以考虑使用Nested
避免正则/通配符/前缀查询
正则,通配符查询,前缀查询属于Term查询,但是性能不够好。特别是将通配符放在开头,会导致性能的灾难
案例:针对版本号的搜索,我们一般会对版本号进行模糊查询,优化方式将一个版本号字段变为保存Object对象类型,其实就是拆分为多个字段,
bash
# 将字符串转对象
PUT softwares/
{
"mappings": {
"properties": {
"version": {
"properties": {
"display_name": {
"type": "keyword"
},
"hot_fix": {
"type": "byte"
},
"marjor": {
"type": "byte"
},
"minor": {
"type": "byte"
}
}
}
}
}
}
#写入多个文档
PUT softwares/_doc/1
{
"version": {
"display_name": "7.1.0",
"marjor": 7,
"minor": 1,
"hot_fix": 0
}
}
PUT softwares/_doc/2
{
"version": {
"display_name": "7.2.0",
"marjor": 7,
"minor": 2,
"hot_fix": 0
}
}
PUT softwares/_doc/3
{
"version": {
"display_name": "7.2.1",
"marjor": 7,
"minor": 2,
"hot_fix": 1
}
}
# 通过 bool 查询,
POST softwares/_search
{
"query": {
"bool": {
"filter": [
{ "match": { "version.marjor": 7 } },
{ "match": { "version.minor": 2 } }
]
}
}
}
避免空值引起的聚合不准
字段的值如果为null,那么就会导致对该字段进行聚合操作得到的结果不准确。因为聚合操作会把为null的文档忽略掉。
比如有5名学生,它们的成绩分别为100、null、null、99、98。此时如果计算平均值那么结果是(100+99+98)/3 ,但是我们期望的是(100+99+98+0+0)/5
我们可以在创建索引时,为这个字段指定 null_value
属性,如果为null就给一个默认值
bash
DELETE scores
# 创建索引,未指定null_value
PUT /scores
{
"mappings": {
"properties": {
"score": {
"type": "float",
"null_value": 0
}
}
}
}
# 创建三个文档
PUT /scores/_doc/1
{"score":100}
PUT /scores/_doc/2
{"score":null}
PUT /scores/_doc/3
{"score":100}
# 求平均值
POST /scores/_search
{
"size": 5,
"aggs": {
"hs_avg": {
"avg": {
"field": "score"
}
}
}
}
补充:
为索引的Mapping加入Meta 信息
-
Mappings设置非常重要,需要从两个维度进行考虑
- 功能︰搜索,聚合,排序
- 性能︰存储的开销; 内存的开销; 搜索的性能
-
Mappings设置是一个迭代的过程
- 加入新的字段很容易(必要时需要update_by_query)
- 更新删除字段不允许(需要Reindex重建数据)
- 最好能对Mappings 加入Meta 信息,更好的进行版本管理
- 可以考虑将Mapping文件上传git进行管理
bash
PUT /my_index
{
"mappings": {
"_meta": {
"index_version_mapping": "1.1"
}
}
}