更新fielddata为true_[翻译]Elasticsearch重要文章之五:预加载fielddata

本文介绍了Elasticsearch如何处理fielddata的加载,包括延迟加载带来的延迟问题及解决方案。通过饿汉式加载fielddata和全局序数,可以提高查询性能,避免用户遇到延迟。全局序数是一种优化string类型fielddata占用内存的技术,通过预加载全局序数,可以显著提升汇总和排序操作的速度。同时,文章提到了index warmers作为预热工具,可以在新段可用前执行查询,预先加载缓存,以减少延迟。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Elasticsearch 是默认延迟加载fielddata到内存里的。当elasticsearch第一次遇到一个查询需要一个指定field的fielddata的时候,就会把索引的每个段中整个field加载到内存。对于小段,这是个可以忽略不计的时间,但是如果你有一些5G大小的段并且需要加载10GB的fielddata到内存里,这个过程需要数十秒,习惯于秒内响应时间的用户会被网突如其来的迟钝所打击。

有三种方法应对这种延迟尖峰:

Eagerly load fielddata(饿汉式(预)加载fielddata)

Eagerly load global ordinals(饿汉式(预)加载全局序数)

Prepopulate caches with warmers (使用warmer提前加载缓存)。

所有这些都是一个意思:预先加载fielddata到内存里,这样当用户需要执行一个搜索的时候就感受不到延迟了。

饿汉式(预)加载fielddata

首先是预先加载(而不是默认的延迟加载),当一个新的段形成时(无乱是刷新,写入或者是合并),可以预先加载的field会提前把段的fielddata加载到内存里,在这段可以用于搜索之前。

这意味着当你第一次查询的时候,如果碰到在这个段上,你不需要再触发加载fielddata的操作,它们已经在内存中了,这会防止你的用户遇到一些冷到缓存而发生延迟尖峰。

预先加载是基于每个field的,所以你可以控制哪些field进行预加载。

PUT /music/_mapping/_song

{

"price_usd": {

"type": "integer",

"fielddata": {

"loading" : "eager"

}

}

}

备注: 通过设置fielddata.loading: eager,告诉elasticsearch预先加载这个field的内容到内存里。

fielddata的加载可以设置成饿汉模式(预先加载)还是懒惰模式(延迟加载),使用update-mapping的api。

预先加载是简单对fielddata加载的开销的转移,从查询时间转义到刷新时刻。

大段的刷新时间会比小段的时间长,通常大段的产生都是由哪些已经可搜素的小段合并而来的,所以慢一点的刷新时间不是那么重要(译者注:意思是大段的刷新时间长不影响你的搜索,在大段合并成前的小段可以用于搜索)。

全局序数

其中一项用于减少string类型的fielddata占用内存的技术叫做序数。

假设我们有十亿条文档,每个文档都有一个status的field,只有三个值:status_pending, status_published, status_deleted,如果我们把所有的status加载到内存里,每个文档需要14-16byte,也就是说15GB

相反,我们可以确认这三个特殊的字符串,对他们排序,依次编号0,1,2

Ordinal | Term

-------------------

0 | status_deleted

1 | status_pending

2 | status_published

序号对应的字符串值要在序号列表中存储一次,每个文档只要使用他们的编号来表示他们所包含的值就可以了。

Doc | Ordinal

-------------------------

0 | 1 # pending

1 | 1 # pending

2 | 2 # published

3 | 0 # deleted

这个可以把15GB的内存占用减少到小于1GB

但是这里有个问题,记住fielddata缓存是针对每个段的,如果一个段包含两个状态-status_deleted 和 status_published,这个序号是(0 和1),如果其它段中有三个不同的状态,那相同的序号的含义在两个段中是不同的。

如果我们试图执行一个status 的field的汇总操作(aggregation ),我们需要在实际的字符串上进行汇总。以为着我们要在所有的段上识别出有相同值的文档,一个单纯的方式就是在每个段上进行汇总操作,从每个段上返回字符串的值,然后合并他们得到最终的结果,这样是可行的,这会很慢很耗CPU。

想反,我们实验了一个数据结构叫做全局序数,全局序号只是在fielddata之上,一小部分内存数据结构,把所有的段的唯一值存储在一个序号列表里,就像前面我们描述的那样。

现在,我们的汇总操作只要在全局序号上进行汇总,把序号转换成实际字符串,只要在最后一个汇总中进行就可以了,这大大提高了在只要三四个值的field上进行汇总(还有排序)操作的性能。

构建全局序数

当然,天下没有免费的午餐,全局序数是针对一个索引的所有段的,所以如果增加了一个段或者删除了一个段,这个全局序数都要进行重建,长袖需要读取每个段的每个唯一term。存储基数越大,唯一tems越多,这个过程会更长。

全局序数是创建在内存里的fielddata和doc values之上的,实际上,他们也是doc values性能表现的主要原因。

和fielddata的加载一样,全局序数的构建默认也是延迟进行的,当第一个请求需要fielddata时候,会触发全局序数的构建,和你的field的基数有关,这可能导致用户的一个延迟响应。一旦全局序数构建完成,他们将被使用,直到索引中的段发生变化:刷新,写入和合并。

饿汉式(预先加载)全局序数

PUT /music/_mapping/_song

{

"song_title": {

"type": "string",

"fielddata": {

"loading" : "eager_global_ordinals"

}

}

}

