【问题标题】:ElasticSearch retrieves documents slowlyElasticSearch 检索文档很慢
【发布时间】:2019-11-21 06:33:18
【问题描述】:

我正在使用 Java_API 从 ElasticSearch 中检索记录,在 Java 应用程序中检索 100000 个文档(记录/行)大约需要 5 秒。

ElasticSearch 慢吗?还是正常?

这里是索引设置:

我试图获得更好的性能但没有结果,这就是我所做的:

  • 将 ElasticSearch 堆空间设置为 3GB,它是 1GB(默认)-Xms3g-Xmx3g

  • 从 7200 RPM 硬盘迁移 SSD 上的 ElasticSearch

  • 只检索一个文件而不是 30 个

这是我的 Java 实现代码

private void getDocuments() {
        int counter = 1;
        try {
            lgg.info("started");
            TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
                    .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));

            SearchResponse scrollResp = client.prepareSearch("ebpp_payments_union").setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                    .setQuery(QueryBuilders.matchAllQuery())                 
                    .setScroll(new TimeValue(1000))
                    .setFetchSource(new String[] { "payment_id" }, null)
                    .setSize(10000)
                    .get();

            do {
                for (SearchHit hit : scrollResp.getHits().getHits()) {
                    if (counter % 100000 == 0) {
                        lgg.info(counter + "--" + hit.getSourceAsString());
                    }
                    counter++;
                }

                scrollResp = client.prepareSearchScroll(scrollResp.getScrollId())
                        .setScroll(new TimeValue(60000))
                        .execute()
                        .actionGet();
            } while (scrollResp.getHits().getHits().length != 0);

            client.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

我知道TransportClient 已被弃用,我尝试过 RestHighLevelClient 也是,但它不会改变任何东西。

您知道如何获得更好的性能吗?

我应该更改 ElasticSearch 中的某些内容还是修改我的 Java 代码?

【问题讨论】:

  • 每个请求需要 5 秒,它是您向 ES 集群发出的唯一请求吗?
  • 从3到7检索100000条记录变化的时间,一次只有一个请求

标签: performance elasticsearch bigdata java


【解决方案1】:

我看到了三个可能的优化轴:

1/ 使用 _doc 键对文档进行排序:

滚动请求具有优化,使它们在排序时更快 订单是_doc。如果您想遍历所有文档而不考虑 顺序,这是最有效的选择:

(documentation source)

2/ 减小页面大小,10000 似乎是一个很高的值。您可以使用 5000 /1000 等降低的值进行差异测试吗?

3/去掉源过滤

.setFetchSource(new String[] { "payment_id" }, null)

进行源过滤可能很繁重,因为弹性节点需要读取源,转换为Object然后过滤。那么你可以尝试删除它吗?网络负载会增加,但这是一个交易:)

【讨论】:

  • 感谢您的回答,按 _doc 排序已减少检索时间,知道它的大约。 2 秒。这很好,但我认为弹性可以做得更快。
  • 在禁用源过滤和减小大小方面运气好吗?
  • 减小大小从 1000 到 10000 没有任何变化,如果我设置低于 1000/500 它会减慢查询速度。 .setFetchSource 提供更好的性能,从 1 秒到 2 秒检索 100000 个文档更改
【解决方案2】:

如果不了解所涉及的所有内容,就很难进行性能故障排除/调整,但这似乎不是很快。因为这是一个单节点集群,你会遇到一些性能问题。如果这是一个生产集群,则每个分片至少有一个副本,也可以用于读取。

您可以做的其他一些事情:

  • 根据您最常搜索的属性为您的文档编制索引 - 这会将具有相同属性的所有文档写入同一个分片,因此 ES 读取工作量更少(这对您没有帮助,因为您只有一个分片)
  • 添加多个副本分片,以便您可以在集群中的节点之间扇出读取(再次强调,需要实际拥有一个集群)
  • 不要在与您的数据相同的盒子上担任主角色 - 如果您有一个中型或大型集群,您应该拥有既不是主也不是数据的盒子 而是您的应用连接的盒子以便他们可以管理搜索的元工作并使数据节点专注于数据。
  • 使用“query_then_fetch” - 除非您使用加权搜索,否则您应该坚持使用 DFS。

【讨论】:

  • 感谢您的回答,正如您所见,索引并不大,它 15000000 百万个文档 8GB,我应该为这么多的数据创建多个分片和副本吗?
  • 您应该始终(在生产环境中)为每个主分片至少拥有 1 个副本分片。除此之外,这实际上取决于您的特定系统,但通常越多越好。
  • 现在我有 15 个分片但速度没有改变,ElasticSearch 只在一台机器上运行,当它只在一台机器上运行时有副本是个好主意吗?
  • 不,尽管它应该在您的 SSD 上运行得非常快。我的答案更针对需要冗余和可靠性能的生产系统。您可能想尝试创建一个基于云的系统来测试,看看您是否仍然遇到性能问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多