分区、分片、段、副本:混用这四个词,召回掉 25%

发布时间:2026/11/3 8:25:10
分区、分片、段、副本:混用这四个词,召回掉 25% 版权与内容来源声明本文为原创整理。文中涉及官方文档、开源仓库、论文与公开报道的内容均在附表 A 中标注来源引用官方原文保持原样不作改写。文中命令、版本号与界面截图以本文成文时的实测/核验结果为准标注「待验证」的部分请以你本地环境实际输出为判断依据。本文不推荐任何不合规的软件获取方式也不对任何收益结果作承诺。转载请注明出处。一、混用的代价落在两本账上一条写几份、一次查几路一条写入到底落几份、一次全库检索要等几路是两个不同参数决定的数把其中一个当成另一个两本账就永远对不上。1.1 一次容量评审会上的原话评审会上记下一句「数据要到 3000 万条了先给它加三个副本扩一下容量。」这句话把两个方向不同的动作塞进了一句。副本是复制同一份数据多放几处单条写入的落盘份数与集群总存储都乘上副本数单机上的数据一份没少。分片是切分按主键把数据劈成几堆每台机器只拿一堆单机容量才真的降代价是每查一次要等 S 路。想扩容动分片想扛读、想容错动副本。两个动作说成一句话评审就过了账在做完之后才到。后面四章把这四个词拆开。先看拆错的两本账。1.2 实测4 片 3 副本单条落 3 份扇出 4 路 实测环境Python 3.13.12 / macOS (darwin) / numpy 2.5.4forshards,replicasin((1,1),(4,1),(4,3),(16,3)):print(分片 %2d × 副本 %d → 单条写入落盘 %d 份集群总存储 %d 倍全库检索扇出 %2d 路%(shards,replicas,replicas,replicas,shards))分片 1 × 副本 1 → 单条写入落盘 1 份集群总存储 1 倍全库检索扇出 1 路 分片 4 × 副本 1 → 单条写入落盘 1 份集群总存储 1 倍全库检索扇出 4 路 分片 4 × 副本 3 → 单条写入落盘 3 份集群总存储 3 倍全库检索扇出 4 路 分片 16 × 副本 3 → 单条写入落盘 3 份集群总存储 3 倍全库检索扇出 16 路三个数各归各的排表更清楚部署单条写入落盘集群总存储全库检索扇出1 片 × 1 副本1 份1 倍1 路4 片 × 1 副本1 份1 倍4 路4 片 × 3 副本3 份3 倍4 路16 片 × 3 副本3 份3 倍16 路4 片那一行最能说明问题分片数 1 涨到 4单条写入还是 1 份、总存储还是 1 倍变的只有扇出1 路变 4 路。副本那两行反过来——副本 1 加到 3单条写入 1 份变 3 份、总存储 1 倍变 3 倍扇出不动。副本放大写入与存储分片放大扇出谁都不能替谁。把副本当扩容磁盘翻倍而容量不变把分片当冗余故障域反而变大——数据拆到更多机器上任何一台掉线都少一部分数据冗余只能靠副本。1.3 四个参数各管一段写入、存储、扇出、可见性互不替代四个参数各有一个数字对应改哪个动的就是那一列副本数单条写入落盘几份、总存储几倍、读并发几路。不动扇出也不动单机数据量。分片数扇出几路、单机数据量缩到几分之一。不动写入份数一条数据只进一个分片也不动总存储。分区键读的可见范围。带上分区名只有那个分区的数据进入检索写入份数与总存储不变。段策略一次查询要扫几个数据文件也就是固定成本的下限。每片名额是查询参数管召回与候选数第三章单独算。回到评审会那句「加三个副本扩一下容量」说的是副本想要的是分片。副本加上去单条写入 1 份变 3 份、总存储 1 倍变 3 倍每台机器上的数据一份没少让它变少的是分片数。二、分区按业务切减的是读分区是给查询做减法它减掉的是「不必读的那部分」写入份数与磁盘占用一份不减。2.1 官方文档把两者的分工写成了一句话Milvus 术语页给 Partition 的定义只有一句A partition is a division of a collection.同一页紧接着写each partition can contain multiple segments.到 Shard 词条两者的分工被压进一句Partitioning works to reduce read load by specifying a partition name, while sharding spreads write load among multiple servers.这句适合抄进评审材料。reduce read load 与 spreads write load 是两个动词、两个宾语分区动读分片动写。分开之后「加三个副本扩容量」这种句子就站不住脚。2.2 分区省下的是「不读」不是「不存」分区键是业务维度租户、业务线、时间片、文档来源。查询时带上分区名范围就缩到那一个分区。关键在「带上」两个字。不指定分区名引擎照样在全集里扫一遍。判断分区有没有用只需一句生产环境的查询里有没有稳定带上分区名。带得上读范围按分区数缩小带不上你只多维护一层元数据还多出一堆段第四章。写侧完全不受益。一条数据进哪个分区是写入时指定的进哪个分片是哈希算的。分区不改变写入落点也不是扩容手段。2.3 拿分区当权限、当扩容是两种最常见的误用分区不是权限。把租户甲的数据放进分区甲只让查询能跳过别的分区能发查询的人照样能在语句里写分区乙。隔离要在接口层做分区帮不上。分区也不是扩容。加了四个分区单机磁盘一点没降数据还在同一批分片上。判断办法很土加完分区看每台机器的磁盘水位没动就说明你动的是读路径。三、分片按主键哈希切分的是写分片键是主键的哈希它只有一个任务——把写入摊到多台机器上所以它天然没有业务含义也不可能被查询跳过。3.1 哈希切分只有负载含义没有业务含义数据落在哪个分片由哈希决定。写的时候你没法说「这条进第二片」查的时候也没法说「这次别查第三片」。这就是它和分区的分界线分区能被查询跳过分片不能。一条判据当场可用如果一条查询能靠「不查某个分片」省时间你手里那个东西不叫分片叫分区。3.2 实测16 片时召回仍是 1.000候选数涨到 160 实测环境Python 3.13.12 / macOS (darwin) / numpy 2.5.4# -*- coding: utf-8 -*-分片检索的名额怎么分每片取 k 个 vs 把 k 平均分给各片召回差多少。importnumpyasnp rngnp.random.default_rng(20261102)N,DIM,K50000,64,10CLUSTERS20centersrng.normal(size(CLUSTERS,DIM))*3.0labelsrng.integers(0,CLUSTERS,N)Xcenters[labels]rng.normal(size(N,DIM))# 20 个簇簇内紧、簇间远Qcenters[rng.integers(0,CLUSTERS,200)]rng.normal(size(200,DIM))*0.8deftopk(mat,q,k):d((mat-q)**2).sum(1)idxnp.argpartition(d,k)[:k]returnidx[np.argsort(d[idx])]truth[set(topk(X,q,K))forqinQ]X32X.astype(np.float32)Q32Q.astype(np.float32)print(N%d 条%d 维%d 个簇%d 条查询目标 top-%d%(N,DIM,CLUSTERS,len(Q),K))print(%-8s %-16s %-12s %-12s%(分片数,每片名额,召回率10,总候选数))forSin(1,2,4,8,16):shardnp.arange(N)%Sformodein(k,k/S):ifS1andmodek/S:continue# 只有 1 片时两种分法等价kkKifmodekelsemax(1,int(np.ceil(K/S)))rec,cand0,0forqi,qinenumerate(Q32):got[]forsinrange(S):idxnp.where(shards)[0]gotlist(idx[topk(X32[idx],q,kk)])candlen(got)reclen(truth[qi]set(got))/Kprint(%-9d %-17s %-13.3f %-12.0f%(S,%d 个/片%kk,rec/len(Q),cand/len(Q)))# 写入与副本副本数决定单条数据落几份分片数决定一次全库检索要等几路print(\n写入侧每条数据按主键落进一个分片副本再复制 R 份查询侧扇出 S 路)forS,Rin((1,1),(4,1),(4,3),(16,3)):print( 分片 %2d × 副本 %d → 单条写入落盘 %d 份集群总存储 %d 倍全库检索扇出 %2d 路%(S,R,R,R,S))N50000 条64 维20 个簇200 条查询目标 top-10 分片数 每片名额 召回率10 总候选数 1 10 个/片 1.000 10 2 10 个/片 1.000 20 2 5 个/片 0.864 10 4 10 个/片 1.000 40 4 3 个/片 0.864 12 8 10 个/片 1.000 80 8 2 个/片 0.874 16 16 10 个/片 1.000 160 16 1 个/片 0.750 16 写入侧每条数据按主键落进一个分片副本再复制 R 份查询侧扇出 S 路 分片 1 × 副本 1 → 单条写入落盘 1 份集群总存储 1 倍全库检索扇出 1 路 分片 4 × 副本 1 → 单条写入落盘 1 份集群总存储 1 倍全库检索扇出 4 路 分片 4 × 副本 3 → 单条写入落盘 3 份集群总存储 3 倍全库检索扇出 4 路 分片 16 × 副本 3 → 单条写入落盘 3 份集群总存储 3 倍全库检索扇出 16 路上面的读数表是本篇最反直觉的一段分片数从 1 加到 16只要每片取满 k 10 个「召回率10」一直是 1.000。掉的是总候选数从 10 涨到 160正好是分片数乘 10。分片不吃召回吃的是合并成本。下面那组把名额压到 k/S 的读数是同一件事的另一面召回掉到 0.864、0.864、0.874、0.750总候选数只有 10、12、16、16。8 片那行 0.874 比 4 片的 0.864 还高一点——不是名额给对了是簇分布让某些片恰好挤了更多近邻属抽样起伏不构成「分片越多召回越好」的证据。3.3 名额不能平摊因为全局 top-k 一定落在某一片的 top-k 里九行读数排成一张表规律比文字直白分片数每片名额召回率10总候选数每查一次要等的分片110 个/片1.000101210 个/片1.00020225 个/片0.864102410 个/片1.00040443 个/片0.864124810 个/片1.00080882 个/片0.8741681610 个/片1.00016016161 个/片0.7501616先把「每片取 k 个不掉召回」证掉一句话就够设全局第 i 名i ≤ k落在分片 s 上若该片内还有 k 个点比它更近这 k 个点的全局排名也都比它靠前i 就不是 i 了矛盾。所以全局 top-k 的每一条必然落在它所在分片的 top-k 内一条不漏。代价在另一头候选数变成 S × k合并排序成本线性涨。16 片时 160 个候选每个都要算距离、排序、去重再截前 10。召回没掉延迟掉了——这就是全部代价可预算。把 k 平摊才是丢召回的原因。名额 1 个/片时某个片里可能挤着 3 个真近邻你只准它交 1 个另外 2 个连面试机会都没有。分片越多这种挤压越严重8 片时 0.874 还撑得住16 片时掉到 0.750——相对 1.000 掉了 25%标题里那个数字就是它。这是「分片数」与「每片名额」被混成一个参数的结果——加片本为摊写入负载与单机容量顺手把每片的名额也分了召回替扇出买单。分片名额对照表可打印把分片数、每片名额、召回率、总候选数四列对照成一页调参前先照着对一遍。放在资料包里扫码即可获取四、段是自动生成的数据文件查询要扫每一个段不是切分维度是写入在存储层留下的文件它对查询的影响是「每个都要扫一遍」所以段数是被运维的对象不是被设计的对象。4.1 段由写入生成不归你指定Milvus 术语页的原句A segment is an automatically created data file that stores inserted data.同一页还写了查询怎么用它During a vector similarity search, Milvus examines each segment to compile search results.两个词值得圈出来automatically created 与 each。前者说明段是写入的副产物你控制不了它叫什么、何时生成后者说明查询要对每个段各动一次。4.2 段数涨涨的是查询的固定成本每个段有自己的索引与统计。一次查询要在每个段上各取一份候选再合并。段数 3 涨到 30固定开销跟着乘 10和数据总量无关。判据查询延迟跟着「最近一次导入量」抖动、不跟「数据总量」变化问题在段不在分片。批量导入后 P99 抬头、过一阵自己回落也是合并在追赶。分区也会把段切碎每个分区各自攒段30 个小分区就是 30 套小段。分区的读收益来自跳过成本来自段变碎两边一起算。4.3 把段当分片调是把运维旋钮拧成架构旋钮段名不稳定会随写入与合并变化写进查询条件等于埋雷。段该做的只有三件控住批量导入的批次、让合并跟上写入节奏、别在一个集合里堆几十个几百条的小段。反过来说容量不够、写入顶不住动段参数没用——那是分片的事查询慢但段已合并干净是扇出或名额的问题。四个旋钮各管一摊拧错了不报错只在账单和延迟上显形。五、副本是复制不是切分加副本换不到容量副本只把同一份数据多放几处换的是读吞吐与容错一份容量都换不来。5.1 Qdrant 的 6 与 12把两个参数摆在同一句话里Qdrant 分布式部署文档的原句This code sample creates a collection with a total of 6 logical shards backed by a total of 12 physical shards.同一页给了默认值By default, replication_factor is set to 1, meaning no additional copy is maintained automatically.6 与 12 的比值就是这份配置的 replication_factor逻辑分片是切分单位数据切 6 份物理分片是存储单元12 个。默认 1 意味着不主动设就没有额外副本——很多「上了三副本」的说法翻配置会发现还是 1。这也解释了副本为什么扩不了容量12 个物理分片装的是同一批数据的 2 份拷贝总盘 2 倍没有一份数据被挪到新机器上。容量靠逻辑分片数也就是切分本身。5.2 四个词的边界一张表管住概念管什么不管什么典型误用分区读的范围按业务维度把集合切开查询指定分区名即可跳过其余部分写入落点、单机容量、访问权限拿分区当租户隔离和扩容手段分片写的落点按主键哈希把数据摊到多个写节点分摊写入负载、压低单机数据量单条写入份数、总存储、容错把分片当冗余故障域变大或指望加片减少单条写入份数段存储层的数据文件写入自动生成查询要逐段扫描再合并切分维度、业务隔离、稳定标识把段名写进查询条件或靠调段参数解决容量问题副本可用性与读吞吐同一份数据多存几份故障时顶上数据切分、容量、备份语义说「加副本扩容量」以为默认就有多副本「不管什么」这一列比「管什么」更有用误用几乎全是把某个词的能力错记到另一个词头上。三种典型配错把副本当扩容。症状是总存储翻倍、单机数据量没动4 片 × 3 副本时单条写入落 3 份、总存储 3 倍扇出仍是 4 路。修法是加分片或换更大的盘不是改副本数。把分区当权限。症状是跨租户的数据「偶尔能查到」——带分区名查不到没带就全库。测试环境难复现因为脚本往往规规矩矩带了分区名。修法是在接口层做租户校验分区只当读优化用。把副本当备份。一条 delete 发下去删的是所有副本副本拦不住误删、误更新这类逻辑错误只拦硬件故障。备份要有独立的时间点副本只是同一时刻的多个拷贝。5.3 四条判断什么时候加分片什么时候加副本照条件对号别照直觉对号单机磁盘水位或写入 QPS 顶住、读没顶 → 加分片。代价是扇出变大候选数按片数线性涨每片名额别跟着改。读 QPS 顶住、单条延迟还能接受 → 先查 replication_factor 是不是默认值再谈加副本。加副本换并发读与故障切换不换容量。召回掉了、候选数不够 → 加每片名额不是加分片。名额给 k不给 k/S实测里 16 片 × 1 个/片 掉到 0.75016 片 × 10 个/片 仍是 1.000。查询能稳定带上业务键 → 用分区别加分片。分区不增加查询扇出还能整体跳过不相干的数据。停手条件两条候选数乘合并成本超过延迟预算时别再加分片改收名额或先合并段分片加上去后单条写入延迟没降说明瓶颈在副本同步或段合并继续加片只是把成本摊薄。四个词对应四个参数分区键、分片数、段策略、副本数。评审时谁把两个词说成一句话就当场拆开问「写入多落几份、查询多等几路」。四层切分参数速查卡分区键、分片数、段策略、副本数四个参数的取值区间与副作用列成一页改动前先核对。放在资料包里扫码即可获取附表 A本文引用事实与出处对照表事实出处一手来源本文位置A partition is a division of a collection.each partition can contain multiple segments.《Terminology》Milvus 官方文档https://milvus.io/docs/glossary.md第 2 章Partitioning works to reduce read load by specifying a partition name, while sharding spreads write load among multiple servers.《Terminology》Shard 词条Milvus 官方文档https://milvus.io/docs/glossary.md第 2 章A segment is an automatically created data file that stores inserted data.During a vector similarity search, Milvus examines each segment to compile search results.《Terminology》Segment 词条Milvus 官方文档https://milvus.io/docs/glossary.md第 4 章This code sample creates a collection with a total of 6 logical shards backed by a total of 12 physical shards.《Distributed deployment》Qdrant 官方文档https://qdrant.tech/documentation/guides/distributed_deployment/第 5 章By default, replication_factor is set to 1, meaning no additional copy is maintained automatically.《Distributed deployment》Qdrant 官方文档https://qdrant.tech/documentation/guides/distributed_deployment/第 5 章5 万条 64 维向量、20 个簇、200 条查询、top-10 条件下每片取 k 个时 1/2/4/8/16 片召回均为 1.000候选数 10/20/40/80/160k/S 时召回 0.864/0.864/0.874/0.750候选数 10/12/16/16本文实测脚本 work/exp1102/shard_k.py取数日期 2026-11-02第 3 章分片 1/4/4/16 与副本 1/1/3/3 组合下单条写入落盘 1/1/3/3 份、集群总存储 1/1/3/3 倍、全库检索扇出 1/4/4/16 路单条写入只进一个分片扇出才随分片数涨本文实测扇出算式见第 1 章实测块 2检索部分见脚本 work/exp1102/shard_k.py取数日期 2026-11-02第 1 章口径实测由脚本用固定随机种子生成 20 个簇的合成向量不来自真实业务库写入侧按「一条数据只进一个分片、副本再复制 R 份」的口径统计召回率只比较两种名额分法的相对差异数值随分布变化结论方向不变。写在最后这篇用到的资料写这篇文章时把 Milvus 和 Qdrant 的分片文档翻出来逐句核对又写了个小脚本把「每片取 k 个」和「把 k 平摊」两种名额分法跑了一遍对比顺手也整理了几份配套的东西大模型学习路线图从零基础到能自己动手做 Agent按阶段说明每一步该学什么、哪些可以先跳过《LangChain LangGraph MCP 智能体开发实战》视频课7 个模块从私有化部署、EmbeddingRAG 到 MCPAgent 全流程AI 大模型知识库在线可查Agent Skills 从入门到落地、Claude Skills 完全指南等专题按目录浏览即可640 套 AI 大模型行业报告 经典 PDF 书籍看行业落地案例和别人怎么做的时候用得上大模型零基础到精通教学视频跟着敲一遍比只读文档快得多资料是我自己整理的放在下面这个码上扫码即可获取添加时备注「AI」优先通过。资料按「先路线、再动手、最后查漏」的顺序整理好了建议先看学习路线那一份照着它挑一条适合自己当前基础的路径再往下看。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询