惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
U
Unit 42
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
Microsoft Azure Blog
Microsoft Azure Blog
有赞技术团队
有赞技术团队
Stack Overflow Blog
Stack Overflow Blog
爱范儿
爱范儿
博客园 - 司徒正美
Vercel News
Vercel News
I
InfoQ
GbyAI
GbyAI
C
Check Point Blog
B
Blog RSS Feed
Martin Fowler
Martin Fowler
B
Blog
MyScale Blog
MyScale Blog
腾讯CDC
博客园 - Franky
Blog — PlanetScale
Blog — PlanetScale
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 三生石上(FineUI控件)

jdhao's digital space

Conversion between base64 and OpenCV or PIL Image 腾讯云对象存储博客图床开启 CDN 加速(不需要购买额外域名) Search and Replace in Multiple Files in Vim/Neovim Change Table Column Width in LaTeX Image or Table Side by Side in LaTeX LaTeX 并排显示图像或表格 Firenvim: Neovim inside Your Browser Content inside HTML tags missing in Latest Hugo? Creating Markdown Front Matter with Ultisnips Labelme JSON 标注格式转 voc XML 格式 Nifty Nvim Techniques That Make My Life Easier -- Series 6 macOS 下如何为视频制作字幕 Running Command Asynchronously inside Neovim Resolving Merge Conflict after Git Stash Pop Pylint: command not found? A Hands-on Experience with Neovim's Built-in LSP Support How to Convert PDF to Images with Imagemagick 互联网上常用缩略语集锦 File Backup in Neovim Converting PDF Pages to Images with Poppler Nifty Nvim Techniques That Make My Life Easier -- Series 5 Neovim Configuration for System-wide Use How to sort a list of tuple or list in Python -- lambda or itemgetter? Building A Vim Statusline from Scratch 人类第一颗原子弹爆炸始末 Distributed Training in PyTorch with Horovod Learning Expect Programming Essential Knowledge about SSH Nifty LaTeX Techniques -- Series 1 更改 Adsense 邮寄地址,重新寄送 PIN
Speed up document indexing in Elasticsearch via bulk inde...
2024-07-27 · via jdhao's digital space

In Elasticsearch, there is index API where you can index a single document to an index.

However, if you have a lot of documents and index them with this API one by one, the indexing speed is quite slow.

For large number of document indexing, it is better to use the bulk API from the elasticsearch.helpers submodule. It has three different bulk method:

  • helpers.bulk()
  • helpers.streaming_bulk()
  • helpers.parallel_bulk()

If you have a lot of products, the official doc recommends using of streaming_bulk():

When errors are being collected original document data is included in the error dictionary which can lead to an extra high memory usage. If you need to process a lot of data and want to ignore/collect errors please consider using the streaming_bulk() helper which will just return the errors and not store them in memory.

Usually the bulk API is way faster than the sequential indexing method. Here is a short code snippet to benchmark the different ways of indexing:

import time
from contextlib import contextmanager

from elasticsearch.helpers import streaming_bulk, parallel_bulk


@contextmanager
def report_time(procedure_name):
    start = time.time()
    yield
    end = time.time()
    print(f"time spent for {procedure_name}: {end - start}")


def sequential_index(client, docs, index_name):
    for doc in docs:
        client.index(index=index_name, document=doc)


def bulk_index(client, docs, index_name, bulk_type):
    def gen_actions(docs):
        for i, doc in enumerate(docs):
            action = {"_id": i, "_index": index_name, "_source": doc}
            yield action

    if bulk_type == "streaming":
        for success, status in streaming_bulk(
            client, actions=gen_actions(docs), chunk_size=500
        ):
            if not success:
                print(status)

    if bulk_type == "parallel":
        for success, status in parallel_bulk(
            client, actions=gen_actions(docs), chunk_size=500
        ):
            if not success:
                print(status)


def recreate_index(client, index_name):
    if client.indices.exists(index=index_name):
        client.indices.delete(index=index_name)
    client.indices.create(index=index_name)


if __name__ == "__main__":
    n = 1000
    index_name = "my_index"
    # set up the client
    es_client = Elasticsearch(...)

    docs = []
    for i in range(n):
        doc = {"title": f"this is document {i}", "date": "2024-07-25"}
        docs.append(doc)

    recreate_index(es_client, index_name)
    with report_time("sequential indexing"):
        sequential_index(es_client, docs, index_name)

    recreate_index(es_client, index_name)
    with report_time("streaming bulk"):
        bulk_index(es_client, docs, index_name, "streaming")

    recreate_index(es_client, index_name)
    with report_time("parallel bulk"):
        bulk_index(es_client, docs, index_name, "parallel")

This is the testing result from my machine:

time spent for sequential indexing: 123.88939809799194
time spent for streaming bulk: 0.6672859191894531
time spent for parallel bulk: 0.45793724060058594

References#