12 es怎么解决深分页的问题及索引优化有哪些方法
Elasticsearch深分页问题解决方案
方案1:Search After(游标分页)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| // 首次查询(按时间倒序) GET /order_index/_search { "size": 20, "sort": [ { "create_time": "desc" }, { "id": "desc" } // 唯一排序字段保证稳定性 ] }
// 后续查询(携带上一页最后一条的排序值) GET /order_index/_search { "size": 20, "search_after": ["2025-01-01T00:00:00", "order_12345"], "sort": [ { "create_time": "desc" }, { "id": "desc" } ] }
|
后续查询(携带上一页最后一条的排序值)
优势:
仅扫描当前页数据,性能恒定(百万数据查询耗时<100ms)。
支持跨分片高效查询(结合您项目中分库分表同步ES的经验)
1 2 3 4 5 6 7 8 9 10 11 12 13
| // 初始化Scroll(适合全量数据导出) GET /order_index/_search?scroll=5m { "size": 1000, "sort": ["_doc"] }
// 后续遍历 GET /_search/scroll { "scroll": "5m", "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAA..." }
|
适用场景:
数据全量导出和非实时性要求高的后台任务
业务妥协与前端优化
限制最大分页深度:仅允许用户访问前1000页(如电商场景),后续需缩小查询范围(如按时间过滤)。
滚动加载(Infinite Scroll):结合search_after实现无感知分页(类似京东商品列表页)。
缓存热点数据:对高频访问的深分页结果(如Top 1000商品)缓存至Redis,减少ES压力
Elasticsearch索引优化方法
分片与副本策略
1 2 3 4 5 6 7 8
| PUT /order_index { "settings": { "number_of_shards": 6", // 按数据量估算(如单分片不超过50GB) "number_of_replicas": 1", // 生产环境建议至少1副本 "refresh_interval": "30s" // 写入高峰期调大,减少段合并开销 } }
|
优化收益:写入吞吐量提升(京东项目中日志采集场景实测提升40%)
Mapping设计:
1 2 3 4 5 6 7 8 9 10 11
| { "properties": { "order_no": { "type": "keyword" }, // 精确查询 "merchant_id": { "type": "keyword" }, // 路由字段(优化查询性能) "amount": { "type": "scaled_float", "scaling_factor": 100 }, // 避免浮点精度问题 "tags": { "type": "text", "fields": { "keyword": { "type": "keyword" } } // 支持聚合 } } }
|
最佳实践:
避免使用dynamic: true,严格定义字段类型(参考您项目中数据清洗规则配置)。
对分页排序字段(如create_time)禁用doc_values以节省内存(仅排序场景)
路由(Routing)优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| // 写入时指定路由(如merchant_id) PUT /order_index/_doc/1?routing=merchant_123 { "merchant_id": "merchant_123", "create_time": "2025-01-01" }
// 查询时携带路由 GET /order_index/_search { "query": { "term": { "merchant_id": "merchant_123" } }, "routing": "merchant_123" // 直接定位到目标分片 }
|
减少跨分片查询开销(适合项目中按商户分库的场景)
索引预过滤
1 2 3 4 5 6 7 8 9 10 11
| GET /order_index/_search { "query": { "bool": { "filter": [ // 不计算相关性得分,结果可缓存 { "range": { "create_time": { "gte": "2025-01-01" } } }, { "term": { "status": "completed" } } ] } } }
|
固定条件筛选(如订单状态、时间范围)
冷热数据分离
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // 按时间范围分索引(如order_2025Q1、order_2025Q2) PUT /order_2025Q1 { "settings": { "index.routing.allocation.require.box_type": "hot" // 热节点(SSD) } }
PUT /order_2024Q4 { "settings": { "index.routing.allocation.require.box_type": "warm" // 冷节点(HDD) } }
|
降低存储成本(冷数据迁移至廉价存储),提升热点数据查询性能(SSD加速)
总结:通过Search After替代传统分页、路由优化及冷热数据分离,结合您项目中分库分表同步ES的经验,可有效解决深分页性能问题。索引设计需严格定义Mapping、合理分配分片,并利用硬件资源分层存储