Elasticsearch 提高建立索引的速度
- 使用Bulk Request。为了得到一次 bulk request 的最佳容量,可以建一个索引在单节点上并且单分片,依次以两倍的数量测试,100,200,400...直到建立索引的速度趋于平稳,此时的数量即为一次bulk request的最佳容量。但是这里有一个误区就是,并不是 bulk request 的容量越大越好(即使更大时建立索引的速度更快),因为当并发请求时,太大的bulk request会对集群造成更大的内存压力,所以建议每次bulk request请求不要超过 几十兆。
- 多线程或多进程去发送数据到ES。显然单线程不能使ES集群达到建立索引的最快速度,所以可以使用多线程或多进程来发送数据。除了可以更好的利用集群资源外,还有助于降低每次fsync的成本。此时需要注意ES返回TOO_MANY_REQUESTS (429)响应码,说明请求太频繁被ES拒绝了,这时需要降低请求速度或暂停请求(可以利用背压机制来调整请求速度)。跟获取一次 bulk request 的最佳容量的步骤相似,通过不断增加线程数直到IO/CPU达到饱和来获取最佳线程数。
- 增大 refresh interval。默认的 index.refresh_interval 为1秒,也就是说每秒会创建一个新的segment。refresh interval越小,segment就越小且越多,未来合并segment的压力就越大。
- 第一次加载数据时关闭 refresh 和 replicas。如果需要马上加载很大量的数据,可以关闭 refresh (index.refresh_interval = -1)和 replica (index.number_of_replicas = 0),这时建立所以会更快因为只需要建立一次索引。但是此时索引有丢失数据的风险(节点宕机),所以当初始化完以后需要马上把 index.refresh_interval 和 index.number_of_replicas 设置为原值。
- Disable swapping。You should make sure that the operating system is not swapping out the java process by disabling swapping.
- 给予超过机器一半的内存到filesystem cache。filesystem cache用于缓存IO操作。
- 使用ES自动生成的id。当为document显式设置id时,es会检查同一分片下是否有同样的id存在,当索引数据越来越多以后,这个检查的代价会越来越大。而使用es自动生成的id,会跳过这个检查。
- 使用更快的硬件。例如SSD
- 调增 Indexing buffer size。当节点进行繁重的建索引的任务时,需要保证足够大的indexing buffer给每一个分片(最多512MB)。可以通过设置 indices.memory.index_buffer_size 来调整节点的indexing buffer(默认是10%)。活跃的分片会占用更多的buffer。
参考文档
Tune for indexing speed