需手动配置index.slowlog.threshold.index.warn等参数并带单位(如1s),在elasticsearch.yml全局设置或通过api动态更新;日志级别、appender配置及轮转策略也需同步检查,否则日志不输出。

如何开启 Elasticsearch 的 index.slowlog.threshold.index.warn
慢查询日志不是默认打开的,得手动配。关键在 index.slowlog.threshold.index.warn 这类设置上——它控制索引写入阶段多慢才记日志,单位是时间字符串(比如 1s、500ms),不是毫秒整数。
常见错误是直接写 1000,结果没生效:Elasticsearch 会静默忽略非法值,日志照常不输出。必须带单位。
- 在
elasticsearch.yml里全局设(影响所有索引):index: slowlog: threshold: index: warn: 1s debug: 500ms - 或用 API 动态更新单个索引:
PUT /my-index/_settings { "index.slowlog.threshold.index.warn": "1s" } - 注意:该配置只对新写入的文档生效;已存在的索引操作不会回溯记录
slowlog 输出内容里哪些字段真正有用
日志本身格式固定,但多数人只扫一眼耗时就跳过,其实 source 和 types 字段才是定位根因的关键。
source 是原始 DSL 查询体(如果有的话),但会被截断;types 表示操作类型(index、update、delete),而真正容易被忽略的是 took_in_millis 和 processing_time_in_nanos 的差值——如果后者远大于前者,说明瓶颈不在网络或协调节点,而在本地 Lucene 写入(比如 merge 压力大、磁盘慢)。
- 查日志时别只 grep
"took",加一句grep -A 5 "source:"看上下文 - 如果
source是空或只有{},大概率是 bulk 请求里的某条出问题,得结合bulk的 response status 定位具体 doc - 日志中
index字段值可能和预期不符——某些插件或 alias 操作会让实际写入的索引名和请求路径不一致
为什么设置了 slowlog 却看不到日志
最常见原因是日志级别压得太低。Slowlog 默认走 index_indexing_slowlog.log,但它的输出受两层控制:一是配置里的 level(如 WARN),二是 logging.yml 中对应 appender 的 root level。
- 检查
config/logging.yml是否有这一行:logger.index_indexing_slowlog: DEBUG
(即使你设了warn,这里也得至少是WARN) - 确认
appender.rolling.strategy.action.condition.age.gte没把日志轮转得太激进——有些集群配成1d,结果日志刚生成就被删了 - 使用
_nodes/loggingAPI 实时验证配置是否加载成功:GET /_nodes/logging?pretty
,搜索"index_indexing_slowlog"看 level 是否匹配
bulk 写入场景下 slowlog 怎么对应到具体文档
bulk 请求是一次发多条,但 slowlog 只按整个请求记一条,source 字段里混着 N 条操作,根本分不清哪条拖慢了整体。
这时候不能只依赖 slowlog,得配合 profile API 或开启 index.indexing.slowlog.level 到 DEBUG,让每条子请求单独打日志(代价是 I/O 增加,仅临时开启)。
- 临时启用细粒度日志:
PUT /my-index/_settings { "index.indexing.slowlog.level": "debug" } - bulk 中每条操作的
index、update会在日志里带独立id和type(7.x 后type固定为_doc) - 注意:
profile对 bulk 不友好,建议先用小批量(如 10 条)复现,再开 profile 查time和breakdown
hot_threads 和 node stats 交叉看。










