# 分片的策略

**以下内容来自“运维那点事”， 原文链接：**<http://www.ywnds.com/?p=3476>

MongoDB的分片策略有两种：哈希分片和范围分片

## 范围分片

对于基于范围的分片，MongoDB按照片键的范围把数据分成不同部分。

![](http://darouwan.com/wp-content/uploads/2018/12/2018120203101249.png)

如上图，假设有一个数字的片键:想象一个从负无穷到正无穷的直线，每一个片键的值都在直线上画了一个点。MongoDB把这条直线划分为更短的不重叠的片段，并称之为数据块，每个数据块包含了片键在一定范围内的数据。在使用片键做范围划分的系统中，拥有”相近”片键的文档很可能存储在同一个数据块中，因此也会存储在同一个分片中。

注：当你选择的片键是单调递增的，类似MySQL的自增主键， 假如你插入了200个文档，到第100个文档由于达到阈值，文档分片了，但是你前面这100个文档都是在同一台机器，同一个分片上进行写入，所以会造成单点数据吞吐量过大。

详情参见：<https://docs.mongodb.com/manual/core/ranged-sharding/>

## 哈希分片

哈希分片的原理是将一个字段指定为哈希索引，再把该索引指定为分片键，从而实现数据的分片。

![](http://darouwan.com/wp-content/uploads/2018/12/2018120203015514.png)

基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀。对于基于哈希的分片，MongoDB计算一个字段的哈希值，并用这个哈希值来创建数据块。在使用基于哈希分片的系统中，拥有”相近”片键的文档很可能不会存储在同一个数据块中，因此数据的分离性更好一些。

注：

* 在使用散列索引当作分片键时，MongoDB会自动计算哈希值。&#x20;
* 在把字段设为哈希索引时，该字段的类型最好不要为浮点数，因为浮点数在MongoDB中会转化成64位整数，容易造成哈希碰撞（2.2, 2.3的哈希值是一样的）

详情参见：<https://docs.mongodb.com/manual/core/hashed-sharding/>

## 基于范围的分片方式与基于哈希的分片方式性能对比

基于范围的分片方式提供了更高效的范围查询，给定一个片键的范围，分发路由可以很简单地确定哪个数据块存储了请求需要的数据，并将请求转发到相应的分片中。不过，基于范围的分片会导致数据在不同分片上的不均衡。有时候，带来的消极作用会大于查询性能的积极作用。比如，如果片键所在的字段是线性增长的，一定时间内的所有请求都会落到某个固定的数据块中，最终导致分布在同一个分片中。在这种情况下，一小部分分片承载了集群大部分的数据，系统并不能很好地进行扩展。

与此相比，基于哈希的分片方式以范围查询性能的损失为代价，保证了集群中数据的均衡。哈希值的随机性使数据随机分布在每个数据块中，因此也随机分布在不同分片中。但是也正由于随机性，一个范围查询很难确定应该请求哪些分片，通常为了返回需要的结果，需要**请求所有分片**。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiehongxin.gitbook.io/mongodb/sharding/shard_strategy.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
