2009-12-21 34 views
5

Tôi có một bảng chứa 3 triệu bản ghi mà tôi muốn thực hiện kết hợp mờ bằng cách sử dụng q-grams (trên tên họ). Tôi đã tạo ra một bảng 2 gram liên kết đến điều này, nhưng hiệu suất tìm kiếm không phải là tuyệt vời về khối lượng dữ liệu này (khoảng 5 phút). Về cơ bản, tôi có hai câu hỏi: (1) Bạn có thể đề xuất bất kỳ cách nào để cải thiện hiệu suất để tránh quét bảng (nghĩa là phải tính số lượng q-gram chung giữa chuỗi tìm kiếm và 3 triệu họ) (2) Với q-grams, nếu A tương tự như B và C tương tự như B, có nghĩa là C giống với A không?tối ưu hóa tương đương gần đúng q-gram

Kind coi

Peter

Trả lời

6

Tôi đã nhìn vào chuỗi mờ phù hợp với thời gian gần đây, vì vậy ngay cả tại các nguy cơ trả lời cho một câu hỏi bị bỏ rơi, ở đây đi. Hy vọng bạn thấy điều này hữu ích.

Tôi cho rằng bạn chỉ quan tâm đến các chuỗi có khoảng cách chỉnh sửa nhỏ hơn giá trị đã cho. Và q-gram của bạn (hoặc n-gram) trông như thế này

2-grams for "foobar": {"fo","oo","ob","ba","ar"} 
  1. Bạn có thể sử dụng vị trí q-gram:

    "foobar": {("fo",1),("oo",2),("ob",3),("ba",4),("ar",5)} 
    

    Thông tin vị trí có thể được sử dụng để xác định xem phù hợp với q-gram thực sự là một "kết hợp tốt".

    Ví dụ, nếu bạn đang tìm kiếm "foobar" với tối đa chỉnh sửa khoảng cách 2, điều này có nghĩa rằng bạn chỉ quan tâm từ nơi

    2-gram "fo" exists in with position from 1 to 3 or 
    2-gram "oo" exists in with position from 2 to 4 or 
    ... and so on 
    

    String "barfoo" doesn' t nhận được bất kỳ trận đấu vì vị trí của các khác phù hợp với 2 gam khác nhau bởi 3.

  2. Ngoài ra, nó có thể có ích cho u se mối quan hệ giữa khoảng cách chỉnh sửa và số lượng phù hợp với q-gram. Các intution là vì

    một chuỗi s đã len (s) q + 1 q-gram

    một chỉnh sửa hoạt động đơn lẻ có thể ảnh hưởng tại q nhất q-gram,

    chúng ta có thể suy luận rằng

    chuỗi s1 và s2 trong chỉnh sửa khoảng cách d có ít nhất max (len (s1), len (s2)) - q + 1-qk khớp với q-grams không có vị trí.

    Nếu bạn đang tìm kiếm "foobar" với bản chỉnh sửa khoảng cách tối đa là 2, một phù hợp với chuỗi 7 ký tự (ví dụ như "fotocar") nên chứa ít nhất hai chung 2-gram.

  3. Cuối cùng, điều hiển nhiên cần làm là đến bộ lọc theo chiều dài. Biên tập sửa đổi khoảng cách giữa hai dây là tại ít nhất sự khác biệt về độ dài của các chuỗi. Ví dụ: nếu ngưỡng của bạn là 2 và bạn tìm kiếm "foobar", "foobarbar" không thể rõ ràng là khớp.

Xem http://pages.stern.nyu.edu/~panos/publications/deb-dec2001.pdf để biết thêm và một số giả SQL.

2

giấy thú vị về DNA indexing q-gam, do đó bạn không cần phải quét toàn bộ bảng:

www.comp.nus.edu.sg/~atung/publication/qgram_edit.pdf

4

Bạn chắc chắn đã thấy các tìm kiếm văn bản mờ ở khắp mọi nơi. Ví dụ bạn gõ "stck" nhưng bạn thực sự có nghĩa là "ngăn xếp"! Bao giờ tự hỏi làm thế nào để công cụ này hoạt động?

Có rất nhiều thuật toán để thực hiện kết hợp văn bản mờ, mỗi đối tượng có tính năng chuyên nghiệp và khuyết điểm riêng. Những người nổi tiếng nhất là chỉnh sửa khoảng cách và qgram. Tôi muốn tập trung vào qgrams ngày hôm nay và thực hiện một mẫu.

Về cơ bản, qgram là thuật toán kết hợp chuỗi mờ phù hợp nhất cho cơ sở dữ liệu quan hệ. Nó khá đơn giản. "q" trong qgram sẽ được thay thế bằng một số như 2 gam hoặc 3 gam hoặc thậm chí 4 gram.

2-gram có nghĩa là mỗi từ được chia thành một tập hợp gồm hai ký tự gram. "Stack" sẽ được chia thành một tập hợp {"st", "ta", "ac", "ck"} hoặc "cơ sở dữ liệu" sẽ được chia thành {"da", "at", "ta", "ba "," là "," se "}.

