Looking for elasticsearch Answers? Try Ask4KnowledgeBase
Looking for elasticsearch Keywords? Try Ask4Keywords

Elasticsearch指数和类型之间的差异


备注

很容易看到type类似于SQL数据库中的表,其中index是SQL数据库。但是,这不是一种接近type的好方法。

关于类型

实际上,类型实际上只是Elasticsearch: _type添加到每个文档的元数据字段。上面的示例创建了两种类型: my_typemy_other_type 。这意味着与类型相关联的每个文档都有一个额外的字段,自动定义为"_type": "my_type" ;这是使用文档编制索引,从而使其成为可搜索或可过滤的字段 ,但它不会影响原始文档本身,因此您的应用程序无需担心它。

所有类型都存在于同一索引中,因此位于索引的相同集合分片中。即使在磁盘级别,它们也存在于相同的文件中。创建第二种类型提供的唯一分离是合乎逻辑的。每种类型,无论它是否唯一,都需要存在于映射中,并且所有这些映射必须存在于集群状态中。这会占用内存,如果每种类型都是动态更新的,它会随着映射的变化而降低性能。

因此,最佳实践是仅定义单个类型,除非您确实需要其他类型。通常会看到需要多种类型的场景。例如,假设您有汽车索引。您可以使用多种类型对其进行细分:

  • 宝马
  • 烦扰
  • 本田
  • 马自达
  • 奔驰
  • 日产
  • rangerover
  • 丰田
  • ...

这样,您可以搜索所有汽车或按制造商按需限制。这两次搜索之间的区别很简单:

GET /cars/_search

GET /cars/bmw/_search

对Elasticsearch的新用户来说,不明显的是第二种形式是第一种形式的特化。它实际上被重写为:

GET /cars/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term" : {
            "_type": "bmw"
          }
        }
      ]
    }
  }
}

它只是过滤掉任何未使用值为bmw_type字段编制索引的文档。由于每个文档都以其类型索引为_type字段,因此这是一个非常简单的过滤器。如果在任一示例中都提供了实际搜索,则过滤器将根据需要添加到完整搜索中。

因此,如果类型相同,则提供单一类型(例如,本示例中的manufacturer )并且有效地忽略它会好得多。然后,在每个文档中,显式提供一个名为make的字段或您喜欢的任何名称 ,并在您想要限制它时手动过滤它。这会将映射的大小减小到1/n ,其中n是单独类型的数量。它确实为每个文档添加了另一个字段,这是为了简化映射。

在Elasticsearch 1.x和2.x中,这样的字段应该定义为

PUT /cars
{
  "manufacturer": { <1>
    "properties": {
      "make": { <2>
        "type": "string",
        "index": "not_analyzed"
      }
    }
  }
}
  1. 这个名字是任意的。
  2. 该名称是任意的如果您也想要它它可以匹配类型名称。

在Elasticsearch 5.x中,上面的代码仍然可以使用(它已被弃用),但更好的方法是使用:

PUT /cars
{
  "manufacturer": { <1>
    "properties": {
      "make": { <2>
        "type": "keyword"
      }
    }
  }
}
  1. 这个名字是任意的。
  2. 该名称是任意的如果您也想要它它可以匹配类型名称。

应该在索引中谨慎使用类型,因为它会使索引映射膨胀,通常没有太大的好处。你必须至少有一个,但没有任何东西说你必须有一个以上。

常见问题

  • 如果我有两个(或更多)类型大多相同但每个类型有一些唯一字段会怎么样?

在索引级别,存在正在与被稀疏地使用几个字段多种类型的,与几个不共享(意味着其它类型甚至从未共享一束非稀疏字段之间使用的一个类型之间没有差别采用现场(一个或多个))。

换句话说: 无论类型如何,稀疏使用的字段在索引上都是稀疏的。稀疏性不会因为它是以单独的类型定义而对索引有益 - 或者真正受到伤害。

您应该只组合这些类型并添加单独的类型字段。

  • 为什么单独的类型需要以完全相同的方式定义字段?

因为每个字段实际上只在Lucene级别定义一次,无论有多少类型。类型存在的事实是Elasticsearch的一个特征,它只是一个逻辑分离。

  • 我可以定义具有不同定义的相同字段的单独类型吗?

不。如果您设法在ES 2.x或更高版本中找到这样做的方法,那么您应该打开一个错误报告 。如前一个问题所述,Lucene将它们视为单个字段,因此无法使其正常工作。

ES 1.x将此作为隐式要求,允许用户创建条件,其中索引中的一个分片映射实际上与同一索引中的另一个分片不同。这实际上是一种竞争条件, 可能会导致意想不到的问题。

规则的例外情况

  • 父/子文档需要在同一索引中使用单独的类型。
    • 父母住在一种类型。
    • 孩子生活在一个单独的类型中(但每个孩子与其父母住在同一个碎片中)。
  • 非常小众的使用案例,其中创建大量的指数是不可取的,稀疏领域的影响优于替代方案。
    • 例如,Elasticsearch监控插件Marvel(1.x和2.x)或X-Pack监控(5.x +)监控Elasticsearch本身的集群,节点,索引,特定索引(索引级别)的变化,甚至是碎片。它可以每天创建5个以上的索引来隔离那些具有唯一映射的文档, 或者它可能违反最佳实践以通过共享索引来减少集群负载(注意:已定义映射的数量实际上是相同的,但是创建的索引的数量从n减少到1)。
    • 这是一种高级方案,但您必须考虑跨类型的共享字段定义!

指数和类型之间的差异 相关例子