索引与分片设计实践 #
这篇更偏“工程实践”:不讲所有细节,只给你一套在大多数场景下都靠谱的索引设计思路,帮你少走弯路。
1. 先确定“索引边界”,再谈分片 #
思考顺序建议是:
- 这一坨数据是否应该是一个索引?
- 典型边界:数据生命周期、访问模式、隔离需求(权限/多租户)、硬件拓扑(可用区)
- 在它内部,需要多少主分片、多少副本?
常用的索引边界模式:
- 按业务域:
orders、products、logs_app、logs_security… - 按时间:
logs-2026.02.01、logs-2026.02.02(时间序列,见数据建模章节) - 按租户/大客户:大客户单独索引,小客户共享索引(见多租户建模章节)
建议:先控制“索引颗粒度”合理,再通过分片做水平扩展;不要指望一个索引撑住所有业务。
2. 分片与副本:从“目标分片大小”倒推 #
分片设计没有万能数字,但可以从一个直觉出发:希望单个分片的大小 & 负载落在一个可控区间内。实践中常见的经验值:
- 单分片 10–50GB 对大多数场景比较健康(结合你的磁盘/快照策略微调)
- 对于热点写入较猛的日志类索引,可以略小一点,便于滚动与恢复
一个简单的倒推流程:
- 用测试环境或历史数据估算:一个分片大概能承载多少数据 & QPS(参考“容量规划”章节)
- 预估未来一段时间的索引规模(例如:单日日志量、订单增长等)
- 用
总数据量 / 目标分片大小 ≈ 主分片数算一个初始值,再按机器数/故障域稍微调整
副本数则更多取决于:
- 可用性(能容忍多少节点故障)
- 读流量(读多写少时可以多一点副本当读节点)
生产上常见组合:
- 写多读少:
number_of_replicas = 0/1 - 读多写少:
number_of_replicas = 1+,甚至为查询集群设独立的 follower
3. 时间序列:按时间切索引,而不是疯狂加分片 #
日志、指标、行为埋点这些“时间序列”场景,最容易踩坑的设计就是:
一个索引,分片拉满,想靠加分片吃下所有历史。
更推荐的做法:
- 按时间切索引:天/周/月(
logs-2026.02.01之类) - 用别名组织“当前/最近 N 天/全部”视图:
logs_current→ 指向当天索引logs_last_7d→ 指向最近 7 个索引
- 数据退役时,按索引维度做:
- flush + close(冷数据仍保留)
- snapshot + delete(非常老的数据)
好处:
- 清理和归档成本都在“索引级别”,而不是“逐文档删除”
- 不需要在单索引内搞海量分片,恢复和迁移更安全
4. 多租户:一索引一大户,多小户共索引 #
多租户设计常见两极:
- 一租户一索引:隔离性好,适合少数大客户(数据量/查询压力足够大)
- 多租户共索引:通过字段 + routing + 查询过滤隔离,适合大量小客户
一个折衷方案:
- 为“大租户”单独建索引(甚至单独集群)
- “长尾小租户”共享一个或少数几个索引,通过
tenant_id字段 + alias/routing 做隔离
索引与分片设计时需要考虑:
- 是否需要“搬家”能力(从共享索引迁出到独立索引)
tenant_id是否作为 routing key(让同一租户数据尽量落在同一分片)
具体建模细节可参考数据建模章节的“多租户”部分。
5. 零停机演进:新索引 + 重建 + 别名切换 #
索引设计从来不是“一步到位”,业务演进到一定阶段,你几乎必然会遇到:
- 字段类型要改(
text↔keyword,数值精度调整) - 分析器要换(分词策略、同义词、归一化规则)
- 分片数要调整(原来的扩展因子不够用了)
这类变更不能在原索引上“硬改”,推荐统一走这条路线:
- 设计并创建新索引(
my_index_v2),带上新 Mapping 与 settings - 用
_reindex或 scroll + bulk 从旧索引迁移数据 - 用别名原子切换:
my_index从my_index_v1移除my_index新增指向my_index_v2
示意(别名切换):
POST /_aliases
{
"actions": [
{ "remove": { "index": "my_index_v1", "alias": "my_index" }},
{ "add": { "index": "my_index_v2", "alias": "my_index" }}
]
}
要点:
- 应用层只使用别名,不直接写死真实索引名
- 重建过程中可以双写/只读/灰度切换,具体策略根据业务而定
6. 索引与分片设计的一点 Checklist #
- 这一坨数据是不是应该拆成多个索引?(按业务域 / 时间 / 租户)
- 单分片目标大小大致是多少?(结合存储和恢复策略)
- 主分片数与副本数是如何依据容量 & HA 要求确定的?
- 是否为时间序列/多租户场景选用了合适的模式?
- 是否已经预留了“新索引 + 重建 + 别名切换”的演进路线?
下一步可以继续阅读:
参考手册(API 与参数) #
本篇更多讲的是“怎么设计”,如果你需要查具体的 API 与参数,可以参考: