Elasticsearch搜索优化-自定义路由规划(routing)

在es的实践学习中,我觉得它的文档是最好的老师,所以先把这部分链接贴出来,本文只是引导,文档全是细节,还是推荐大家事后认真看看文档

Metadata fields-routing

在es搜索中,请求是先分发到所有分片,然后聚合结果返回,如果我们将相同业务领域的数据聚集到同一个或者少部分分片,搜索的时候只搜索这几个分片,那么将会减少机器压力,提高搜索性能。

没有指定路由的情况

在没有指定路由的情况,所有的数据是依据文档_id(_routing的默认为_id),然后套公式均匀的分发到分片中,公式如下:

//我这边用的是7.9.3版本,我看7.17的公式多加了一个num_routing_shards参数,分片算法改进但本质结果没有变。
shard_num = hash(_routing) % num_primary_shards

从公式中我们可以看到id的不同必然导致文档会分散到不同的分片中,这就是没有自定义路由的普遍情况。

指定路由的情况

新建索引

如何指定路由要分析产品需求和数据上的相通性,就拿商品搜索来说,商品分布在不同的门店,而同一门店的商品可能会有列表搜索,有了这么一个需求,那么同一门店的商品是不是放在一个分片里是最好选择?

分析好需求以后我们确定了针对门店编码做路由,首先我们简单建立一个索引

PUT ***/routing

{
  "settings": {
    "number_of_shards": "3",
    "number_of_replicas": "3",
    "index.routing_partition_size": "2",
    "index.number_of_routing_shards": "3"
  },
  "mappings": {
    "_routing": {
      "required": true
    }
  }
}

除了指定了常见的分片数,副本数,还有两个新的参数index.routing_partition_size
index.number_of_routing_shards,

index.routing_partition_size

当使用了路由,可以让路由相同的文档分配到同一个分片上,从而减少查询时需要的分片数,提高查询效率。但是使用该参数容易导致数据不平衡。为此,ES还提供了一个index.routing_partition_size参数,用于将路由相同的文档映射到不止一个分片上,默认值是1,这样一方面可以减少查询的分片数,另一方面又可以在一定程度上防止分片数据不平衡。引入该参数后计算公式如下

shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards

这个参数只是对上面公式的进一步延申,我在索引参数中设置了2,说明在这个3个分片的索引中,路由相同的文档分配到其中2个分片上,后面我们导入数据时看看效果。

index.number_of_routing_shards

当在es中使用自定义路由时,路由分片的数量(number_of_routing_shards)决定了有多少分片用于路由。如果不指定此设置,则无论设置的分区大小(routing_partition_size)是多少,都只使用一个分片进行路由。为了确保正确实现分区大小,请将number_of_routing_shards设置为索引中的主分片数(number_of_shards)。这将确保根据指定的路由分片大小(number_of_routing_shards)使用预期数量的分片(number_of_routing_shards)进行路由。

在很多资料中,只提了routing_partition_size但是没有提number_of_routing_shards,如果不设置number_of_routing_shards,routing_partition_size的作用就会失效,这里着重强调,我在例子中设置了3,跟主分片数量一样。

Unique IDs with custom routing

其次,mappings里_routing的required值为true,会让使用自定义路由时,每当保存、获取、删除或更新文档时,都必须提供路由值,否则报错。我们要明白一点,如果不强制设置这个必填,会导致一条数据在多个分片中出现,没错,连_id都会一模一样,因为在es机制中,不同的路由值下的_id才必须是唯一的。这一条规则(Unique IDs with custom routing)文档也有写清。

导入数据

同一个routing随意导入若干条数据,看看数据分片的情况

插入数据

POST http://***/routing/_doc?routing=107U

{
  "shopCode": "107U"
}

检查预期结果

查询分片情况:

GET 
http://***/_cat/shards/routing?v

可以看到在同一个路由的情况下,数据只分布在2个分片中,符合预期。

index   shard prirep state      docs store ip         node
routing 1     p      STARTED      13 5.1kb 10.6.11.20 node-2
routing 1     r      STARTED      13 5.1kb 10.6.11.20 node-1
routing 1     r      STARTED      13 5.1kb 10.6.11.20 node-3                     
routing 2     r      STARTED       7 4.8kb 10.6.11.20 node-2
routing 2     r      STARTED       7 4.8kb 10.6.11.20 node-1
routing 2     p      STARTED       7 4.8kb 10.6.11.20 node-3        
routing 0     r      STARTED       0  208b 10.6.11.20 node-2
routing 0     p      STARTED       0  208b 10.6.11.20 node-1
routing 0     r      STARTED       0  208b 10.6.11.20 node-3              

结语

自定义路由在用户了解查询需求和业务的基础之上,可以对查询性能进行优化,然而使用不当会导致数据不平衡,重复ID等问题。所以要充分了解其机制再去使用(这里再次推荐看下官方文档),避免反向优化。

你可能感兴趣的:(elasticsearch,elasticsearch,搜索引擎)