Как улучшить parallel_bulk из кода python для эластичной вставки?

#python #performance #elasticsearch

#python #Производительность #elasticsearch

Вопрос:

Я получил несколько документов (размером примерно 300o/doc ), которые я хотел бы вставить в свой ES index, используя библиотеку python, у меня получилась огромная разница во времени между кодом и использованием curl очевидно, что это нормально, но я хотел бы знать, можно ли увеличить время (по сравнению с соотношением времени)

  1. curl вставка параметра занимает около 20 секунд, а все время — 10 секунд (для печати результата, но после вставки данных через 20 секунд)

     curl -H "Content-Type: application/json" -XPOST 
            "localhost:9200/contentindex/doc/_bulk?" --data-binary @superfile.bulk.json 
      
  2. С помощью python опции я достиг как минимум 1min20, используя параметр 10000/16/16 ( chunk/thread/queue )

     import codecs
    from collections import deque
    from elasticsearch import Elasticsearch
    from elasticsearch.helpers import parallel_bulk
    
    es = Elasticsearch()
    
    def insert_data(filename, indexname):
        with codecs.open(filename, "r", encoding="utf-8", errors="ignore") as fic:
            for line in fic:        
                json_line = {}
                json_line["data1"] = "random_foo_bar1"
                json_line["data2"] = "random_foo_bar2"
                # more fields ...        
                yield {
                    "_index": indexname,
                    "_type": "doc",
                    "_source": json_line
                }
    
    if __name__ == '__main__':
     pb = parallel_bulk(es, insert_data("superfile.bulk.json", "contentindex"), 
                           chunk_size=10000, thread_count=16, queue_size=16)
     deque(pb, maxlen=0)
      

Факты

  • Я получил машину с 2 процессорами xeon 8-ядерными и 64 ГБ оперативной памяти
  • Я попробовал несколько значений для каждого [100-50000]/[2-24]/[2-24]

Вопросы

  • Могу ли я все еще улучшить время?

  • Если нет, должен ли я придумать способ записи данных в файл, а затем использовать процесс для curl команды?


Если я попробую только часть синтаксического анализа, это займет 15 секунд :

 tm = time.time()
array = []

pb = insert_data("superfile.bulk.json", "contentindex") 
for p in pb:
   array.append(p)
print(time.time() - tm)            # 15

pb = parallel_bulk(es, array, chunk_size=10000, thread_count=16, queue_size=16)
dequeue(pb, maxlen = 0)
print(time.time() - tm)              # 90
  

Комментарии:

1. Попробуйте разделить ваше приложение. На две части, создающие bulk и parallel_bulk. И поделитесь результатами с нами.

2. @ozlevka не уверен, что понимаю, что вы подразумеваете под основной частью, мой код уже разделен на генератор и параллельную основную часть

3. Я имею в виду отделить создание объемной структуры данных в памяти от отправки в elastic, чтобы указать, какая из двух частей является узким местом

4. @ozlevka готово, отредактировано и занимает 15-20 секунд для разбора части

5. И сколько времени занимает индексация?

Ответ №1:

После моего тестирования:

  1. curl работает быстрее, чем клиент python, очевидно, что curl реализован лучше.

  2. После дополнительного тестирования и игры с параметрами я могу сделать вывод:

    1. Производительность индекса Elasticsearch зависит от конфигурации индекса и всего кластера. Вы можете повысить производительность, правильно отображая поля в индекс.
    2. Мой лучший подход был на 8 потоках и 10000 элементах. Это зависит от конфигурации index.index_concurrency, которая по умолчанию равна 8.

    3. Я думаю, что использование многоузлового кластера с отдельным главным узлом должно повысить производительность.

    4. Для получения дополнительной информации вы можете прочитать отличную статью из 2 частей, которую я нашел: здесь и здесь