2014-10-17 15 views
6

Chúng tôi có trong cá thể ElasticSearch của chúng tôi khoảng 55.000.000 tài liệu. Chúng tôi có tệp CSV với user_ids, CSV lớn nhất có mục nhập 9 triệu. Tài liệu của chúng tôi có user_id là khóa, vì vậy điều này rất thuận tiện.Áp dụng "thẻ" cho hàng triệu tài liệu, sử dụng phương pháp hàng loạt/cập nhật

Tôi đang đăng câu hỏi vì tôi muốn thảo luận và có tùy chọn tốt nhất để thực hiện việc này, vì có nhiều cách khác nhau để giải quyết vấn đề này. Chúng tôi cần thêm "nhãn" mới vào tài liệu nếu tài liệu người dùng chưa có tài liệu, ví dụ: gắn thẻ người dùng bằng "stackoverflow" hoặc "github".

  1. Có điểm cuối cổ điển partial update. Điều này nghe có vẻ chậm như chúng ta cần phải lặp lại hơn 9 triệu user_ids và đưa ra lời gọi api cho mỗi người trong số họ.
  2. bulk request, cung cấp một số hiệu suất tốt hơn nhưng với giới hạn 1000-5000 tài liệu có thể được đề cập trong một cuộc gọi. Và biết khi lô quá lớn là kinda biết làm thế nào chúng ta cần phải tìm hiểu trên đường đi.
  3. Sau đó, có official open issue cho điểm cuối /update_by_query có rất nhiều lưu lượng truy cập, nhưng không có xác nhận nào được thực hiện trong bản phát hành chuẩn.
  4. Về vấn đề mở này, có đề cập đến một số update_by_query plugin cần xử lý tốt hơn, nhưng có các sự cố cũ và mở nơi người dùng đang phàn nàn về các sự cố về hiệu suất và vấn đề về bộ nhớ.
  5. Tôi không chắc nó có thể làm được trên EL, nhưng tôi nghĩ tôi sẽ tải tất cả các mục CSV vào một chỉ mục riêng biệt, và bằng cách nào đó sẽ tham gia hai chỉ mục và áp dụng tập lệnh sẽ thêm thẻ nếu chưa tồn tại.

Vì vậy, câu hỏi vẫn là cách tốt nhất để làm điều này, và nếu một số bạn đã làm trong quá khứ này, hãy đảm bảo bạn chia sẻ số/hiệu suất của mình và cách bạn sẽ làm khác đi lần này.

+0

câu hỏi thú vị; Tôi sẽ chọn tùy chọn # 2 trộn với tùy chọn # 5; 1k tài liệu cho mỗi yêu cầu là tốt; Tôi cũng sẽ tạo một tài liệu 55M duy nhất bởi user_id trống trước khi thêm nhãn mới và sau đó cập nhật tài liệu –

Trả lời

2

Sử dụng nói trên update-by-query plugin, bạn chỉ cần gọi:

curl -XPOST localhost:9200/index/type/_update_by_query -d '{ 
    "query": {"filtered": {"filter":{ 
     "not": {"term": {"tag": "github"}} 
    }}}, 
    "script": "ctx._source.label = \"github\"" 
}' 

Plugin update-by-truy vấn chỉ chấp nhận một kịch bản, tài liệu không cục bộ .

Đối với các vấn đề hiệu suất và bộ nhớ, tôi đoán điều tốt nhất là hãy thử.

0

Tôi muốn sử dụng API hàng loạt với thông báo trước rằng bạn nên cố gắng cập nhật từng tài liệu với số lần tối thiểu. Cập nhật chỉ là xóa nguyên tử và thêm và để lại tài liệu đã bị xóa dưới dạng bia mộ cho đến khi nó có thể được hợp nhất.

Gửi tập lệnh groovy để thực thi cập nhật có thể có ý nghĩa nhất ở đây, do đó bạn không phải tìm nạp tài liệu trước tiên.

+0