Khi từ được chia thành 2-gram, chúng tôi có thể tìm kiếm cơ sở dữ liệu cho một tập hợp các giá trị thay vì một chuỗi. Ví dụ: nếu người dùng nhập sai "stck", bất kỳ tìm kiếm nào cho "stck" sẽ không khớp với "ngăn xếp" vì "a" bị thiếu, nhưng tập hợp 2 "{" st "," tc "," ck "} có 2 hàng chung với bộ 2 ngăn xếp! Bingo chúng tôi tìm thấy một trận đấu khá gần. Nó không có điểm chung với bộ cơ sở dữ liệu 2 gram và chỉ có 1 điểm chung với bộ "stat" 2 gram để chúng tôi có thể dễ dàng đề xuất người dùng mà anh ta muốn nhập: "xếp chồng" đầu tiên hoặc thứ hai "sao ".

Bây giờ chúng ta hãy thực hiện nó bằng cách sử dụng Sql Server: Giả sử một số liệu từ giả định. Bạn cần phải có một mối quan hệ nhiều đến nhiều giữa 2grams và các từ.

CREATE TABLE Grams(twog char(2), wordId int, PRIMARY KEY (twog, wordId)) 

Bảng Gram nên được nhóm lại trên twog đầu tiên và sau đó là wordId để thực hiện. Khi bạn truy vấn một từ (ví dụ: ngăn xếp), bạn đặt gam trong bảng tạm thời. Đầu tiên cho phép tạo một vài triệu bản ghi giả.

--make millions of 2grams 
DECLARE @i int =0 
WHILE (@i<5000000) 
BEGIN 
-- a random 2gram 
declare @rnum1 char = CHAR(CAST(RAND()*28 AS INT)+97) 
declare @rnum2 char = CHAR(CAST(RAND()*28 AS INT)+97) 
INS... INTO Grams (twog, wordId) VALUES (@rnum1 + @rnum2, CAST(RAND()*100000 AS int)) 
END 

Bây giờ, hãy truy vấn từ "ngăn xếp" sẽ được chia thành: {'st', 'ta', 'ac', 'ck'} hai gram.

DECLARE @word TABLE(twog char(2)) -- 'stack' 
INS... INTO @word VALUES ('st'), ('ta'), ('ac'), ('ck') 

select wordId, count(*) from @word w inner join Grams g ON w.twog = g.twog 
GROUP BY wordId 

Bạn nên đảm bảo rằng Sql Server sử dụng một nhóm chỉ mục nhóm tìm kiếm (hoặc loockups) để chạy truy vấn này.Nó phải là sự lựa chọn tự nhiên nhưng đôi khi số liệu thống kê có thể bị hỏng hoặc lỗi thời và SqlServer có thể quyết định rằng việc quét toàn bộ sẽ rẻ hơn. Điều này thường xảy ra nếu nó không biết cardinality của bảng bên trái, ví dụ SqlServer có thể giả định rằng bảng @word là lớn và hàng triệu loockups sẽ đắt hơn một lần quét chỉ mục đầy đủ.

0

Tôi có một cải tiến đơn giản sẽ không loại bỏ quá trình quét, nhưng hãy tăng tốc độ quét nếu bạn chỉ sử dụng 2 gam hoặc 3 gram: thay thế các chữ cái theo số. Hầu hết các công cụ SQL hoạt động nhanh hơn rất nhiều khi so sánh các số.

Ví dụ: bảng nguồn của chúng tôi chứa các mục nhập văn bản trong một cột. Chúng tôi tạo ra một bảng tạm thời nơi chúng tôi chia các tên trong 2 gram sử dụng một

SELECT SUBSTRING (column, 1,2) as gram, 1 as position FROM sourcetable 
UNION 
SELECT SUBSTRING (column, 2,2) as gram, 2 as position FROM sourcetable 
UNION 
SELECT SUBSTRING (column, 3,2) as gram, 3 as position FROM sourcetable 

etc. 

này nên chạy trong một vòng lặp trong đó i = 0 và j = kích thước tối đa của một mục nguồn.

Sau đó, chúng tôi chuẩn bị bảng ánh xạ chứa tất cả các ký tự 2 ký tự có thể và bao gồm cột IDENTITY (1,1) được gọi là gram_id. Chúng ta có thể sắp xếp gam theo tần số trong từ điển tiếng Anh và loại bỏ các gam không thường xuyên nhất (như 'kk' hoặc 'wq') - phân loại này có thể mất thời gian và nghiên cứu nhưng nó sẽ gán các số nhỏ nhất cho các gam thường xuyên nhất sau đó sẽ cải thiện hiệu suất nếu chúng ta có thể giới hạn số lượng gram thành 255 vì sau đó chúng ta có thể sử dụng một cột nhỏ xíu cho gram_id.

Sau đó, chúng tôi xây dựng lại một bảng tạm thời khác từ bảng đầu tiên, nơi chúng tôi sử dụng gram_id thay vì gram. Điều đó trở thành bảng chủ. Chúng tôi tạo một chỉ mục trên cột gram_id và trên cột vị trí. Sau đó, khi chúng ta phải so sánh chuỗi văn bản với bảng chính, trước tiên chúng ta chia chuỗi văn bản chia thành 2-gram, sau đó thay thế 2-gram bằng gram_id của chúng (sử dụng bảng ánh xạ) và so sánh chúng vào một trong các bảng chính

Điều đó tạo ra nhiều so sánh, nhưng hầu hết trong số chúng là các số nguyên gồm 2 chữ số, rất nhanh.