Thuật toán tìm kiếm thẻ nhanh


16

Vấn đề là như sau.

  • Có một tập hợp các thực thể E đơn giản, mỗi thực thể có một bộ thẻ T được đính kèm. Mỗi thực thể có thể có một số lượng thẻ tùy ý. Tổng số thực thể là gần 100 triệu và tổng số thẻ là khoảng 5000.

Vì vậy, dữ liệu ban đầu là như thế này:

E1 - T1, T2, T3, ... Tn
E2 - T1, T5, T100, ... Tk
..
Ez - T10, T12, ... Tl

Dữ liệu ban đầu này khá hiếm khi được cập nhật.

  • Bằng cách nào đó, ứng dụng của tôi tạo ra một biểu thức logic trên các thẻ như thế này:

    T1 & T2 & T3 | (T5 &! T6)

  • Điều tôi cần là tính toán một số thực thể khớp với biểu thức đã cho (lưu ý - không phải là các thực thể, mà chỉ là số). Điều này có thể không hoàn toàn chính xác, tất nhiên.

Những gì tôi có bây giờ là một tra cứu bảng trong bộ nhớ đơn giản, cho tôi thời gian thực hiện 5-10 giây trên một luồng.

Tôi tò mò, có cách nào hiệu quả để xử lý công cụ này không? Cách tiếp cận nào bạn muốn giới thiệu? Có một số thuật toán hoặc cấu trúc dữ liệu phổ biến cho việc này?

Cập nhật

Một chút làm rõ theo yêu cầu.

  1. Tcác đối tượng thực sự là các chuỗi hằng tương đối ngắn. Nhưng nó không thực sự quan trọng - chúng tôi luôn có thể gán một số ID và hoạt động trên các số nguyên.
  2. Chúng tôi chắc chắn có thể sắp xếp chúng.

1
T1tài liệu tham khảo đối tượng tương tự cho E1, E2, vv?
Phản ứng

Làm thế nào là các thẻ so sánh? các thẻ có thể được sắp xếp sao cho T2 < T3luôn đúng?
Phản ứng

Là thẻ nhị phân? Tức T1truehoặc falsecho một E, và không phải là biến dựa trên đầu vào? (tức là Model = "V5") Hoặc là T1một biểu thức biến như thế Model = <input>nào?
Bobson

Câu trả lời:


4

tôi sẽ làm điều này trong sql có một bảng liên kết EntityCategorygiữa eidthực thể cidtham chiếu và danh mục tham chiếu bằng cách tự tham gia:

    select count(ec1.eid)
    from EntityCategory ec1 
    left join EntityCategory ec2 on ec1.eid=ec2.eid 
    left join EntityCategory ec3 on ec1.eid=ec3.eid 
    ...
    where 
      ec1.cid={categoryId1} and 
      ec2.cid={categoryId2} and
      ec3.cid={categoryId3} ...

1
+1, đây là lãnh thổ DB cổ điển. Câu trả lời khác có thể có ý tưởng hợp lý làm thế nào để tự viết mã, nhưng đó phải là phương sách cuối cùng.
MSalters

Tôi cũng sẽ chọn sql là kỹ thuật để giải quyết điều này. Hầu hết các cơ sở dữ liệu đều được tối ưu hóa khá tốt cho các thuật toán này :)
winkbrace 27/12/13

3

Sau khi viết câu trả lời này, tôi có lẽ nên đánh dấu câu hỏi là quá rộng - chúng ta có thể nói chuyện lâu dài về các chiến lược khác nhau, cuối cùng, một điểm chuẩn sẽ phải được chạy với dữ liệu của bạn.

Mỗi thẻ có thể được biểu diễn một cách hiệu quả bởi một số nguyên. Mỗi thực thể có một bộ thẻ. Chọn cách thực hiện tập hợp chính xác là rất quan trọng - cả hai cây B và các mảng được sắp xếp đều có thể. Với bộ này, chúng tôi sẽ chỉ làm các bài kiểm tra thành viên. Vì cả hai cấu trúc làm điều này trong O (log t) (với các thẻ t trên mỗi thực thể), tôi sẽ thích các mảng do biểu diễn dày đặc hơn của chúng.

Bây giờ chúng ta có thể lọc qua tất cả các thực thể trong một hoạt động O (n · log t · p) , trong đó p là độ dài đường dẫn trung bình trong cây quyết định vị ngữ. Cây quyết định này có thể được đặt hàng để có thể nhanh chóng đưa ra quyết định. Không có dữ liệu thống kê, chỉ có thể tạo ra yếu tố phụ phổ biến.

Thứ tự mà các thực thể được tìm kiếm không thực sự quan trọng. Mặt khác, có thể thuận lợi khi sắp xếp nó sao 0cho itất cả các thực thể tại các chỉ mục đều có một thẻ nhất định, trong khi phần còn lại thì không. Điều này làm giảm n khi tìm kiếm thẻ cụ thể này (trong cây quyết định, đây sẽ là thử nghiệm đầu tiên). Điều này có thể được mở rộng thành nhiều cấp độ, nhưng điều này làm phức tạp mọi thứ và chiếm bộ nhớ O (2 k ) với kcấp độ. Với nhiều cấp độ, các thẻ có mức tăng cao nhất phải được quyết định trước, trong đó mức tăng là số lượng thực thể không phải tìm kiếm nhiều lần xác suất loại bỏ chúng. Mức tăng trở thành tối đa cho 50:50 cơ hội hoặc khi 50% thực thể có thẻ cụ thể này. Điều này sẽ cho phép bạn tối ưu hóa ngay cả khi các mẫu truy cập không được biết đến.