Cung cấp một phần tài liệu hiệu quả hơn so với tập lệnh. Tài liệu 'Update API' cung cấp ví dụ này:' curl -XPOST 'localhost: 9200/test/type1/1/_update' -d '{"doc": {"label": "github"}, "detect_noop": true } ''. Tuy nhiên, lưu ý rằng nó không thể nối thêm vào một mảng, nó chỉ có thể thiết lập các trường thành một giá trị đã cho hoặc một mảng các giá trị. – ofavre

+0

Chỉ cần thêm liên kết vào yêu cầu kéo của Nik - https://github.com/elastic/elasticsearch/pull/15125 –

0

Bạn có thể tạo mối quan hệ cha mẹ/con theo đó bạn có thể thêm loại 'thẻ' tham chiếu loại 'bài đăng' làm cha mẹ của nó. Bằng cách này, bạn sẽ không cần phải thực hiện reindex đầy đủ dữ liệu của bạn - chỉ cần lập chỉ mục từng thẻ thích hợp với ID bài đăng thích hợp.

+0

Cách tiếp cận này thực sự thú vị nếu tài liệu hoặc là khá lớn hoặc thường xuyên được cập nhật. Tuy nhiên trước khi chọn giải pháp này, bạn nên lưu ý rằng truy vấn cha-con đến với chi phí bộ nhớ khi truy vấn: tất cả các id mẹ được tải trong bộ nhớ trong khi thực hiện kết nối hiệu quả. Tùy thuộc vào nhu cầu hiệu suất, có thể hiệu quả hơn khi chỉ cập nhật tài liệu gốc một lần và cho tất cả. – ofavre

3

Trong khi chờ đợi bản cập nhật hỗ trợ truy vấn, tôi đã chọn cho:

  1. Sử dụng scan/scroll API để lặp qua các ID tài liệu mà bạn muốn gắn thẻ (related answer).

  2. Sử dụng bulk API để thực hiện partial updates để đặt thẻ trên mọi tài liệu phù hợp.

Bên cạnh đó tôi lưu trữ các dữ liệu thẻ (CSV) trong một loại doc riêng biệt, và truy vấn từ đó và tag tất cả các tài liệu mới khi chúng được tạo ra, ví dụ, để không phải chỉ số đầu tiên và sau đó cập nhật.

đoạn

Python để minh họa cho cách tiếp cận:

def actiongen(): 
    docs = helpers.scan(es, query=myquery, index=myindex, fields=['_id']) 
    for doc in docs: 
     yield { 
      '_op_type': 'update', 
      '_index': doc['_index'], 
      '_type': doc['_type'], 
      '_id': doc['_id'], 
      'doc': {'tags': tags}, 
     } 

helpers.bulk(es, actiongen(), index=args.index, stats_only=True) 
+0

Điều này về cơ bản là những gì plugin cập nhật theo truy vấn thực hiện, với nhiều chuyến đi vòng quanh mạng bổ sung. Mặc dù plugin chưa hỗ trợ một phần tài liệu, chỉ tập lệnh. – ofavre

+0

@Teka, rất vui được biết. Tôi đoán bạn có nghĩa là các plugin thực hiện điều này * mà không cần * nhiều vòng mạng không cần thiết. – Anton

+0

Đây thực sự là ý tôi. – ofavre

0

Một chuỗi rất cũ. Landed thông qua trang github để thực hiện "cập nhật bằng truy vấn" để xem nếu nó được thực hiện trong 2.0 nhưng không may mắn không. Nhờ plugin từ Teka, nếu bản cập nhật nhỏ, rất có thể làm được từ ý nghĩa nhưng trường hợp sử dụng của chúng tôi là cập nhật hàng triệu tài liệu hàng ngày dựa trên các truy vấn phức tạp nhất định. Cuối cùng, chúng tôi chuyển sang kết nối es-hadoop. Mặc dù cơ sở hạ tầng là một chi phí lớn lớn ở đây nhưng song song quá trình tìm nạp/cập nhật/chèn tài liệu thông qua tia lửa đã giúp chúng tôi dù sao đi nữa. Nếu bất cứ ai có bất kỳ gợi ý nào khác được phát hiện :) trong một năm qua, rất thích nghe về điều đó.

Các vấn đề liên quan