赞
踩
对于 ES 的新用户来说,有一个常见的问题:要存储一批新数据时,应该在已有 index 里新建一个 type,还是给它新建一个 index?要想回答这个问题,我们必须先理解这两者是怎么实现的。
在过去,我们试图通过与关系数据库建立类比来使弹性搜索更容易理解:索引index
就像数据库一样,类型type
似于数据库中的表。这是一个错误:数据的存储方式是如此不同,以至于任何比较几乎都没有意义,这最终会导致在有害的情况下过度使用类型。
索引index
存储在一系列分片中,它们本身就是Lucene index。所以使用新索引应该注意:Lucene索引在磁盘空间,内存使用和使用的文件描述符方面有一个小而固定的开销。因此,单个大index比几个小index效率更高,Lucene index的固定开销更好地摊销在多个文档中。
另一个重要因素是如何搜索数据,虽然每个分片都是独立搜索的,但Elasticsearch
最终需要合并所有搜索分片的结果。例如,搜索10个index
,每个index
有5个分片,则协调搜索请求执行的节点将需要合并5x10 = 50个分片结果。在这里需要注意:如果有太多的分片结果要合并,或者运行了一个产生大量分片响应的大量请求,合并这些分片结果的任务会非常消耗CPU和内存资源。这也是提倡少用index
的原因。
使用type
允许我们在一个index
里存储多种类型的数据,这样就可以减少index
的数量了。在使用时,向每个文档加入_type
字段,在指定type搜索时就会被用于过滤。使用type的一个好处是,搜索一个index下的多个type,和只搜索一个type相比没有额外的开销 —— 需要合并结果的分片数量是一样的。
但是,这也是有限制的:
index
下的不同type
里有两个名字相同的字段,他们的类型(string, date 等等)和配置也必须相同。type
里存在的字段,在其他没有该字段的 type 中也会消耗资源。这是Lucene Index
带来的常见问题:它不喜欢稀疏。由于连续文档之间的差异太大,稀疏的 posting list 的压缩效率不高。这个问题在 doc value 上更为严重:为了提高速度,doc value 通常会为每个文档预留一个固定大小的空间,以便文档可以被高速检索。这意味着,如果 Lucene 确定它需要一个字节来存储某个数字类型的字段,它同样会给没有这个字段的文档预留一个字节。未来版本的 ES 会在这方面做一些改进,但是我仍然建议你在建模的时候尽量避免稀疏。[1]index
内的统计数据来决定的。也就是说,一个 type 中的文档会影响另一个 type 中的文档的得分。这意味着,只有同一个index
的中的 type 都有类似的映射 (mapping) 时,才应该使用 type
。否则,使用多个type
可能比使用多个index
消耗的资源更多。
这是个困难的问题,它的答案取决于你用的硬件、数据和用例。首先你要明白 type 是有用的,因为它能减少 ES 需要管理的Lucene Index
的数量。但是也有另外一种方式可以减少这个数量:创建 index 的时候让它的分片少一些。例如,与其在一个 index 里塞上 5 个 type,不如创建 5 个只有一个分片的 index。
在你做决定的时候可以问自己下面几个问题:
总之,你可能有点惊讶,因为 type 的使用场景没有你想象的多,这是正确的。由于我们上面提到原因,在一个 index 中使用多个 type 的情景其实很少。如果你的数据有不同的映射,那就给他们分配不同的 index。但是请记住,如果不需要很高的写入吞吐量,或者存储的文档数量不多,你可以通过减少 index 的分片来使集群中的分片数量保持合理。
[1] posting list 和 doc value 都是 Lucene 的压缩技术,原理是保存后一个文档和前一个文档的差异,而不是完整的文档。
1. ES 数据库的存储结构变化:去除了Type
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。