一口气看完 43 个关于 ElasticSearch 的使用建议( 五 )

  • 超时时间需要足够长,建议 60s 以上 。
  • 写入端尽量将数据轮询打到不同节点上 。
  • 29. 脚本刷大量数据,写入前调大 Refresh Interval,不建议将副本分片为 0,待写入完成后再调回来 。副本分片重新加入节点会触发副分片恢复 Recovery 流程,如果是大分片会影响集群性能 。
    四、索引创建分片30. 副本分片数大于等于 1 。高可用性保证 。增加副本数可以一定程度上提高搜索性能;但会降低写入性能,建议每个主分片对应 1-2 个副本分片即可 。
    31. 官方建议单分片限制最大数据条数不超过 2^32 - 1 。32. 索引主分片数量不要设置过大 。ES 创建好索引后,一般情况下不再动态调整主分片数量 。
    每个分片本质上就是一个 Lucene 索引,因此会消耗相应的文件句柄、内存和 CPU 资源 。
    ES 使用词频统计来计算相关性,当然这些统计也会分配到各个分片上,如果在大量分片上只维护了很少的数据 , 则将导致最终的文档相关性较差 。
    一般来说 , 我们遵循一些原则:
    • 读场景较多则可以设置少一点,写场景则可以设置多一些 。
    • 控制每个分片占用的硬盘容量不超过ES的最大 JVM 的堆空间设置(32G) , 因此 , 如果索引的总容量在 200G 左右,那分片大小在 7-8 个左右即可 。
    • 考虑一下 Node 数量,一般一个节点对应一台物理机,如果分片数远大于节点数,则一个节点上存在多个分片 , 一旦该节点故障 , 即使保持了1个以上的副本,同样有可能会导致数据丢失,集群无法恢复 。所以,一般都设置分片数不超过节点数的 3 倍 。
    33. 单个分片数据量不要超过 50GB 。单个索引的规模控制在 1TB 以内,单个分片大小控制在 30 ~ 50GB ,Docs 数控制在 10 亿内,如果超过建议滚动 。
    Mapping设计
    34. 避免使用字段动态映射功能,指定具体字段类型,子类型(若需要),分词器(特别有场景需要) 。35. 对于不需要分词的字符串字段,使用 Keyword 类型而不是 Text 类型 。36. ES 默认字段个数最大 1000 , 建议不要超过 100 。单个 Doc 在建立索引时的运算复杂度 , 最大的因素不在于 Doc 的字节数或者说某个字段 Value 的长度,而是字段的数量 。例如在满负载的写入压力测试中,Mapping 相同的情况下,一个有 10 个字段,200 字节的 Doc ,  通过增加某些字段 Value 的长度到 500 字节,写入 ES 时速度下降很少,而如果字段数增加到 20,即使整个 Doc 字节数没增加多少,写入速度也会降低一倍 。
    37. 对于不索引字段,Index 属性设置为 False 。在下面的例子中,Title 字段的 Index 属性被设置为 False , 表示该字段不会被包含在索引中 。而 Content 字段的 Index 属性默认为 True,表示该字段会被包含在索引中 。需要注意的是,即使 Index 属性被设置为 False,该字段仍然会被保存在文档中,可以被查询和聚合 。
    参考示例:
    {"mappings": {"properties": {"title": {"type": "text","index": false},"content": {"type": "text"}}}}38. 避免使用 Nested 或 Parent/Child 。Nested Query慢,Parent/Child Query 更慢,针对 1 个 Document,每一个 Nested Field 都会生成一个独立的 Document,这将使 Doc 数量剧增,影响查询效率尤其是 JOIN 的效率 。因此能在 Mapping 设计阶段搞定的(大宽表设计或采用比较 Smart 的数据结构) , 就不要用父子关系的 Mapping 。如果一定要使用 Nested Fields , 保证 Nested Fields字段不能过多 , 目前ES默认限制是Index.mapping.nested_fields.limit=50 。不建议使用 Nested , 那有什么方式来解决 ES 无法 JOIN 的问题?主要有几种实现方式: