Tại sao THÍCH nhanh hơn gấp 4 lần so với MATCH ĐỒNG Ý về chỉ số FULLTEXT trong MySQL?


12

Tôi không nhận được điều này.

Tôi đã có một bảng với các chỉ mục này

PRIMARY     post_id
INDEX       topic_id
FULLTEXT    post_text

Bảng có (chỉ) 346 000 hàng. Tôi đang cố gắng thực hiện 2 truy vấn.

SELECT post_id 
FROM phpbb_posts 
WHERE topic_id = 144017 
AND post_id != 155352 
AND MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar')

mất 4,05 giây trong khi

SELECT post_id 
FROM phpbb_posts 
WHERE topic_id=144017 
AND post_id != 155352 
AND post_text LIKE ('%http://rapidshare.com/files/5494794/photo.rar%')

mất 0,027 giây.

GIẢI THÍCH cho thấy rằng sự khác biệt duy nhất là ở khả fulltextnăng_key ( đã bao gồm postSphere, LIKEkhông)

Điều đó thực sự kỳ lạ.

Điều gì đằng sau điều này? Điều gì đang xảy ra trong nền? Làm thế nào có LIKEthể nhanh như vậy khi không sử dụng chỉ mục và FULLTEXT rất chậm khi sử dụng chỉ mục của nó?

CẬP NHẬT1:

Trên thực tế, bây giờ mất khoảng 0,5 giây, có thể bảng đã bị khóa, nhưng vẫn vậy, khi tôi bật hồ sơ, điều đó cho thấy rằng KHỞI TẠO FULLTEXT mất 0,2 giây. Có chuyện gì vậy?

Tôi có thể truy vấn bảng của mình với LIKE10 lần một giây, với toàn văn chỉ 2 lần

CẬP NHẬT2:

Sự ngạc nhiên!

mysql> SELECT post_id FROM phpbb_posts WHERE post_id != 2 AND topic_id = 6 AND MATCH(post_text) AGAINST ('rapidshare.com');
Empty set (0.04 sec)

Vì vậy, tôi hỏi, làm thế nào là có thể?

Ngoài ra,

SELECT count(*) FROM phpbb_posts WHERE MATCH(post_text) AGAINST ('rapidshare.com')

thực sự rất chậm Có thể fulltext bất kỳ bị hỏng?

CẬP NHẬT3:

Cái quái gì thế?

SELECT forum_id, post_id, topic_id, post_text  FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

mất 0,27 giây trong khi

SELECT count(*) FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

mất hơn 30 giây! Điều gì đang xảy ra ở đây?


Là thời gian đáp ứng giữa hai lần nhất quán trên nhiều lần chạy? Tôi muốn nghĩ rằng bộ nhớ đệm đĩa có thể sẽ xuất hiện trong đó thử nghiệm "chậm" đầu tiên tải tất cả dữ liệu cần thiết vào ram để truy vấn "nhanh" thứ hai rất nhanh.
atxdba

Kiểm tra truy vấn chỉ với SQL_NO_CACHE .
mgutt

Đây là câu hỏi / câu trả lời khá cũ. Có sự tiến bộ nào từ mysql / mariadb kể từ những ngày đó không?
Roman Susi

1
Thận trọng: Thời điểm của Hỏi & Đáp này ngụ ý rằng nó chỉ nói về MyISAM. Khả năng ứng dụng của nó vào InnoDB đang được đề cập.
Rick James

@RomanSusi - Bạn có muốn bắt đầu một câu hỏi mới nhắm vào InnoDB không?
Rick James

Câu trả lời:


2

Tôi nghĩ vấn đề có thể xuất phát từ sự hiện diện của chính chỉ số FULLTEXT.

Mỗi khi có một truy vấn liên quan đến chỉ mục FULLTEXT, Trình tối ưu hóa truy vấn MySQL có xu hướng đưa truy vấn vào quét toàn bộ bảng. Tôi đã thấy điều này trong những năm qua. Tôi cũng đã viết một bài viết trước đó về hành vi rắc rối nhất này trong các chỉ mục FULLTEXT .

Bạn có thể cần làm hai việc:

  1. cấu trúc lại truy vấn để chỉ mục FULLTEXT không ném Trình tối ưu hóa truy vấn MySQL vào trạng thái nhầm lẫn
  2. Thêm một chỉ mục bổ sung sẽ hỗ trợ chính xác truy vấn được cấu trúc lại

