Kết quả tìm kiếm toàn văn trong một lượng lớn thời gian dành cho 'Khởi tạo FULLTEXT'


12

Tôi hiện đang cố gắng chạy một số truy vấn đối với kết xuất dữ liệu của các bình luận của Stack Overflow. Đây là lược đồ trông như thế nào:

CREATE TABLE `socomments` (
  `Id` int(11) NOT NULL,
  `PostId` int(11) NOT NULL,
  `Score` int(11) DEFAULT NULL,
  `Text` varchar(600) NOT NULL,
  `CreationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `UserId` int(11) NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `idx_socomments_PostId` (`PostId`),
  KEY `CreationDate` (`CreationDate`),
  FULLTEXT KEY `Text` (`Text`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Tôi đã chạy truy vấn này trên bảng và nó chạy rất chậm (Nó có 29 triệu hàng, nhưng nó có chỉ mục Toàn văn):

SELECT *
FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)

Vì vậy, tôi đã mô tả nó, kết quả của nó là:

|| Status                     || Duration ||
|| starting                   || 0.000058 ||
|| checking permissions       || 0.000006 ||
|| Opening tables             || 0.000014 ||
|| init                       || 0.000019 ||
|| System lock                || 0.000006 ||
|| optimizing                 || 0.000007 ||
|| statistics                 || 0.000013 ||
|| preparing                  || 0.000005 ||
|| FULLTEXT initialization    || 207.1112 ||
|| executing                  || 0.000009 ||
|| Sending data               || 0.000856 ||
|| end                        || 0.000004 ||
|| query end                  || 0.000004 ||
|| closing tables             || 0.000006 ||
|| freeing items              || 0.000059 ||
|| logging slow query         || 0.000037 ||
|| cleaning up                || 0.000046 ||

Như bạn có thể thấy, nó dành một thời gian dài để khởi tạo FULLTEXT. Điều này có bình thường không? Nếu không, tôi sẽ sửa nó như thế nào?


Ý tưởng: Xây dựng bảng thứ 2 trong đó bạn đặt mỗi 1.000 nhận xét vào một trường văn bản. Bây giờ bạn tìm kiếm đầu tiên trong bảng thứ hai này và bạn lấy ví dụ id_group 2id_group 23. Với điều này, tìm kiếm của bạn bên trong bảng chính của bạn và giới hạn truy vấn của bạn trong phạm vi id từ 2.000 đến 2.999 và 23.000 đến 23.999. Tất nhiên lần thứ 2 sẽ mang lại nhiều kết quả hơn khi bạn cần kết hợp tất cả các bình luận tạo ra các kết hợp từ khóa mới, nhưng cuối cùng nó sẽ tăng tốc toàn bộ. Tất nhiên nó tăng gấp đôi không gian sử dụng đĩa. Nhận xét mới nên được CONCAT'ed vào bảng nhóm.
mgutt

Câu trả lời:


5

Những người khác đã tìm thấy một tình huống rắc rối

Tài liệu MySQL rất ngắn gọn về trạng thái luồng này

Khởi tạo FULLTEXT

Máy chủ đang chuẩn bị thực hiện tìm kiếm toàn văn bản bằng ngôn ngữ tự nhiên.

cách duy nhất của bạn là chuẩn bị với ít dữ liệu hơn. Làm sao ?

BỀN VỮNG # 1

Nhìn vào truy vấn của bạn một lần nữa. Nó đang chọn tất cả các cột. Tôi sẽ cấu trúc lại truy vấn để chỉ thu thập các cột id từ đó socomments. Sau đó, tham gia những id được truy xuất trở lại socommentsbảng.

SELECT B.* FROM
(SELECT id FROM socomments
WHERE MATCH (Text) AGAINST ('"fixed the post"' IN BOOLEAN MODE)) A
LEFT JOIN socomments B USING (id);

Điều này có thể tạo ra một kế hoạch GIẢI THÍCH xấu hơn nhưng tôi nghĩ rằng hồ sơ sẽ thay đổi tốt hơn. Ý tưởng cơ bản là: Nếu bạn có Tìm kiếm FULLTEXT tích cực, hãy làm cho nó thu thập ít dữ liệu nhất trong FULLTEXT initializationgiai đoạn đó, do đó giảm thời gian.

Tôi đã đề nghị điều này nhiều lần trước đây

BỀN VỮNG # 2

Vui lòng đảm bảo rằng bạn đang đặt các tùy chọn FULLTEXT dựa trên InnoDB, chứ không phải các tùy chọn cho MyISAM. Hai lựa chọn bạn nên quan tâm là

Nghĩ về nó ngay lúc này. Trường văn bản là VARCHAR (600). Nói trung bình là 300 byte. Bạn có 29.000.000 triệu trong số họ. Đó sẽ là một chút của 8GB. Có lẽ việc tăng innodb_ft_cache_sizeinnodb_ft_total_cache_size cũng có thể giúp ích.

Đảm bảo bạn có đủ RAM cho bộ đệm InnoDB FULLTEXT lớn hơn.

HÃY THỬ MỘT LẦN !!!


Đã thử cả hai gợi ý, nó đưa thời gian xuống khoảng 10 giây, còn 200 giây. Điều kỳ lạ là nhóm bộ đệm chỉ sử dụng 9% ...
hichris123

Hãy thử đặt một dấu cộng bên trong phần AGAINST: SELECT B.* FROM (SELECT id FROM socomments WHERE MATCH (Text) AGAINST ('+"fixed the post"' IN BOOLEAN MODE)) A LEFT JOIN socomments B USING (id);và xem liệu nó có tạo ra sự khác biệt không.
RolandoMySQLDBA

Lý do tôi đề nghị một dấu cộng? Doc ( dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html ) nói A leading or trailing plus sign indicates that this word must be present in each row that is returned. InnoDB only supports leading plus signs.Trong trường hợp cụ thể của bạn, cụm từ chính xác fixed the postphải tồn tại.
RolandoMySQLDBA

Kết quả tương tự. Nhanh hơn và chậm hơn, vì vậy có lẽ chỉ do sự khác biệt nhỏ trong khi nó được thực thi.
hichris123

5

Nếu bạn đang sử dụng các chỉ mục InnoDB FULLTEXT, các truy vấn sẽ thường bị treo ở trạng thái "Khởi tạo FULLTEXT" nếu bạn đang truy vấn một bảng có số lượng lớn các hàng bị xóa. Trong triển khai FULLTEXT của InnoDB, các hàng đã xóa sẽ không được cắt xén cho đến khi một thao tác TỐI ƯU tiếp theo được chạy với bảng bị ảnh hưởng. Xem: https://dev.mysql.com/doc/refman/5.6/en/innodb-fulltext-index.html

Để xóa các mục nhập chỉ mục toàn văn bản cho các bản ghi bị xóa, bạn phải chạy TỐI ƯU BẢNG trên bảng được lập chỉ mục với innodb_optizes_fulltext_only = ON để xây dựng lại chỉ mục toàn văn bản.

Người ta cũng có thể kiểm tra số lượng hồ sơ đã xóa nhưng không bị xóa bằng cách truy vấn information_schema.innodb_ft_delatted

Để giải quyết vấn đề này, người ta nên thường xuyên chạy BẢNG TỐI ƯU đối với các bảng có chỉ mục InnoDB FULLTEXT.


Tôi hiểu logic về điều này, nhưng bạn có thể xác minh điều đó innodb_optimize_fulltext_only=1và một OPTIMIZEbảng thực sự quan tâm đến các hàng đã bị xóa "đang chờ" không? dba.stackexchange.com/questions/174486/ từ
Riedsio


0

Các chỉ mục toàn văn bản trong MySQL không được thiết kế để hỗ trợ một lượng lớn dữ liệu nên tốc độ tìm kiếm giảm xuống khá nhanh khi dữ liệu của bạn đang tăng lên. Một trong những giải pháp là sử dụng các công cụ tìm kiếm toàn văn bản bên ngoài như Solr hoặc Sphinx đã cải thiện chức năng tìm kiếm (hỗ trợ điều chỉnh cụm từ và hỗ trợ tìm kiếm cụm từ, khía cạnh tích hợp, đoạn trích, v.v.) cú pháp truy vấn mở rộng và tốc độ nhanh hơn nhiều vào giữa bộ dữ liệu lớn.

Solr dựa trên nền tảng Java, vì vậy nếu bạn chạy ứng dụng dựa trên Java sẽ là lựa chọn tự nhiên cho bạn, Sphinx được viết trên C ++ và hoạt động như một daemon theo cùng kiểu với MySQL. Ngay khi bạn cung cấp công cụ bên ngoài với dữ liệu bạn muốn tìm kiếm, bạn cũng có thể di chuyển một số truy vấn ra khỏi MySQL. Tôi không thể cho bạn biết công cụ nào tốt hơn trong trường hợp của bạn, tôi chủ yếu sử dụng Sphinx và đây là ví dụ sử dụng: http://astellar.com/2011/12/replaces-mysql-full-text-search-with-sphinx/

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.