Bạn cũng có thể tạo các bộ chỉ mục các thực thể theo từng thẻ được sử dụng - một bộ với tất cả các thực thể cho T1, tiếp theo cho T2. Tối ưu hóa rõ ràng (không gian và thời gian) là dừng khi một bộ chứa hơn một nửa tất cả các yếu tố và để lưu các yếu tố không có thẻ này - theo cách này, việc tạo các chỉ mục cho tất cả các thẻ sẽ mất ít hơn ½ · n · tkhông gian (với tổng số thẻ t ). Lưu ý rằng việc lưu các bộ bổ sung có thể làm cho việc tối ưu hóa khác trở nên khó khăn hơn. Một lần nữa, tôi sẽ (sắp xếp) mảng cho các bộ.

Nếu bạn cũng đại diện cho các thực thể của mình thông qua một phạm vi số nguyên, bạn có thể nén không gian được sử dụng cho các bộ chỉ mục bằng cách chỉ lưu trữ thành viên bắt đầu và kết thúc của một phạm vi liên tục. Thực hiện khôn ngoan điều này có thể sẽ được thực hiện với một bit cao để cho biết liệu một mục nhập là một phạm vi ràng buộc hoặc mục thường xuyên.

Nếu bây giờ chúng ta có các bộ chỉ mục (và do đó thống kê trên các thẻ), chúng ta có thể tối ưu hóa các vị từ để các thuộc tính không chắc chắn được kiểm tra trước (chiến lược không nhanh). Điều này có nghĩa là nếu T1phổ biến và T2hiếm, thì T1 & T2nên đánh giá vị ngữ bằng cách lặp qua tất cả các T2mục nhập của bộ chỉ mục và kiểm tra từng phần tử T1.

Nếu chúng ta sử dụng các mảng được sắp xếp để thực hiện các bộ chỉ mục, thì nhiều bước đánh giá có thể được thực hiện như các hoạt động hợp nhất. T1 & T2có nghĩa là chúng ta lấy T1T2liệt kê, phân bổ một mảng mục tiêu kích thước của các đầu vào lớn hơn và thực hiện thuật toán sau cho đến khi cả hai đầu vào đều trống: If T1[0] < T2[0], sau đó T1++(loại bỏ đầu). Nếu T1[0] > T2[0]sau đó T2++. Nếu cả hai người đứng đầu đều bình đẳng, sau đó sao chép số đó giao cho mảng mục tiêu, và tăng cả ba con trỏ ( T1, T2, mục tiêu). Nếu vị ngữ là T1 | T2, thì không có phần tử nào bị loại bỏ mà phần tử nhỏ hơn được sao chép. Một vị từ của biểu mẫu T1 & ¬T2cũng có thể được thực hiện bằng cách sử dụng chiến lược hợp nhất, nhưng ¬T1hoặc T1 | ¬T2không thể.

Điều này cần được xem xét khi đặt hàng cây quyết định vị ngữ: Việc bổ sung sẽ xảy ra trên RHS của một &hoặc cuối cùng, khi số lượng cuối cùng được xác định và các yếu tố thực tế không phải xem xét.

Không sử dụng các bộ chỉ mục, mỗi luồng có thể lọc qua một phần của các thực thể và trả về số lượng phần tử khớp với vị từ, có thể được tóm tắt. Khi sử dụng các bộ chỉ mục, thì mỗi luồng sẽ được gán một nút trong cây quyết định. Phải mất hai luồng đầu vào tương ứng với các bộ được đặt hàng và trả về một luồng đã hợp nhất. Lưu ý rằng mỗi nút trong cây quyết định có một tập hợp tương ứng đại diện cho tất cả các thực thể thực hiện biểu thức con đó và do thứ tự của các tập hợp, không cần thiết phải biết toàn bộ tập hợp cùng một lúc để hợp nhất chúng .

Các chiến lược khác nhau như hợp nhất các bộ được lập chỉ mục hoặc lọc qua danh sách các thực thể có thể được kết hợp ở một mức độ nhất định. Lọc có hiệu suất rất dễ đoán. Nếu một truy vấn rất cụ thể để việc sử dụng các bộ chỉ mục làm giảm đáng kể không gian tìm kiếm, thì các hoạt động hợp nhất có thể tốt hơn. Điều quan trọng cần lưu ý là việc hợp nhất nhiều bộ đầu vào lớn có thể dẫn đến hiệu suất kém hơn nhiều so với tìm kiếm vũ phu. Một thuật toán rất tối ưu sẽ chọn một chiến lược phù hợp dựa trên kích thước đầu vào, cấu trúc truy vấn và các chỉ số thống kê.

Bên cạnh đó, kết quả bộ nhớ đệm có thể có lợi nếu dự kiến ​​các truy vấn tương tự sẽ được chạy trong tương lai, mặc dù chúng không tăng tốc độ chạy bộ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.