Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm thế nào để tối ưu hóa MySQL Boolean Full-Text Search? (Hoặc thay thế nó bằng cái gì?) - C #

Trước tiên, bạn nên nhận ra rằng hỗ trợ RDBMS cho lập chỉ mục văn bản đầy đủ là một sự tấn công để buộc một công nghệ được thiết kế để cho phép truy cập hiệu quả vào dữ liệu có cấu trúc để xử lý văn bản không có cấu trúc. (Vâng, đó chỉ là của tôi ý kiến. Nếu được yêu cầu, tôi có thể bảo vệ nó vì tôi hiểu rất rõ cả hai công nghệ.;)

Vì vậy, có thể làm gì để cải thiện hiệu suất tìm kiếm?

Lựa chọn Một - "Công cụ Tốt nhất Cho Công việc"

Cách tốt nhất để xử lý tìm kiếm toàn văn trong kho tài liệu là sử dụng công nghệ được thiết kế đặc biệt để làm như vậy, chẳng hạn như SOLR (Lucene) từ Apache hoặc Sphinx từ err, Sphinx.

Vì những lý do sẽ trở nên rõ ràng dưới đây, tôi thực sự khuyên bạn nên tiếp cận này.

Tùy chọn Hai - Tải trước kết quả của bạn

Khi xây dựng các giải pháp tìm kiếm dựa trên văn bản, cách tiếp cận thông thường là lập chỉ mục tất cả các tài liệu vào một chỉ mục có thể tìm kiếm duy nhất và mặc dù điều này có thể phù hợp nhất, nhưng đó không phải là cách tiếp cận duy nhất.

Giả sử những gì bạn đang tìm kiếm có thể dễ dàng được định lượng thành một tập hợp các quy tắc đã biết, bạn có thể cung cấp nhiều kiểu tìm kiếm "có hướng dẫn" hơn là chỉ toàn văn bản không đủ tiêu chuẩn. Ý tôi muốn nói ở đây là, nếu ứng dụng của bạn có thể hưởng lợi từ việc phân loại người dùng với kết quả, bạn có thể tải trước các bộ kết quả khác nhau dựa trên một bộ quy tắc đã biết vào bảng của riêng họ và do đó giảm lượng lớn dữ liệu cần tìm kiếm.

Nếu bạn mong đợi phần lớn người dùng của mình sẽ được hưởng lợi từ một tập hợp các cụm từ tìm kiếm đã biết theo thứ tự đã biết, bạn có thể xây dựng giao diện người dùng tìm kiếm của mình để ưu tiên các cụm từ đó.

Vì vậy, giả sử phần lớn người dùng đang tìm kiếm nhiều loại ô tô khác nhau, bạn có thể đưa ra các tìm kiếm xác định trước dựa trên kiểu xe, năm, tình trạng, v.v. Giao diện người dùng tìm kiếm của bạn sẽ được tạo thành một loạt menu thả xuống để "hướng dẫn" người dùng đến các kết quả cụ thể.

Hoặc nếu phần lớn các tìm kiếm dành cho một chủ đề chính cụ thể (chẳng hạn như 'ô tô'), bạn có thể xác định trước một bảng chỉ gồm những bản ghi mà trước đây bạn đã xác định là có liên quan đến ô tô.

Cả hai cách tiếp cận này sẽ làm giảm số lượng bản ghi được tìm kiếm và do đó, tăng thời gian phản hồi.

Tùy chọn Ba - "Tự làm của riêng bạn"

Nếu bạn không thể tích hợp công nghệ tìm kiếm bên ngoài vào dự án của mình và tải trước không phải là một tùy chọn, vẫn có nhiều cách để cải thiện đáng kể thời gian phản hồi truy vấn tìm kiếm, nhưng chúng khác nhau dựa trên những gì bạn cần hoàn thành và cách bạn mong đợi tìm kiếm được thực hiện .

Nếu bạn mong đợi người dùng tìm kiếm bằng các từ khóa hoặc cụm từ đơn lẻ và mối quan hệ boolean giữa chúng, bạn có thể cân nhắc tạo ' đảo ngược chỉ mục 'của kho tài liệu của bạn. (Đây là những gì mà Tìm kiếm toàn văn bản Boolean của MySQL đã làm, nhưng tự mình thực hiện nó cho phép kiểm soát tốt hơn cả tốc độ và độ chính xác của tìm kiếm.)

Để tạo chỉ mục đảo ngược từ dữ liệu hiện có của bạn:

Bước 1. Tạo ba bảng

    // dict - a dictionary containing one row per unique word in corpus  
    create table dict (    
      id int primary key,  
      word varchar  
    )

    // invert - an inverted_index to map words to records in corpus  
    create table invert (    
      id int primary key,  
      rec_id int,  
      word_id int  
    )

    // stopwords - to contain words to ignore when indexing (like a, an, the, etc)
    create table stopwords ( 
      id int primary key,  
      word varchar  
    )

Lưu ý:Đây chỉ là một bản phác thảo. Bạn sẽ muốn thêm các chỉ mục và ràng buộc, v.v. khi bạn thực sự tạo các bảng này.

Bảng từ dừng được sử dụng để giảm kích thước chỉ mục của bạn xuống chỉ những từ quan trọng đối với truy vấn mong đợi của người dùng. Ví dụ:hiếm khi hữu ích khi lập chỉ mục các bài báo tiếng Anh, như 'a', 'an', 'the', vì chúng không đóng góp ý nghĩa hữu ích cho các tìm kiếm từ khóa.

