2016-10-18 28 views
6

Một phần biểu đồ của tôi được tạo bằng cách sử dụng kết hợp khổng lồ giữa hai bộ sưu tập lớn và tôi chạy nó mỗi khi tôi thêm tài liệu vào bộ sưu tập. Truy vấn được dựa trên older post.ArangoDB: Chèn làm hàm truy vấn bằng ví dụ

FOR fromItem IN fromCollection 
    FOR toItem IN toCollection 
     FILTER fromItem.fromAttributeValue == toItem.toAttributeValue 
     INSERT { _from: fromItem._id, _to: toItem._id, otherAttributes: {}} INTO edgeCollection 

Việc này mất khoảng 55.000 giây để hoàn thành tập dữ liệu của tôi. Tôi hoàn toàn sẽ hoan nghênh các đề xuất để làm nhanh hơn.

Nhưng tôi có hai vấn đề liên quan:

  1. Tôi cần một upsert. Thông thường, upsert sẽ ổn, nhưng trong trường hợp này, vì tôi không có cách nào để biết chìa khóa ở phía trước, nó sẽ không giúp tôi. Để có được chìa khóa lên phía trước, tôi sẽ cần phải truy vấn bằng ví dụ để tìm chìa khóa của cạnh khác nhau, hiện tại. Điều đó có vẻ hợp lý miễn là nó không giết hiệu suất của tôi, nhưng tôi không biết làm thế nào trong AQL để xây dựng truy vấn của tôi có điều kiện để nó chèn một cạnh nếu cạnh tương đương chưa tồn tại, nhưng không có gì nếu cạnh tương đương không tồn tại. Tôi có thể làm cái này như thế nào?
  2. Tôi cần phải chạy điều này mỗi khi dữ liệu được thêm vào bộ sưu tập. Tôi cần một cách để chạy điều này chỉ trên các dữ liệu mới nhất để nó không cố gắng tham gia toàn bộ bộ sưu tập. Làm thế nào tôi có thể viết AQL cho phép tôi chỉ tham gia các bản ghi mới được chèn vào? Chúng được thêm vào với Arangoimp và tôi không đảm bảo thứ tự chúng sẽ được cập nhật, vì vậy tôi không thể tạo các cạnh cùng lúc khi tạo các nút. Làm cách nào để tôi chỉ có thể tham gia dữ liệu mới? Tôi không muốn chi tiêu 55k giây mỗi khi một bản ghi được thêm vào.
+1

Tôi đã thực hiện truy vấn trong cơ sở dữ liệu khác với cùng thách thức, làm cách nào để giảm kích thước của tập dữ liệu khi liên kết lại dữ liệu. Giải pháp làm việc cho tôi là thêm một trường được gọi là 'linked = false' trong cả bộ sưu tập' fromCollection' và 'toCollection'. –

+1

... Sau đó, khi bạn chèn tài liệu mới vào bộ sưu tập, bạn luôn đặt 'liên kết' thành' false'. Khi bạn liên kết các tài liệu, bạn cũng quay lại và đặt 'linked' thành' true'. Để tăng tốc, bạn cũng sẽ muốn đặt chỉ mục trên 'liên kết'. Bạn sẽ thấy điều này làm tăng tốc độ xử lý của bạn mặc dù nó sẽ vẫn còn chậm trong lần đầu tiên bạn làm điều đó, vì mọi thứ sẽ có giá trị 'linked = false'. –

+1

