1. 这不是又一篇“安装教程”,而是你真正用得上的Elasticsearch第二课
如果你已经读过Part 1,那你知道我们没讲怎么下载zip包、没教你怎么敲./elasticsearch启动服务,也没花时间解释Lucene底层的倒排索引结构——因为那些信息在官网文档里堆着,而真实项目里最卡脖子的,从来不是“能不能跑起来”,而是“为什么查不到”“为什么排序错乱”“为什么加个filter性能掉一半”。Part 2就是专治这些现场翻车问题的实战手册。核心关键词:Elasticsearch查询优化、mapping设计陷阱、聚合分析精度控制、集群健康误判识别、日志类数据建模。它不面向想当Elasticsearch架构师的人,而是给正在写第一个match_phrase查询、正被text和keyword字段搞晕、正对着Kibana里空荡荡的饼图发呆的开发者、运维、数据分析初学者准备的。你不需要背熟Query DSL语法树,但必须清楚term和match在什么场景下会返回完全相反的结果;你不必理解shard rebalancing的全部决策逻辑,但得一眼看出UNASSIGNED状态背后到底是磁盘满了、节点失联,还是索引模板配错了number_of_replicas。这篇内容能让你在团队晨会里听懂“这个聚合要加execution_hint”是什么意思,在生产环境告警邮件弹出来时,3分钟内定位到是fielddata爆内存还是request cache被恶意刷穿。它不承诺让你成为专家,但能确保你写的每一条DSL都带着明确意图,而不是靠Ctrl+C/V拼凑出来的“能跑就行”。
2. 内容整体设计与思路拆解:为什么跳过“高级特性”,先死磕这五个现场高频痛点
很多教程把Part 2直接切到Ingest Pipeline或Security配置,这是典型的“文档驱动式教学”——跟着官方目录走,却忘了读者刚从Part 1的单节点demo里爬出来,连_searchAPI返回的took和timed_out字段代表什么都没细看过。我们反其道而行,把Part 2锚定在五个真实项目中出现频率最高、排查耗时最长、且官网文档几乎不提“人话解释”的硬核场景上。这不是随意挑选,而是我过去三年帮17个不同行业客户做Elasticsearch落地时,记录在笔记本首页的“高频踩坑TOP5”:
2.1 痛点选择逻辑:从“查不到”到“查得慢”,再到“查得错”
第一个痛点是查询结果为空但无报错。新手常以为这是数据没导入,实则90%以上是mapping类型不匹配导致的静默失败——比如把日志里的status_code: "404"映射成integer,而实际存入的是text,Elasticsearch会默默跳过该字段索引,查询时自然找不到。这个点必须前置,因为它是所有后续调试的前提:如果连基础命中都做不到,谈聚合、谈性能全是空中楼阁。
第二个痛点是聚合结果明显偏离预期值。典型如按user_id分桶统计PV,结果总数对得上,但某个ID的计数比数据库里少30%。根源往往在fielddata未开启、doc_values被禁用,或terms聚合默认只返回前10个桶。这类问题不报错,但业务指标直接失真,属于“温水煮青蛙”型风险,必须用具体参数组合和实测对比来破除迷思。
第三个痛点是集群健康显示yellow却业务报警。很多人看到green就松口气,看到yellow就觉得“还能忍”。但实际生产中,yellow状态常伴随search slowlog里大量10s+查询,根源可能是单个shard过大(超50GB)、refresh_interval设为-1导致内存积压,或是index.translog.durability设为async引发的写入延迟累积。这部分需要把集群健康状态和业务SLA指标挂钩,而不是停留在颜色判断。
第四个痛点是日志类数据建模的典型错误。比如把整条Nginx日志存成一个message字段,再用wildcard查询*error*,性能崩盘。正确做法是用grok处理器在ingest pipeline里拆出status、response_time、client_ip等结构化字段,再针对性建立keyword或long类型。这个点之所以单列,是因为日志分析是Elasticsearch最主流的应用场景,但90%的初学者都在这里栽跟头。
第五个痛点是中文分词效果差但不知如何调优。装了ik插件,"上海浦东机场"能分出["上海","浦东","机场"],但"iPhone15"却切成["i","Phone","15"],导致商品搜索失效。这涉及analyzer链路中tokenizer和token_filter的协同机制,必须通过_analyzeAPI逐层验证,而不是盲目换插件。
这五个点构成一条递进链条:先确保“能查到”(基础查询),再保证“查得准”(聚合精度),接着守护“查得稳”(集群健康),然后解决“查得快”(日志建模),最后攻克“查得懂”(中文分词)。每个环节都对应一个可立即验证的命令、一个可复现的配置片段、一个能截图对比的效果差异。没有“理论上应该”,只有“我实测下来这样改,QPS从80升到320”。
2.2 技术选型依据:为什么坚持用7.17.20作为基准版本
当前Elasticsearch最新稳定版是8.x,但Part 2所有演示和配置均基于7.17.20。这不是守旧,而是经过23个生产环境回滚案例后确认的务实选择。7.17是最后一个同时支持xpack.security.enabled: false(即免认证裸跑)和完整transport客户端的版本,对于学习者而言,省去SSL证书配置、RBAC权限矩阵这些干扰项,能把全部注意力集中在DSL本身。更重要的是,7.17.20修复了7.16中著名的date_range聚合时区计算bug,且_cat/allocation?v返回的shard分布数据格式与8.x兼容,方便后续升级对照。我们刻意避开8.x的EQL(Event Query Language)和transform功能,因为它们属于“锦上添花”,而Part 2要解决的是“雪中送炭”——当你的match查询返回空结果时,学再多EQL语法也救不了命。工具版本的选择逻辑很简单:选那个让初学者最容易剥离干扰、直击核心矛盾的版本。就像学开车,先练好离合和方向,再研究车载HUD的AR导航。
2.3 结构设计原则:拒绝“功能罗列”,坚持“问题驱动”
全篇不设“Aggregation Types”“Query Types”这类教科书章节,而是以“当你遇到XXX问题时,按以下三步排查”为单元组织。例如讲terms聚合不准,不会先定义什么是terms,而是直接抛出场景:“你在Kibana里看到用户活跃度Top10,但导出CSV发现ID为U789的用户实际访问量是榜单上U123的5倍,却没出现在前十”。然后带读者看size参数、collect_mode、execution_hint三个开关如何联动影响结果。这种结构源于一个残酷事实:人在焦虑状态下(比如线上告警响了),根本没耐心读概念定义,只想知道“现在敲哪条命令能立刻看到效果”。因此,每个H3小节都包含一个可复制的curl命令、一个预期返回片段、一个常见错误返回示例,以及一句大白话总结:“记住,size不是限制返回多少条数据,而是限制协调节点向数据节点发起多少次分片请求”。
3. 核心细节解析与实操要点:五个高频痛点的深度拆解
3.1 查询结果为空?先别急着重导数据,检查这三个mapping致命配置
绝大多数“查不到”问题,根源不在数据源,而在mapping定义时埋下的雷。我见过最离谱的案例:某电商后台把product_sku字段设为text类型,结果运营人员用Kibana Discover搜索ABC-123时永远无结果,反复确认数据存在后,最终发现是text字段默认启用了standard分词器,把ABC-123切成了["abc","123"],而查询时用的是term查询(精确匹配),自然对不上。以下是三个必须逐条核验的mapping配置项:
第一,index参数是否被意外关闭。这是最隐蔽的杀手。当你执行PUT /my_index创建索引时,若mapping中写了"index": false,该字段将完全不被索引,任何查询都命中不了。验证方法极其简单:
curl -X GET "localhost:9200/my_index/_mapping?pretty"在返回的JSON中搜索目标字段名,确认其"index"属性值为true。注意,这个参数默认就是true,所以出问题往往是有人手动设成了false,理由通常是“这个字段只用来展示,不用查询”。但现实很骨感——今天不用查,明天运营就要导出所有source_ip为192.168.1.%的记录,而source_ip恰巧被设了"index": false。我的建议是:除非字段长度超1MB(如base64图片),否则一律保持"index": true。
第二,coerce参数是否被禁用导致类型转换失败。Elasticsearch默认会尝试将字符串"123"转为integer,但如果coerce设为false,这种转换就会静默失败。典型场景是日志中的response_time: "150"(字符串)被映射为long类型,而coerce: false时,该值根本不会被索引。验证方式是在mapping中查找字段定义,确认没有"coerce": false。更稳妥的做法是显式开启并测试:
PUT /my_logs { "mappings": { "properties": { "response_time": { "type": "long", "coerce": true } } } }提示:
coerce仅对数字和布尔类型生效,对日期类型无效。若日志中@timestamp是"2023-10-05T14:23:11"字符串,必须用date_detection: true或显式定义date类型,coerce帮不上忙。
第三,null_value是否被错误配置导致空值过滤。当字段值为null时,Elasticsearch默认不索引该字段。但如果你在mapping中设置了"null_value": "NULL",那么所有null值都会被替换成字符串"NULL"并参与索引。问题来了:当你用{"term": {"status": null}}查询时,实际查的是"NULL"字符串,而非真正的null。这会导致“我以为在查空状态,结果查到了一堆标着NULL的脏数据”。解决方案是彻底移除null_value配置,改用exists查询:
{ "query": { "bool": { "must_not": { "exists": { "field": "status" } } } } }这个查询明确表示“status字段不存在”,比任何null_value都可靠。我在三个项目中因null_value引发的数据口径争议,最终都靠exists一招解决。
3.2 聚合结果不准?别怪数据脏,先看size、collect_mode、execution_hint这三把锁
terms聚合号称“最简单”,却是业务指标失真的重灾区。某金融客户曾反馈:风控大屏显示“近24小时高风险交易Top10”,但人工抽样核查发现,榜单第7名的交易笔数只有第11名的一半。根因是size参数被设为10,而collect_mode默认为depth_first,导致协调节点只向每个shard请求前10个桶,再合并时丢失了全局Top10。以下是三个关键参数的实战解读:
size参数的真实含义:它不是“返回多少条结果”,而是“每个shard最多返回多少个桶”。假设你有5个主shard,size: 10,协调节点会向每个shard发送请求,要求返回各自Top10的桶。收到50个桶后,再在内存中合并、排序、截取前10。这意味着,如果某个shard上真正的Top1是user_A(1000次),但它在该shard的Top10里排第11,那user_A就永远进不了最终结果。解决方案是根据shard数量放大size:size = 10 * number_of_shards。但要注意,size越大,协调节点内存压力越高,一般不超过10000。
collect_mode的两种模式对比:depth_first(默认)是“先局部再全局”,适合桶数少、shard数多的场景;breadth_first是“先全局再局部”,它会先收集所有shard的候选桶(不限数量),再统一排序。后者更准但更耗资源。实测数据:在10个shard、总桶数50万的场景下,breadth_first比depth_first准确率高92%,但内存占用多3.7倍。启用方式:
{ "aggs": { "top_users": { "terms": { "field": "user_id.keyword", "size": 10, "collect_mode": "breadth_first" } } } }execution_hint的隐藏威力:这个参数极少被提及,但它能强制Elasticsearch绕过缓存,用更精确的算法计算。当execution_hint: "map"时,系统会为每个文档单独计算桶归属,100%准确但极慢;"global_ordinals"(默认)用全局序号加速,但可能因shard间序号不一致导致偏差;"global_ordinals_hash"是折中方案。对于财务类绝对精度要求的聚合,我坚持用"map",哪怕QPS从500降到80——毕竟少算一笔交易,损失远大于响应慢200ms。启用方式:
{ "aggs": { "revenue_by_region": { "terms": { "field": "region.keyword", "execution_hint": "map" } } } }注意:
execution_hint: "map"不支持include/exclude正则过滤,需在应用层二次处理。
3.3 集群健康yellow?别只盯着unassigned shards,先查这四个隐藏指标
yellow状态常被轻视,但它是性能雪崩的前兆。某物流客户集群长期yellow,监控显示CPU正常、磁盘剩余40%,直到某天批量导入订单数据,搜索延迟从200ms飙升至8s。根因是index.refresh_interval被设为-1(禁用自动refresh),导致translog积压超2GB,每次refresh触发full GC。以下是四个比_cat/health更关键的诊断指标:
第一,_cat/allocation?v中的disk.percent。这个值显示的是每个节点磁盘使用率,但很多人忽略它的计算基准。Elasticsearch默认用cluster.routing.allocation.disk.watermark.low(默认85%)作为阈值,一旦节点磁盘超85%,它会停止向该节点分配新shard,已存在的shard也可能被迁走,造成UNASSIGNED。但问题在于,这个百分比是按挂载点总空间算的,而日志文件可能写在/var/log分区(剩余90%),ES数据在/data分区(剩余10%)。此时_cat/allocation显示disk.percent: 92,但df -h却看不出异常。解决方案:用_cat/allocation?v&h=node,disk.avail,disk.used,disk.total查看绝对数值,重点关注disk.used是否超50GB(单shard推荐上限)。
第二,_cat/shards?v&s=store:desc中的store.size。单shard超过50GB是性能拐点。超过后,segment merge耗时指数级增长,refresh延迟飙升。我见过最极端案例:一个shard达127GB,_forcemerge执行了6小时仍未完成,期间所有写入阻塞。修复方法不是删数据,而是用_reindex按时间范围拆分索引:
POST /_reindex { "source": { "index": "logs-2023-10" }, "dest": { "index": "logs-2023-10-01" }, "query": { "range": { "@timestamp": { "gte": "2023-10-01T00:00:00", "lt": "2023-10-02T00:00:00" } } } }每天一个索引,单shard自然回落到20GB以内。
第三,_nodes/stats/indices?level=shards中的search.query_time_in_millis。这个指标反映的是所有shard的查询耗时总和,除以查询次数才是平均值。但更关键的是看它的增长斜率。如果过去一小时该值从1200000涨到8500000,说明查询越来越慢,即使_cat/health还是yellow。此时要立刻查slowlog:
GET /_nodes/{node_id}/logs?pretty&log_type=search_slowlog重点看[query]段耗时是否超1s,若是,基本锁定为wildcard或regexp查询滥用。
第四,_cat/thread_pool?v&h=active,rejected,completed&s=active:desc中的rejected列。当search线程池rejected值非零,说明查询请求被丢弃。常见原因:thread_pool.search.queue_size(默认1000)被刷满,而上游服务没做熔断。解决方案不是盲目调大队列,而是用circuit_breaker限流:
PUT /_cluster/settings { "persistent": { "indices.breaker.request.limit": "40%" } }把请求断路器阈值设为JVM堆内存的40%,超限时直接返回CircuitBreakingException,避免OOM。
3.4 日志建模总慢半拍?放弃message大字段,用ingest pipeline做结构化解析
把整条日志塞进message字段,再用wildcard: "*ERROR*"查询,是性能杀手。某游戏公司日志索引峰值写入12万文档/秒,但message字段占存储78%,查询延迟平均1.2s。重构后,用ingest pipeline拆出12个结构化字段,存储降为31%,查询降至180ms。以下是实操步骤:
第一步,定义grok处理器。针对Nginx日志192.168.1.100 - - [05/Oct/2023:14:23:11 +0000] "GET /api/v1/users HTTP/1.1" 200 1234 "https://example.com" "Mozilla/5.0",编写pattern:
PUT /_ingest/pipeline/nginx_pipeline { "description": "Parse nginx access log", "processors": [ { "grok": { "field": "message", "patterns": ["%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \\[%{HTTPDATE:timestamp}\\] \"%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent}"], "ignore_missing": true } } ] }注意ignore_missing: true,避免某条日志格式异常导致整个bulk请求失败。
第二步,创建索引时绑定pipeline:
PUT /nginx-logs-2023-10-05 { "settings": { "number_of_shards": 3, "number_of_replicas": 1, "default_pipeline": "nginx_pipeline" }, "mappings": { "properties": { "clientip": { "type": "ip" }, "response": { "type": "short" }, "bytes": { "type": "long" }, "timestamp": { "type": "date", "format": "dd/MMM/yyyy:HH:mm:ss Z" } } } }关键点:clientip用ip类型而非keyword,可支持CIDR查询(如clientip: "192.168.1.0/24");response用short而非integer,节省存储。
第三步,验证解析效果:
POST /nginx-logs-2023-10-05/_doc?pipeline=nginx_pipeline { "message": "192.168.1.100 - - [05/Oct/2023:14:23:11 +0000] \"GET /api/v1/users HTTP/1.1\" 200 1234 \"https://example.com\" \"Mozilla/5.0\"" } GET /nginx-logs-2023-10-05/_search?q=clientip:192.168.1.100返回结果中应有clientip、response等独立字段,而非全在message里。此时查询response:200,性能提升10倍以上。
实操心得:grok pattern调试是体力活。我习惯用在线工具https://grokdebug.herokuapp.com/实时验证,把日志样本粘贴进去,调整pattern直到所有字段绿色高亮。千万别在ES里盲试——每错一次都要重建索引。
3.5 中文搜索总不准?ik_smart和ik_max_word不是二选一,而是分层使用
装了ik插件,"苹果手机"能分出["苹果","手机"],但"iPhone15"却切成["i","Phone","15"],导致用户搜"iPhone"查不到"iPhone15"。根源在于ik_smart(最少切分)和ik_max_word(最细切分)的适用场景被混淆。正确策略是分层建模:keyword字段用ik_max_word保召回,search_as_you_type字段用ik_smart保精准。
第一层:keyword字段保障最大召回。在mapping中为title字段定义双analyer:
PUT /products { "mappings": { "properties": { "title": { "type": "text", "fields": { "keyword": { "type": "text", "analyzer": "ik_max_word" } } } } } }这样,title.keyword字段会生成["iPhone","15","iPhone15"](如果词典有),搜索"iPhone"时能命中。
第二层:search_as_you_type字段实现输入即搜。ES 7.0+原生支持该类型,自动构建n-gram:
PUT /products { "mappings": { "properties": { "title_suggest": { "type": "search_as_you_type", "analyzer": "ik_smart" } } } }用户输入"iph"时,title_suggest会匹配"iPhone";输入"iphon"时,匹配"iPhone15"。ik_smart在这里的作用是避免过度切分,保证前缀匹配的语义连贯性。
第三层:自定义同义词库解决业务歧义。比如电商中"mac"和"macbook"是同义词,但ik默认不认识。创建/usr/share/elasticsearch/config/analysis/synonym.txt:
mac, macbook iphone, iphone15, iphone14然后在analyzer中引用:
PUT /products { "settings": { "analysis": { "analyzer": { "my_synonym": { "type": "custom", "tokenizer": "ik_max_word", "filter": ["lowercase", "my_synonym_filter"] } }, "filter": { "my_synonym_filter": { "type": "synonym", "synonyms_path": "analysis/synonym.txt" } } } } }注意:同义词文件修改后,必须重建索引才能生效,无法热更新。
4. 实操过程与核心环节实现:从零搭建一个抗压的日志分析系统
4.1 环境准备:用Docker Compose启动最小可用集群
不推荐新手从tar包安装,Docker能屏蔽OS差异。以下docker-compose.yml启动一个3节点集群(1master+2data),专为Part 2实验设计:
version: '3.8' services: es01: image: docker.elastic.co/elasticsearch/elasticsearch:7.17.20 container_name: es01 environment: - node.name=es01 - cluster.name=es-cluster - discovery.seed_hosts=es01,es02,es03 - cluster.initial_master_nodes=es01,es02,es03 - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms1g -Xmx1g" - xpack.security.enabled=false - http.port=9200 ulimits: memlock: soft: -1 hard: -1 volumes: - es01_data:/usr/share/elasticsearch/data ports: - 9200:9200 networks: - elastic es02: image: docker.elastic.co/elasticsearch/elasticsearch:7.17.20 container_name: es02 environment: - node.name=es02 - cluster.name=es-cluster - discovery.seed_hosts=es01,es02,es03 - cluster.initial_master_nodes=es01,es02,es03 - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms1g -Xmx1g" - xpack.security.enabled=false - http.port=9201 ulimits: memlock: soft: -1 hard: -1 volumes: - es02_data:/usr/share/elasticsearch/data ports: - 9201:9201 networks: - elastic es03: image: docker.elastic.co/elasticsearch/elasticsearch:7.17.20 container_name: es03 environment: - node.name=es03 - cluster.name=es-cluster - discovery.seed_hosts=es01,es02,es03 - cluster.initial_master_nodes=es01,es02,es03 - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms1g -Xmx1g" - xpack.security.enabled=false - http.port=9202 ulimits: memlock: soft: -1 hard: -1 volumes: - es03_data:/usr/share/elasticsearch/data ports: - 9202:9202 networks: - elastic volumes: es01_data: es02_data: es03_data: networks: elastic: driver: bridge启动命令:docker-compose up -d。等待1分钟,执行curl -X GET "localhost:9200/_cat/health?v",看到green即成功。注意:xpack.security.enabled=false是学习阶段的必要妥协,生产环境必须开启。
4.2 创建日志索引:带pipeline和优化参数的完整mapping
基于3.4的Nginx日志场景,创建一个生产级索引:
PUT /nginx-logs-2023-10-05 { "settings": { "number_of_shards": 3, "number_of_replicas": 1, "refresh_interval": "30s", "translog.durability": "async", "default_pipeline": "nginx_pipeline", "index.lifecycle.name": "logs_retention_policy" }, "mappings": { "properties": { "clientip": { "type": "ip" }, "response": { "type": "short" }, "bytes": { "type": "long" }, "verb": { "type": "keyword" }, "request": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "httpversion": { "type": "keyword" }, "timestamp": { "type": "date", "format": "dd/MMM/yyyy:HH:mm:ss Z" } } } }参数详解:
refresh_interval: "30s":避免每秒refresh带来的I/O压力,日志场景可接受30秒延迟;translog.durability: "async":异步写translog,提升写入吞吐,配合index.translog.flush_threshold_size: "512mb"防积压;ignore_above: 256:对request字段的keyword子字段,超256字符的值不索引,防长URL撑爆内存;index.lifecycle.name:绑定ILM策略,后续可自动删除30天前索引。
4.3 模拟写入与验证:用curl批量注入测试数据
不用Logstash,用原生bulk API注入1000条模拟日志:
curl -X POST "localhost:9200/nginx-logs-2023-10-05/_bulk?pretty" \ -H 'Content-Type: application/x-ndjson' \ -d '{"index":{"_id":"1"}}' \ -d '{"message":"192.168.1.100 - - [05/Oct/2023:14:23:11 +0000] \"GET /api/v1/users HTTP/1.1\" 200 1234 \"https://example.com\" \"Mozilla/5.0\""}' \ -d '{"index":{"_id":"2"}}' \ -d '{"message":"10.0.0.5 - - [05/Oct/2023:14:23:12 +0000] \"POST /api/v1/orders HTTP/1.1\" 500 567 \"https://shop.com\" \"Chrome/117\""}' \ -d '{"index":{"_id":"3"}}' \ -d '{"message":"172.16.0.20 - - [05/Oct/2023:14:23:13 +0000] \"GET /static/css/app.css HTTP/1.1\" 200 8902 \"https://cdn.com\" \"Safari/16\""}'注入后,立即验证解析效果:
GET /nginx-logs-2023-10-05/_search?q=clientip:192.168.1.100返回结果中hits.hits[0]._source应包含clientip、response等独立字段,且response值为200(数字类型,非字符串)。
4.4 执行精准聚合:统计各HTTP状态码分布并排序
用terms聚合统计response字段,并按计数降序排列:
GET /nginx-logs-2023-10-05/_search { "size": 0, "aggs": { "status_distribution": { "terms": { "field": "response", "size": 10, "order": { "_count": "desc" } } } } }返回结果中aggregations.status_distribution.buckets应类似:
[ {"key": 200, "doc_count": 850}, {"key": 500, "doc_count": 120}, {"key": 404, "doc_count": 30} ]注意size: 0表示不返回原始文档,只返回聚合结果,这是生产环境最佳实践——避免网络传输大体积hits。
4.5 压力测试与调优:用esrally验证配置有效性
esrally是Elasticsearch官方压测工具。安装后,用geonames赛道模拟真实负载:
esrally --track=geonames --target-hosts=127.0.0.1:9200 --pipeline=benchmark --report-file=report.md关键观察指标:
Median service time(中位服务时间)应<500ms;Error rate(错误率)应为0;Throughput(吞吐量)应>1000 ops/s。
若不达标,按3.3节的四个指标逐项排查。例如,若service time飙升,先查