Performance Considerations for Elasticsearch Indexing

原文地址:https://www.elastic.co/blog/performance-considerations-elasticsearch-indexing


Update November 2, 2015: If you're running Elasticsearch 2.0, check out this updated post about performance considerations for Elasticsearch 2.0 indexing. 

Elasticsearch users have delightfully diverse use cases, ranging from appending tiny log-line documents to indexing Web-scale collections of large documents, and maximizing indexing throughput is often a common and important goal. While we try hard to set good general defaults for "typical" applications, you can quickly improve your indexing performance by following a few simple best practices, described here.

To begin with, do not use a very large java heap if you can help it: set it only as large as is necessary (ideally no more than half of the machine's RAM) to hold the overall maximum working set size for your usage of Elasticsearch. This leaves the remaining (hopefully sizable) RAM for the OS to manage for IO caching. Make sure the OS is not swapping out the java process.

Upgrade to the most recent Elasticsearch release (1.3.2 at this time): numerous indexing related issues have been fixed in recent releases.

Before delving into the details, a caveat: remember that all the information here is up-to-date as of today (1.3.2), but as Elasticsearch is a fast moving target, this information may no longer be accurate when you, future Googler, come across it. If you are unsure, just come ask on the user's list.

Marvel is especially useful when tuning your cluster for indexing throughput: as you iterate on each setting described here you can easily visualize the impact of each change on your cluster's behavior.

Client side

Always use the bulk api, which indexes multiple documents in one request, and experiment with the right number of documents to send with each bulk request. The optimal size depends on many factors, but try to err in the direction of too few rather than too many documents. Use concurrent bulk requests with client-side threads or separate asynchronous requests.

Before you conclude indexing is too slow, be sure you are really making full use of your cluster's hardware: use tools like iostattop and ps to confirm you are saturating either CPU or IO across all nodes. If you are not then you need more concurrent requests, but if you hit EsRejectedExecutionException from the java client, or TOO_MANY_REQUESTS (429)HTTP response from REST requests, then you are sending too many concurrent requests. If you are using Marvel, you can see the rejection counts under the THREAD POOLS - BULK section of the Node Statistics Dashboard. It is usually not a good idea to increase the bulk thread pool size (defaults to the number of cores) as that will likely decrease overall indexing throughput; it is better to decrease client-side concurrency or add more nodes instead.

Since the settings we discuss here are focused on maximizing indexing throughput for a single shard, it is best to first test just a single node, with a single shard and no replicas, to measure what a single Lucene index is capable of on your documents, and iterate on tuning that, before scaling it out to the entire cluster. This can also give you a baseline to roughly estimate how many nodes you will need in the full cluster to meet your indexing throughput requirements.

Once you have a single shard working well, you can take full advantage of Elasticsearch's scalability and multiple nodes in your cluster by increasing the shard count and replica count.

Before drawing any conclusions, be sure to measure performance of the full cluster over a fairly long time (say 60 minutes), so your test covers the full lifecycle including events like large merges, GC cycles, shard movements, exceeding the OS's IO cache, possibly unexpected swapping, etc.

Storage devices

Unsurprisingly, the storage devices that hold the index have a huge impact on indexing performance:

  • Use modern solid-state disks (SSDs): they are far faster than even the fastest spinning disks. Not only do they have lower latency for random access and higher sequential IO, they are also better at the highly concurrent IO that is required for simultaneous indexing, merging and searching.
  • Do not place the index on a remotely mounted filesystem (e.g. NFS or SMB/CIFS); use storage local to the machine instead.
  • Beware virtualized storage, such as Amazon's Elastic Block Storage. Virtualized storage works very well with Elasticsearch, and it is appealing since it is so fast and simple to set up, but it is also unfortunately inherently slower on an ongoing basis when compared to dedicated local storage. In a recent informal test, even the highest performance provisioned IOPS SSD-backed EBS option was still substantially slower than the local instance-attached SSD, and remember that the local instance-attached SSD is still shared across all virtual machines on that physical machine so you will see otherwise inexplicable slowdowns if the other virtual machines on that physical machine suddenly become IO intensive.
  • Stripe your index across multiple SSDs by setting multiple path.data directories, or just configure a RAID 0 array. The two are similar, except instead of striping at the file block level, Elasticsearch "stripes" at the individual index files level. Just remember that either approach increases the risk of failure for a single shard (to trade off for faster IO performance) since the failure of any one SSD destroys the index. This is typically the right tradeoff to make: optimize single shards for maximum performance, and then add replicas across different nodes so there's redundancy for any node failures. You can also use snapshot and restore to backup the index for further insurance.

Segments and merging

Under the hood, newly indexed documents are first held in RAM by Lucene's IndexWriter. Periodically, when the RAM buffer is full, or when Elasticsearch triggers a flush or refresh, these documents are written to new on-disk segments. Eventually there are too many segments, and they are merged according to the merge policy and scheduler. This process cascades: the merged segments produce a larger segment, and after enough small merges, those larger segments are also merged. Here is a nice visualization of how this works.

Merges, especially large ones, can take a very long time to run. This is normally fine, because such merges are also rare, so the amortized cost remains low. But if merging cannot keep up with indexing then Elasticsearch will throttle incoming indexing requests to a single thread (as of 1.2) to prevent serious problems when there are far too many segments in the index.

If you see INFO level log messages saying now throttling indexing or you see segment counts growing and growing inMarvel then you know merges are falling behind. Marvel plots the segment count under the MANAGEMENT EXTENDEDsection of the Index Statistics dashboard, and it should grow at a very slow logarithmic rate, perhaps showing a saw-tooth pattern as large merges complete:

Why would merges fall behind? By default, Elasticsearch limits the allowed aggregate bytes written across all merges to a paltry 20 MB/sec. For spinning disks, this ensures that merging will not saturate the typical drive's IO capacity, allowing concurrent searching to still perform well. But if you are not searching during your indexing, search performance is less important to you than indexing throughput or your index is on SSDs, you should disable merge throttling entirely by setting index.store.throttle.type to none; see store for details. Note that prior to 1.2, there was a nasty bug that caused merge IO throttling to be far more restrictive than you asked for. Upgrade!

If you are unfortunately still using spinning disks, which do not handle concurrent IO nearly as well as SSDs, then you should set index.merge.scheduler.max_thread_count to 1. Otherwise, the default value (which favors SSDs) will allow too many merges to run at once.

Do not call optimize on an index that is still being actively updated, since it is a very costly operation (it merges all segments). However, if you are done adding documents to a given index, it is a good idea to optimize it at that point, since that will reduce resources required during searching. For example, if you are using time-based indices where each day's worth of logs is added to a new index, once that day has passed, it is a good idea to optimize the index, especially if nodes will hold many days worth of indices.

Here are some further settings to tune:

  • Tune your mappings to turn off any fields you do not actually need, such as disabling the _all field. For fields you would like to keep, you can also tune whether and how they are indexed or stored.
  • You may be tempted to disable the _source field, but its indexing cost is likely small (just stored, not indexed), and it has substantial value for future updates or for fully re-indexing a previous index, so it is typically not worth disabling unless disk usage is a concern, which it should not be since disk is relatively cheap.
  • If you can accept some delay in searching recently indexed documents, increase index.refresh_interval to 30s, or disable it entirely by setting it to -1. This allows larger segments to flush and decreases future merge pressure.
  • As long as you have upgraded to at least Elasticsearch 1.3.2, which fixes issues that could cause excessive RAM usage when flushes are infrequent, increase index.translog.flush_threshold_size from the default (currently 200 mb) to 1 gb, to decrease how frequently fsync is called on the index files.
    Marvel plots the flush rate under the MANAGEMENT section of the Index Statistics dashboard.
  • Use 0 replicas while building up your initial large index, and then enable replicas later on and let them catch up. Just beware that a node failure when you have 0 replicas means you have lost data (your cluster is red) since there is no redundancy. If you plan to call optimize (because no more documents will be added), it is a good idea to do that after finishing indexing and before increasing the replica count so replication can just copy the optimized segment(s). Seeupdate index settings for details.

Index buffer size

If your node is doing only heavy indexing, be sure indices.memory.index_buffer_size is large enough to give at most ~512 MB indexing buffer per active shard (beyond that indexing performance does not typically improve). Elasticsearch takes that setting (a percentage of the java heap or an absolute byte-size), and divides it equally among the currently active shards on the node subject to min_index_buffer_size and max_index_buffer_size values; larger values means Lucene writes larger initial segments which reduces future merge pressure.

The default is 10% which is often plenty: for example, if you have 5 active shards on a node, and your heap is 25 GB, then each shard gets 1/5th of 10% of 25 GB = 512 MB (already the maximum). After dedicated heavy indexing, lower this setting back to its default (currently 10%) so search-time data structures have plenty of RAM to use. Note that this is not yet a dynamic setting; there is an issue open to fix that.

The number of bytes currently in use by the index buffer was added to the indices stats API in 1.3.0. You can see it by looking at the indices.segments.index_writer_memory value. This is not yet plotted in Marvel and will be added in the coming version, but you can add a chart yourself (Marvel still collects the data).

Coming in 1.4.0, the indices stats API also shows exactly how much RAM buffer was allocated to each active shard asindices.segments.index_writer_max_memory. To see these values per-shard for a given index, use thehttp://host:9200/<indexName>/_stats?level=shards; this will return the stats per shard as well as the totals across all shards.

Use auto id or pick a good id

If you do not care what id your documents have, let Elasticsearch automatically assign them: this case is optimized (as of 1.2) to save an ID and version lookup per document, and you can see the performance difference in Elasticsearch'snightly indexing benchmarks (compare the Fast and FastUpdate lines).

If you do have your own ids, try to pick one that is fast for Lucene if that is under your control, and upgrade to at least 1.3.2 since there were further optimizations to id lookup. Just remember that java's UUID.randomUUID() is the worst choice for an id because it has no predictability or pattern on how ids are assigned to segments, causing a seek per segment in the worst case.

You can see the difference in indexing rate as reported by Marvel when using Flake IDs:

versus using fully random UUIDs:

Coming in 1.4.0, we have switched Elasticsearch's auto-generated IDs from random UUIDs to Flake IDs.

If you are curious about the low-level operations Lucene is doing on your index, try enabling lucene.iw TRACE logging(available in 1.2). This produces very verbose output but can be helpful to understand what is happening at the LuceneIndexWriter level. The output is very low-level; Marvel provides a much better real-time graphical view on what is happening to the index.

Scaling out

Remember, we focused here on tuning performance for a single shard (Lucene index) but once you are happy with that, where Elasticsearch really shines is in easily scaling out your indexing and searching across a full cluster of machines. So be sure to increase your shard count again (the default is currently 5), which buys you concurrency across machines, a larger maximum index size, and lower latency when searching. Also remember to increase your replicas to at least 1 so you have redundancy to hardware failures.

Finally, if you are still having trouble, get in touch, e.g. through the Elasticsearch user list. Maybe there is an exciting bug to fix (patches are always welcome!).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PCI Express(简称PCIe)架构是一种用于连接计算机内置设备的高速串行总线标准。在进行PCIe的物理电测试时,需要考虑以下几个方面。 首先,传输速率是PCIe物理电测试的一个重要考虑因素。PCIe标准定义了不同的传输速率,如2.5Gbps、5Gbps和8Gbps等。测试时需要确保信号能以指定的速率进行传输,而不产生数据错误或错误的传输速率。 其次,信号完整性是另一个需要考虑的因素。PCIe信号在传输过程中容易受到干扰,如时钟抖动、串扰和噪声等。在测试中需要检测和分析信号的完整性,确保它们能稳定地传输而不受到干扰。 第三,功耗和电源管理也是PCIe物理电测试中需要关注的方面。PCIe设备在工作期间会产生热量,而不正确的功耗管理可能导致设备过热或不稳定。测试时需要测量设备的功耗和电源管理功能,以确保其在不同工作负载下能够正常运行。 此外,电缆和连接器的质量也是物理电测试中需要考虑的因素之一。PCIe连接器的接触质量和电缆的传输性能直接影响了整个系统的稳定性和可靠性。测试时需要检查连接器和电缆的连接状态,并测试其传输性能以确保其质量。 最后,抗干扰能力也是PCIe物理电测试中一个重要的考虑因素。PCIe设备在实际使用中可能会受到其他电子设备或无线信号的干扰。因此,在测试中需要评估设备的抗干扰能力,确保其在干扰环境下仍能稳定工作。 综上所述,PCIe物理电测试需要考虑传输速率、信号完整性、功耗和电源管理、连接器质量以及抗干扰能力等因素。通过对这些方面的测试和评估,可以确保PCIe设备的可靠性、性能和稳定性。 ### 回答2: PCI Express(PCIe)架构是一种高速串行数据总线标准,用于计算机系统中的外部设备连接。在测试PCIe架构时,需要考虑一些物理电测试的因素。 首先,应该确保传输介质的质量和可靠性。PCIe使用不同版本的传输介质,如铜线缆或光纤。测试人员需要检查传输介质的物理状态,确保其没有损坏或其他问题,以确保数据传输的稳定性和可靠性。 其次,还需考虑电气特性。PCIe架构需要满足特定的电气规范,以确保信号的正确传输和接收。测试时应检查电压、电流和信号波形等电气特性是否符合规范。这包括测试电源电压稳定性、消耗功率以及时钟信号等。 第三,信号完整性也是一个重要的考虑因素。PCIe使用差分信号传输,在测试过程中需要检查信号的完整性。差分信号测试涉及测试信号的振幅、上升时间、下降时间和噪声等。通过测试信号完整性,可以确保数据的正确传输,减少丢失和误码等问题。 此外,还应考虑外部干扰的影响。外部干扰可能会导致信号质量下降,从而影响PCIe架构的性能。测试人员需要测试环境中的干扰情况,以及采取适当的措施来减少干扰对PCIe架构的影响,例如使用屏蔽措施或进行地线和屏蔽的良好连接。 总之,测试PCIe架构时需要考虑传输介质的质量和可靠性、电气特性、信号完整性以及外部干扰等因素。通过进行全面的物理电测试,可以确保PCIe架构在实际应用中的稳定性和性能。 ### 回答3: PCI Express(以下简称PCIe)架构是一种计算机总线标准,用于在计算机内部连接外部设备和其他组件。进行PCIe物理电测试时需要考虑以下几个方面。 首先,受电控制和供电电机应该被充分考虑。在进行物理电测试之前,需要确保PCIe接口和其他相关设备的电源系统能够稳定地工作,并能提供足够的电流和电压。这需要进行电感、阻抗和稳压控制等方面的测试,以确保电源系统的稳定性和可靠性。 其次,信号完整性也是物理电测试的重要考虑因素之一。信号完整性是指在信号从发送器到接收器过程中,保持信号的正确性和可靠性。为了确保信号的完整性,需要对信号传输线路的电阻、电容和传输延迟进行测试。此外,还需要检查信号的波形、噪音和抖动等参数,以评估信号的质量和稳定性。 另外,电磁兼容性(EMC)也是PCIe物理电测试的重要考虑因素之一。EMC测试是为了确保PCIe接口和其他设备在电磁环境中能够正常工作,且不会对其他设备产生干扰。在EMC测试中,需要检查设备的辐射和敏感度,以及接地和屏蔽的效果,以确保PCIe架构在各种电磁环境下都能保持稳定的工作状态。 最后,还需要考虑PCIe接口的机械强度和可靠性。这包括对接口连接器的插拔次数、连接器的保持力和连接器接触性能等方面进行测试,以确保PCIe接口在长时间使用中能够保持稳定的连接和可靠的传输性能。 综上所述,PCIe物理电测试涉及到电源控制、供电电机、信号完整性、电磁兼容性和机械强度等多个方面的考虑因素。通过对这些方面的测试和评估,可以确保PCIe架构在各种环境下都能够提供稳定、可靠的数据传输和设备连接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值