使用我自己的_id,Elasticsearch索引性能越来越差

时间:2015-01-12 14:49:28

标签: elasticsearch

我正在构建一个相当大的索引 - 大约30亿个文档,平均大小为2KB,没有像父/子关系这样的花哨。起初,批量索引运行正常,但现在它正在大幅放缓。

不确定硬件信息对于问题是否重要,但现在是:

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

这里有什么重要的(至少我是这么认为):

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

起初我每秒索引大约3000个文档(瓶颈不是ES,而是文档被拉出的数据库)。目前,由于常量查找,服务器几乎停止了IO(99%读取)。我已经将大约60%的文档编入索引,大约需要两周时间。

当这个初始索引完成时,我将只提供顺序 ID,其速率大约为100 docs / s。这里的主要问题是 - 性能是否会像使用顺序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
                    ]
                ]
            ]
        ]
    ]

Config(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,因为索引是由OS缓存的。

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

主要问题仍然存在:

  

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

2 个答案:

答案 0 :(得分:1)

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

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

当然,您还应该在多台计算机上生产多个节点。 ES建议生产中至少有3个节点。

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

祝你好运!

答案 1 :(得分:1)

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

分片数

do not overshard your data。使两个服务器具有较少的CPU核心,并使用一个副本创建两个分片。因此,如果一台服务器出现故障,您将获得一些冗余。

时间序列用例

我认为,最常访问的数据是最近一两个月。比方说,你有一个名为“events”的别名。它指向名为 events_2014_12 events_2014_11 events_2014_10 events_2013 events_2012 依此类推。索引越大 - 添加新文档或搜索它的时间就越多。使用month-based data我认为你不会在底部增长超过100-300Gb的索引。你可以阅读它here

_id generation

ElasticSearch始终确保标识符均匀。如果您在另一个存储中有数据源,那么预先生成标识符是有意义的。

其他

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