【问题标题】:Elasticsearch indexing performance getting worse with my own _id我自己的 _id 使 Elasticsearch 索引性能变差
【发布时间】:2016-10-07 16:05:02
【问题描述】:

我正在构建一个相当大的索引 - 大约 30 亿个文档,平均大小为 2KB,没有什么比父/子关系更有趣了。起初批量索引运行良好,但现在速度急剧下降。

不确定硬件信息对这个问题是否重要,但这里是:

集群当前位于具有 24 个内核、128GB RAM 和 RAID 10 阵列的单个服务器上,该阵列具有 7200K 磁盘和带 BBU 的硬件控制器。不幸的是,大部分 RAM 被其他守护进程占用(大约 80GB)。

以下是重要的(至少我是这么认为的):

我提供了我自己的 ID。我已经阅读了Choosing a fast unique identifier (UUID) for Lucene,这对我来说似乎都是合乎逻辑的。我的 ID 是 64 位整数,最终会是连续的,但由于各种原因,初始索引是使用完全随机的 ID 批量完成的。

起初我每秒索引大约 3000 个文档(瓶颈不是 ES,而是从其中提取文档的数据库)。目前,由于不断的查找,服务器几乎停止了 IO(99% 的读取)。我已经索引了大约 60% 的文档,这大约需要两周时间。

当这个初始索引完成时,我将只提供顺序 ID,其速率约为 100 文档/秒。这里的主要问题是 - 性能是否会像整个索引是使用顺序 ID 构建的一样好? 如果答案是否定的,那么我将放弃当前索引并创建一个新索引使用 ES 的默认 _id 字段,我的 ID 将在另一个字段中。当然,这需要对应用程序进行一些更改,但我的文档很少更新,所以应该不难。

=== 编辑 ===

我正在添加有关我的设置的更多信息:

分片数:6
ES_HEAP_SIZE:32g
映射(为简洁起见,不包括 PHP 数组、过滤器、分析器和标记器):

    'index' => 'articles',
    'body' => [
        'settings' => [
            'number_of_shards' => 6,
            'number_of_replicas' => 0,
            'refresh_interval' => -1,
            'analysis' => [
                'filter' => [
                ],
                'analyzer' => [
                ],
                'tokenizer'=> [
                ]
            ]
        ],
        'mappings' => [
            'article' => [
                '_source' => ['enabled' => false],
                '_all' => ['enabled' => false],
                '_analyzer' => ['path' => 'lang_analyzer'],
                'properties' => [
                    'lang_analyzer' => [
                        'type' => 'string',
                        'doc_values' => true,
                        'store' => false,
                        'index' => 'no'
                    ],
                    'date' => [
                        'type' => 'date',
                        'doc_values' => true
                    ],
                    'feed_id' => [
                        'type' => 'integer'
                    ],
                    'feed_subscribers' => [
                        'type' => 'integer'
                    ],
                    'feed_canonical' => [
                        'type' => 'boolean'
                    ],
                    'title' => [
                        'type' => 'string',
                        'store' => false,
                    ],
                    'content' => [
                        'type' => 'string',
                        'store' => false,
                    ],
                    'url' => [
                        'type' => 'string',
                        'analyzer' => 'simple',
                        'store' => false
                    ]
                ]
            ]
        ]
    ]

配置(elasticsearch.yml):

node.master: true
node.data: true
plugin.mandatory: analysis-kuromoji,analysis-icu,langdetect-1.4.0.2-1368fbe,analysis-smartcn
bootstrap.mlockall: true
action.disable_delete_all_indices: true;
index.merge.scheduler.max_thread_count: 1
indices.memory.index_buffer_size: 3gb
index.translog.flush_threshold_size: 1gb
index.store.throttle.type: none

我已经从主机中删除了其他服务,现在所有 128GB 内存都用于 ES。它现在在索引时不会进行任何读取 IO,因为索引是由操作系统缓存的。

我基本上是在索引具有自动增量 ID 的文档,从 MySQL 到给定的 ID,我已经写下了。这些文档不是按顺序索引的,而是在整个 ID 范围内非常随机的。在这个索引阶段没有重复的请求(更新)。

主要问题仍然存在:

当我完成对所有 ID 的批量索引直到我的阈值,然后开始仅按顺序索引新文档时,索引性能是否与使用顺序 ID 构建整个索引相同?

【问题讨论】:

  • 你在这方面的表现有什么成功吗?

标签: elasticsearch


【解决方案1】:

我的猜测是减速与提供您自己的 _id 字段无关。我建议观看有关为生产配置 ES 的视频,它讨论了许多需要更新的设置。主要是将机器 50% 的内存固定到 JVM。这对我们的生产至关重要。

http://www.elasticsearch.org/webinars/elasticsearch-pre-flight-checklist/

当然,您还应该在超过 1 台机器上拥有超过 1 个生产节点。 ES 建议在生产中至少有 3 个节点。

另一个考虑是单个索引中的 3B 记录是相当大的。您可能会从滚动索引(例如每 30 天的索引)中获得更好的性能,然后在需要时使用别名将所有滚动索引组合成一个可查询的索引。

祝你好运!

【讨论】:

  • 谢谢。我已经阅读了很多关于性能调整的内容。我会更新帖子的更多细节。
【解决方案2】:

据我所知,您的案例可能与时间序列数据有关,我们正在谈论 6Tb 的数据。

分片数

do not overshard your data。使其成为两台 CPU 内核较少的服务器,并创建两个具有一个副本的分片。这样如果一台服务器发生故障,您将有一些冗余。

时间序列用例

我假设,最常访问的数据是最近一两个月的数据。假设您有一个名为“events”的别名。它指向所有名为 events_2014_12events_2014_11events_2014_10events_2013events_2012 的索引> 等等。索引越大 - 添加新文档或搜索它所花费的时间就越多。使用month-based data,我认为底部的索引不会超过 100-300Gb。你可以阅读它here

_id 生成

ElasticSearch 始终确保标识符是均匀的。仅当您在另一个存储中有数据源时,预生成标识符才有意义。

其他

如果您想深入研究这项技术,我可以推荐 a blog of a company,它提供 ElasticSearch 即服务。

【讨论】:

  • 谢谢。我有 6 个分片,所以不会过度分片。这不是时间序列,而是文章,所以年龄不是标准。我需要我的 ID 才能将它们与我的主数据库相关联。我当然可以将它们添加为另一个字段,但我的主要目的是将它们添加为 _id 以不浪费任何空间。
  • 然后尝试通过ID分片数据并创建一些索引,这样你拥有的每个索引都不会大于500G
  • _timestamp 字段在 5.x 中被删除
猜你喜欢
  • 1970-01-01
  • 2012-10-09
  • 2021-11-13
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多