提升写入性能
使用 bulk 接口批量写入
- 节省重复创建连接的网络开销
- 通过进行基准测试来找到最佳的批处理数量
延长 refresh 的时间间隔
- 通过延长 refresh(刷新)的时间间隔可以降低段合并的频率,段合并十分耗费资源
- 默认的刷新频率为1s,对 index 修改 index.refresh_interval 即可立即生效
初始化性能的大量写入
- 比如 reindex 或是导入基础数据这种一次性批量索引操作
- 可以配置成不刷新,并且把副本数也配置成0,完了之后再设置成正常值
关闭操作系统的 swapping
- 操作系统会自动把不常用的内存交换到磁盘(虚拟内存),关闭后就不会进行交换
使用自动生成的id
- 指明文档 id 时,es 需要先判断一下这个 id 对应的文档是否已经存在,以做一些合并或者更新操作。如果使用自生成的 id,可以跳过这个步骤,加快索引速度
合理设置字段 mapping
- 不需要分析的字段就不用分析
合理设置分片和副本数量
- 副本数量越多,写入越慢
提升查询性能
用过滤器上下文替代查询上下文
- 过滤器上下文,不计算得分可以减少资源消耗,过滤器结果可以缓存
避免使用脚本
- 脚本非常耗性能,因为每次计算且无法缓存
- 如果非用不可,就用 painless 或者 expressions
提前索引字段
假如有如下的文档
PUT index/_doc/1
{
"designation": "spoon",
"price": 13
}
经常进行如下的范围查询
GET index/_search
{
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 10 },
{ "from": 10, "to": 100 },
{ "from": 100 }
]
}
}
}
}
索引的时候可以增加一个 price_range 字段,用来存储范围
PUT index
{
"mappings": {
"properties": {
"price_range": {
"type": "keyword"
}
}
}
}
PUT index/_doc/1
{
"designation": "spoon",
"price": 13,
"price_range": "10-100"
}
最开始的分组方式就可以改成如下形式
GET index/_search
{
"aggs": {
"price_ranges": {
"terms": {
"field": "price_range"
}
}
}
}
合理 mapping
- 数值数据可以映射为 numeric 类型或者keyword类型
- 数字类型适合范围查询
- keyword 类型适合精确查询(精确查询时搜索 keywrod 比搜索 numeric 更快)
比如产品id或者 ISBN(一种用于唯一标识图书的国际标准)基本上是用在精确查询的场景中,我们就可以映射为 keyword 类型
使用更轻量的查询语句
- 通配符查询很费性能,尤其是通配符放在前面
不要使用关联关系
- 不管是嵌套还是父子,都会使查询量倍增
增加副本数量
- 查询时会查询主分片或副本分片,因此增加副本数量可以提高系统吞吐量
按时间查询时对时间进行四舍五入
- 这样可以更好的利用缓存
在可以接受的前提下,可以从方式一改为方式二
方式一:查询当前时间减去1小时到当前时间,精确到秒的时间范围
GET index/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"my_date": {
"gte": "now-1h",
"lte": "now"
}
}
}
}
}
}
方式二:和方式一相比,多了/m,表示这是一个精确到分钟的相对时间范围
GET index/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"my_date": {
"gte": "now-1h/m",
"lte": "now/m"
}
}
}
}
}
}
如果 index 不再写入可以合并分段
- 分段越少,查询越快,每次查询都要拆到所有分段去处理,再合并结果,有 _forcemerge 接口,可以把分段数设为1
- 甚至可以合并分片,reindex 或 shink
POST /my-index-000001/_forcemerge
给文件系统(filesystem cache)预留足够内存
- es 非常依赖操作系统的文件缓存来提高查询速度
- 预留至少一半的内存给文件系统缓存
使用 ssd 磁盘而且别用远程磁盘
- es需要频繁读取磁盘
路由优化
节省磁盘空间
关闭不需要的特性
- 不被用来查询的字段,不索引
- 不做全文检索,不分词
- 不关注文档相关性,关闭 norms
- 不需要短语搜索,关闭位置索引
不要使用自动 mapping
- 默认会对 string 字段做两次索引(text 和 keyword)
禁用 _source 字段
- _source字段存储了文档原始的 json 格式,如果不需要访问,可以禁用
配置压缩存储
分段合并
- 段里面的数据是逻辑删除的,段合并的时候会将这些数据真正删除
数字类型用最小数字类型
- 尽量选择占用空间较小的数组类型,byte < short < integer < long
参考博客
官网性能优化建议
[1]https://www.elastic.co/guide/en/elasticsearch/reference/8.11/how-to.html
[2]https://pdai.tech/md/db/nosql-es/elasticsearch-y-peformance.html