Thông thường, bạn sẽ yêu cầu một danh sách từ khóa được tạo riêng theo nhu cầu của ứng dụng của bạn. Nếu bạn không bao giờ mong đợi người dùng bao gồm các thuật ngữ 'đỏ', 'trắng' hoặc 'xanh lam' trong truy vấn của họ hoặc nếu các thuật ngữ này xuất hiện trong mọi bản ghi có thể tìm kiếm được, bạn muốn thêm chúng vào danh sách từ khóa của mình.

Xem ghi chú ở cuối thư này để biết hướng dẫn về cách sử dụng danh sách từ dừng của riêng bạn trong MySQL.

Xem thêm:

Bước 2. Xây dựng Chỉ mục Đảo ngược

Để tạo chỉ mục đảo ngược từ các bản ghi hiện có của bạn, bạn sẽ cần (mã giả):

    foreach( word(w) in record(r) ) {
      if(w is not in stopwords) {
        if( w does not exist in dictionary) {
          insert w to dictionary at w.id
        }
        insert (r.id, w.id) into inverted_index
      }
    }
Thông tin thêm về từ dừng:

Thay vì sử dụng danh sách từ dừng cụ thể, kiểm tra 'nếu (w không có trong từ dừng)' có thể đưa ra các quyết định khác thay vì hoặc như một phần bổ trợ cho danh sách các từ không được chấp nhận của bạn.

Ứng dụng của bạn có thể muốn lọc ra tất cả các từ dài dưới 4 ký tự hoặc chỉ bao gồm từ một tập hợp được xác định trước.

Bằng cách tạo chỉ mục đảo ngược của riêng bạn, bạn có được quyền kiểm soát chi tiết và lớn hơn nhiều đối với tìm kiếm.

Bước 3. Truy vấn Chỉ mục Đảo ngược Sử dụng SQL

Bước này thực sự phụ thuộc vào cách bạn mong đợi các truy vấn được gửi đến chỉ mục của mình.

Nếu các truy vấn được 'mã hóa cứng', bạn có thể chỉ cần tự tạo câu lệnh select hoặc nếu bạn cần hỗ trợ các truy vấn do người dùng nhập, bạn sẽ cần chuyển đổi bất kỳ ngôn ngữ truy vấn nào bạn chọn thành câu lệnh SQL (thường được thực hiện bằng cách sử dụng phân tích cú pháp đơn giản).

Giả sử bạn muốn truy xuất tất cả các tài liệu khớp với truy vấn logic '(word1 AND word2) OR word3', một cách tiếp cận khả thi có thể là:

CREATE TEMPORARY TABLE temp_results ( rec_id int, count int ) AS 
    ( SELECT rec_id, COUNT(rec_id) AS count 
      FROM invert AS I, dict AS D 
      WHERE I.word_id=D.id AND (D.word='word1' OR D.word='word2') 
      GROUP BY I.rec_id 
      HAVING count=2
    ) 
    UNION (
      SELECT rec_id, 1 AS count 
      FROM invert AS I, dict AS D
      WHERE I.word_id=D.id AND D.word='word3'
    );

SELECT DISTINCT rec_id FROM temp_results;

DROP TABLE temp_results;

LƯU Ý:Đây chỉ là một thông tin đầu tiên qua đỉnh đầu của tôi. Tôi tin rằng có nhiều cách hiệu quả hơn để chuyển đổi một biểu thức truy vấn boolean thành một câu lệnh SQL hiệu quả và hoan nghênh bất kỳ và tất cả các đề xuất để cải thiện.

Để tìm kiếm các cụm từ, bạn sẽ cần thêm một trường vào chỉ mục đảo ngược để thể hiện vị trí của từ xuất hiện trong bản ghi của nó và nhân tố đó vào CHỌN của bạn.

Và cuối cùng, bạn sẽ cần cập nhật chỉ mục đảo ngược của mình khi thêm các bản ghi mới hoặc xóa các bản ghi cũ.

Lời cuối cùng

"Tìm kiếm toàn văn" thuộc một lĩnh vực nghiên cứu rất lớn được gọi là "Truy xuất thông tin" hoặc IR và có nhiều sách về chủ đề này, bao gồm

Kiểm tra Amazon để biết thêm.

Ghi chú

Cách sử dụng danh sách từ dừng của riêng bạn trong MySQL

Để sử dụng danh sách từ dừng của riêng bạn trong MySQL:

  1. Tạo danh sách từ dừng của riêng bạn, một từ trên mỗi dòng và lưu nó vào một vị trí đã biết trên máy chủ của bạn, chẳng hạn như:/usr/local/lib/IR/stopwords.txt

  2. Chỉnh sửa my.cnf để thêm hoặc cập nhật các dòng sau:
        [mysqld]  
        ft_min_word_len=1    
        ft_max_word_len=40  
        ft_stopword_file=/usr/local/lib/IR/stopwords.txt
    

    sẽ đặt độ dài tối thiểu và tối đa của các từ hợp pháp tương ứng là 1 và 40, đồng thời cho mysqld biết nơi tìm danh sách từ dừng tùy chỉnh của bạn.

    (Lưu ý:ft_max_word_len mặc định là 84, mà tôi tin là khá quá mức và có thể gây ra các chuỗi không phải là từ thực được lập chỉ mục.)

  3. Khởi động lại mysqld

  4. Thả và tạo lại tất cả các chỉ số liên quan đến toàn văn bản



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. EF6 MySql:Update-Database -Script tạo SQL mà không có dấu chấm phẩy

  2. Cách tạo cơ sở dữ liệu MySQL bằng API cPanel

  3. MySQL - Cách tách các giá trị trong các chuỗi đơn bằng cách sử dụng dấu phẩy

  4. Cách đặt lại mật khẩu gốc MySQL hoặc MariaDB trong Linux

  5. Sử dụng Python và MySQL trong Quy trình ETL:SQLAlchemy