REFACTOR THE QUERY

Đây là truy vấn ban đầu của bạn

SELECT post_id  
FROM phpbb_posts  
WHERE topic_id = 144017  
AND post_id != 155352  
AND MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar') 

Bạn sẽ cần cấu trúc lại truy vấn như thế này:

SELECT subqueryA.post_id
FROM
(
    SELECT post_id FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) subqueryA
INNER JOIN
(
    SELECT post_id FROM phpbb_posts
    WHERE MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar')
) subqueryB
USING (post_id);

TẠO MỘT INDEX MỚI

Bạn sẽ cần một chỉ số để hỗ trợ subqueryA. Bạn đã có một chỉ mục trên topic_id. Bạn cần thay thế nó như sau:

ALTER TABLE phpbb_posts ADD INDEX topic_post_ndx (topic_id,post_id);
ALTER TABLE phpbb_posts DROP INDEX topic_id;

Hãy thử một lần !!!

CẬP NHẬT 2012/03/19 13:08 EDT

Hãy thử cái này trước

SELECT post_id FROM
(
    SELECT * FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) A;

Nếu điều này chạy nhanh và trả về một số lượng nhỏ hàng, thì hãy thử truy vấn con lồng nhau này:

SELECT post_id FROM
(
    SELECT * FROM phpbb_posts
    WHERE topic_id = 144017
    AND post_id != 155352
) A
WHERE MATCH(post_text) AGAINST('http://rapidshare.com/files/5494794/photo.rar');

CẬP NHẬT 2012/03/19 13:11 EDT

So sánh thời gian chạy này:

SELECT count(*) FROM phpbb_posts  WHERE MATCH(post_text) AGAINST ('rapidshare.com') LIMIT 0, 30;

Với cái này

SELECT count(*) FROM phpbb_posts WHERE 1 = 1;

Nếu có thời gian chạy là như nhau, thì mệnh đề MATCH đang được thực thi trên mỗi hàng. Như tôi đã đề cập trước đó, sử dụng các chỉ mục FULLTEXT có xu hướng vô hiệu hóa bất kỳ lợi ích nào được cố gắng và đóng góp bởi Trình tối ưu hóa truy vấn MySQL.


Vì vậy, bạn muốn nói rằng truy vấn của tôi thực sự quét toàn bộ bảng vì topic_id và post_idnhầm lẫn nó? Tại sao truy vấn THÍCH hoạt động ngay cả khi không có chỉ mục trên các cột này (topic_id, post_id)? Tại sao MYSQL không chọn một cách thông minh topic_id = 144017 AND post_id != 155352và sau đó chỉ trình duyệt thông qua các kết quả này? Và nếu hàng 100k bao gồm chuỗi tìm kiếm fulltext của tôi post_textthì sao? Nó sẽ không chọn tất cả?
genesis

Thật ra tôi còn bối rối hơn nữa. THÍCH '% text%' cũng không sử dụng chỉ mục, điều đó có nghĩa là nó quét toàn bộ bảng, vậy tại sao nó lại nhanh như vậy?
gen

Hãy nhìn vào CẬP NHẬT của tôi , tôi nghĩ bạn sẽ giải quyết nó rất nhanh. Tôi sẽ cung cấp cho bạn đại diện của tôi nếu bạn giải quyết nó.
gen

Trả lời bản cập nhật thứ hai của bạn. Truy vấn thứ hai chạy trong chưa đầy 0,01ms, truy vấn đầu tiên không kết thúc. Tại sao bạn lại nói "Nếu có thời gian chạy giống nhau, thì mệnh đề MATCH đang được thực thi trên mỗi hàng." ? Nó không hoàn toàn trái ngược với những gì nó phải là? Nếu bạn nhìn vào đây , bạn sẽ thấy tôi không phải là người duy nhất gặp vấn đề này
genesis

Trả lời cập nhật đầu tiên của bạn. Truy vấn đầu tiên chạy trong 0,01ms, 0 hàng, lần thứ hai trả về "Không thể tìm thấy chỉ mục FULLTEXT phù hợp với danh sách cột". Tuy nhiên, truy vấn của bạn với 2 truy vấn con hoạt động hoàn hảo!
genesis
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.