注:设置为eager_global_ordinals 也代表实现了预先加载fielddata。

就像预先加载fielddata一样,全局序数会在一个新的段可进行搜索之前进行构建。

注意:序数只用于字符串类型的field,数值类型(整型,地理位置,时间等)都不需要一个序数映射,因为他们自身就是一个内存的序数映射。

所以,你只能开启字符串类型的全局序数的预加载。

文档的值也可以有他们的全局序数:

PUT /music/_mapping/_song

{

"song_title": {

"type": "string",

"doc_values": true,

"fielddata": {

"loading" : "eager_global_ordinals"

}

}

}

注:这种情况,fielddata就不加载到内存里了,而是文档的values会被加载到系统级缓存里。

和fielddata的预加载不同,对全局序数的预加载会对数据的实时性有影响,队友一个很大基数的field,构建全局序数会导致数秒的延迟刷新,是把时间花在每次刷新上呢,还是每次刷新之后的第一次查询上面这是一个选择。如果你插入数据频繁,查询很少,最好是把代价花在查询时刻,而不是每次刷新上。

注意:让你的全局序号自己处理,如果你有一个很大基数的field,导致很长时候构建,你可以增加refresh_interval 配置,这样回增加全局序数的有效时间,减少CPU的利用率,同样构建全局序数的次数也会减少。

Index warmers(索引热身)

最后,我们到了index warmers,wamers可以提早加载fielddata和全局序数,但是他还有一个目的。一个索引的warmer允许你指定一个查询或者汇聚操作在你的新段可被查询之前执行,这个idea就叫做预热、或者叫暖身,缓存等,那你的用户就永远不会遇到延迟尖峰时刻了。

期初,这个warmers的最重要的用处是为了确保fielddata的预先加载,这通常是开销最大的部分,这是我们之前讨论的利用这个技术控制的最好的地方,然而,warmers可以用于构建filter 缓存,也可以用于预加载fielddata,这个目的随你选择。

先让我们注册一个warner再去讨论发生了什么:

PUT /music/_warmer/warmer_1

{

"query" : {

"filtered" : {

"filter" : {

"bool": {

"should": [

{ "term": { "tag": "rock" }},

{ "term": { "tag": "hiphop" }},

{ "term": { "tag": "electronics" }}

]

}

}

}

},

"aggs" : {

"price" : {

"histogram" : {

"field" : "price",

"interval" : 10

}

}

}

}

注:这表示在music索引上注册一个id为warmer_1的warmer,三大流行音乐流派的filter 缓存都会被预先创建,对price字段的fielddata和全局序数都会被预先加载

warmers是注册在一个特定的索引上面的,每一个warmer都有一个唯一的id,因为你可以为一个索引指定多个warmer。

然后你可以之低昂一个查询,或者多个查询,他包含查询语句,filters,aggregations,sort,脚本等有效的查询语句。重点是要注册那些你的用户将要进行,有代表性的查询,从而适当的缓存可以被预先加载。

当一个新的段产生的时候,elasticsearch就会执行你这些warmers里的查询语句。执行这些查询会导致缓存进行加载,只有索引warmers都被执行了,新的段才会变成可搜素状态。

注意:类似于预先加载,warmers 把对冷缓存的开销转移到了刷新时刻。当你注册了warmers,你必须是经过明智判断的。你可以增加成千上万个wamer确保预热所有的缓存,但是这将极大的增加一个新的段从创建变为可搜索的时间。

实践中,选择几条代表大部分用户的查询语句进行注册。

一些管理方面的细节(例如获取存在的warmer,删除warmer)就不在这里过多解释了,阅读warmer相关文档,获取其它细节。

智能网联汽车的安全员高级考试涉及多个方面的专业知识,包括但不限于自动驾驶技术原理、车辆传感器融合、网络安全防护以及法律法规等内容。以下是针对该主题的一些核心知识点解析: ### 关于智能网联车安全员高级考试的核心内容 #### 1. 自动驾驶分级标准 国际自动机工程师学会(SAE International)定义了六个级别的自动驾驶等级,从L0到L5[^1]。其中,L3及以上级别需要安全员具备更高的应急处理能力。 #### 2. 车辆感知系统的组成与功能 智能网联车通常配备多种传感器,如激光雷达、毫米波雷达、摄像头和超声波传感器等。这些设备协同工作以实现环境感知、障碍物检测等功能[^2]。 #### 3. 数据通信与网络安全 智能网联车依赖V2X(Vehicle-to-Everything)技术进行数据交换,在此过程中需防范潜在的网络攻击风险,例如中间人攻击或恶意软件入侵[^3]。 #### 4. 法律法规要求 不同国家和地区对于无人驾驶测试及运营有着严格的规定,考生应熟悉当地交通法典中有关自动化驾驶部分的具体条款[^4]。 ```python # 示例代码:模拟简单决策逻辑 def decide_action(sensor_data): if sensor_data['obstacle'] and not sensor_data['emergency']: return 'slow_down' elif sensor_data['pedestrian_crossing']: return 'stop_and_yield' else: return 'continue_driving' example_input = {'obstacle': True, 'emergency': False, 'pedestrian_crossing': False} action = decide_action(example_input) print(f"Action to take: {action}") ``` 需要注意的是,“橙点同学”作为特定平台上的学习资源名称,并不提供官方认证的标准答案集;建议通过正规渠道获取教材并参加培训课程来准备此类资格认证考试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值