Bạn có thể viết một ứng dụng Foxx để làm điều đó cho bạn, tôi ghi lại một ví dụ ứng dụng Foxx cho câu hỏi của người khác, nó có sẵn [ở đây] (http://stackoverflow.com/questions/39897954/arangodb-aql-recursive-graph- traversal) trên StackOverflow. Bạn nên dành chút thời gian để tìm hiểu Foxx vì nó có thể tốt đẹp và nhanh chóng và một chức năng giống như những gì bạn mô tả là một trường hợp sử dụng hoàn hảo. Hàm này thậm chí không cần bất kỳ tham số nào, nó chỉ chạy và nó sẽ chỉ quét các bản ghi đó bằng 'linked = false'. –

Trả lời

8

Nếu bạn chạy truy vấn của bạn như được viết mà không cần bất kỳ chỉ số, sau đó nó sẽ phải làm hai quét bộ sưu tập đầy đủ lồng nhau, như có thể thấy bằng cách nhìn vào sản lượng

db._explain(<your query here>);

mà show cái gì đó như:

1 SingletonNode    1 * ROOT 
    2 EnumerateCollectionNode  3  - FOR fromItem IN fromCollection /* full collection scan */ 
    3 EnumerateCollectionNode  9  - FOR toItem IN toCollection /* full collection scan */ 
    4 CalculationNode    9   - LET #3 = (fromItem.`fromAttributeValue` == toItem.`toAttributeValue`) /* simple expression */ /* collections used: fromItem : fromCollection, toItem : toCollection */ 
    5 FilterNode     9   - FILTER #3 
    ... 

Nếu bạn làm

db.toCollection.ensureIndex({"type":"hash", fields ["toAttributeValue"], unique:false})` 

Sau đó, sẽ có một lần quét toàn bộ bảng thu thập trong fromCollection và đối với mỗi mục được tìm thấy có tra cứu băm trong toCollection, sẽ nhanh hơn nhiều. Tất cả mọi thứ sẽ xảy ra theo lô, vì vậy điều này đã được cải thiện tình hình. Các db._explain() sẽ hiển thị này:

1 SingletonNode    1 * ROOT 
    2 EnumerateCollectionNode  3  - FOR fromItem IN fromCollection /* full collection scan */ 
    8 IndexNode     3  - FOR toItem IN toCollection /* hash index scan */ 

Để làm việc chỉ vào các mặt hàng thời gian gần đây lắp vào fromCollection là tương đối dễ dàng: Chỉ cần thêm một dấu thời gian của thời gian nhập khẩu tất cả các đỉnh, và sử dụng:

FOR fromItem IN fromCollection 
    FILTER fromItem.timeStamp > @lastRun 
    FOR toItem IN toCollection 
     FILTER fromItem.fromAttributeValue == toItem.toAttributeValue 
     INSERT { _from: fromItem._id, _to: toItem._id, otherAttributes: {}} INTO edgeCollection 

và của tất nhiên đặt chỉ số skiplist lên thuộc tính timeStamp trong fromCollection.

Điều này sẽ hoạt động tốt để khám phá các đỉnh mới trong số fromCollection. Nó sẽ "bỏ qua" các đỉnh mới trong toCollection được liên kết với các đỉnh trong fromCollection.

Bạn có thể khám phá những qua việc trao đổi vai trò của fromCollectiontoCollection trong truy vấn của bạn (đừng quên chỉ số trên fromAttributeValue trong fromCollection) và ghi nhớ để chỉ đưa vào mép nếu từ đỉnh trở về già, như trong:

FOR toItem IN toCollection 
    FILTER toItem.timeStamp > @lastRun 
    FOR fromItem IN fromCollection 
     FILTER fromItem.fromAttributeValue == toItem.toAttributeValue 
     FILTER fromItem.timeStamp <= @lastRun 
     INSERT { _from: fromItem._id, _to: toItem._id, otherAttributes: {}} INTO edgeCollection 

Hai người này cùng nhau nên làm những gì bạn muốn. Vui lòng tìm ví dụ hoàn chỉnh đã làm việc here.

+0

Cảm ơn Max! Một vấn đề tiềm ẩn khi sử dụng dấu thời gian là các bộ sưu tập khác nhau được nhập ở các mức khác nhau, do đó dữ liệu trong 'fromCollection' có thể đã được nhập vào tối qua, nhưng dữ liệu trong' toCollection' đã được nhập một giờ trước. Ngoài ra, đôi khi dữ liệu mới cần phải được liên quan đến dữ liệu đã được nhập một thời gian dài trước đây. Điều này sẽ làm việc nếu cả hai 'fromItem' và' toItem' trước đó đã được nhập, nhưng không phải chỉ cho một. Nhóm của tôi kể từ khi đưa ra một quy tắc chính xác định cho các cạnh, do đó, trùng lặp không phải là một vấn đề - bây giờ nó hoàn toàn là hiệu suất của chèn. –

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