MySQL의 FULLTEXT 인덱스에서 LIKE가 MATCH… AGAINST보다 4 배 이상 빠른 이유는 무엇입니까?


12

나는 이것을 얻지 못한다.

이 색인이있는 테이블이 있습니다.

PRIMARY     post_id
INDEX       topic_id
FULLTEXT    post_text

테이블에 3 억 6 천 행이 있습니다. 2 개의 쿼리를 수행하려고합니다.

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')

동안 4.05 초 소요

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%')

0.027 초가 걸립니다.

EXPLAIN은 possible_keys에 유일한 차이점이 있음을 보여줍니다 ( fulltextpost_text 포함, 포함 LIKE되지 않음)

정말 이상합니다.

이 뒤에 무엇입니까? 백그라운드에서 무슨 일이 일어나고 있습니까? LIKE인덱스를 사용하지 않을 때 어떻게 그렇게 빠를 수 있고 인덱스를 사용할 때 FULLTEXT를 너무 느리게 할 수 있습니까?

업데이트 1 :

실제로는 약 0.5 초가 걸리고 테이블이 잠겨있을 수 있지만 프로파일 링을 켤 때 FULLTEXT INITIALIZATION이 0.2 초 걸린다는 것을 보여줍니다. 뭐야?

전체 LIKE텍스트 만 2x로 초 당 10x로 테이블을 쿼리 할 수 ​​있습니다

UPDATE2 :

놀라다!

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)

그래서 묻습니다. 어떻게 이것이 가능합니까?

또한

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

정말 느립니다. 전체 텍스트가 손상 될 수 있습니까?

업데이트 3 :

도대체?

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

0.27 초 소요

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

30 초 이상 걸립니다! 여기서 무엇이 잘못 되었나요?


두 번의 응답 시간이 여러 번 실행되는 동안 일관됩니까? 디스크 캐싱이 첫 번째 "느린"테스트가 필요한 모든 데이터를 램에로드하여 두 번째 "빠른"쿼리가 빠르면 디스크 캐싱이 작동 할 수 있다고 생각합니다.
atxdba

SQL_NO_CACHE 로만 쿼리를 테스트 하십시오 .
mgutt

이것은 꽤 오래된 질문 / 답변입니다. 그 이후로 mysql / mariadb의 발전은 무엇입니까?
Roman Susi

1
주의 :이 Q & A의 시점은 MyISAM에 대해서만 이야기하고 있음을 의미합니다. InnoDB에 대한 적용 가능성이 의문입니다.
Rick James

@RomanSusi-InnoDB를 겨냥한 새로운 질문을 시작 하시겠습니까?
Rick James

답변:


2

FULLTEXT 인덱스 자체의 존재로 인해 문제가 발생할 수 있다고 생각합니다.

FULLTEXT 인덱스와 관련된 쿼리가있을 때마다 MySQL Query Optimizer는 쿼리를 전체 테이블 스캔으로 흔드는 경향이 있습니다. 나는 수년에 걸쳐 이것을 보았다. 또한 FULLTEXT 인덱스에서이 가장 사소한 동작에 대한 이전 게시물을 작성했습니다 .

다음 두 가지를 수행해야 할 수도 있습니다.

  1. FULLTEXT 인덱스가 MySQL Query Optimizer를 혼란 상태로 만들지 않도록 쿼리를 리팩터링하십시오.
  2. 리팩토링 된 쿼리를 올바르게 지원할 추가 인덱스 추가

쿼리를 리플렉터

원래 검색어는 다음과 같습니다.

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') 

다음과 같이 쿼리를 리팩터링해야합니다.

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);

새로운 색인 작성

지원하려면 색인이 필요합니다 subqueryA. 에 대한 색인이 이미 있습니다 topic_id. 다음과 같이 교체해야합니다.

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

시도 해봐 !!!

업데이트 2012-03-19 13:08 EDT

이걸 먼저 해봐

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

이것이 빠르게 실행되고 적은 수의 행을 반환하면이 중첩 하위 쿼리를 사용해보십시오.

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');

업데이트 2012-03-19 13:11 EDT

이것의 실행 시간을 비교하십시오.

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

이것으로

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

실행 시간이 동일하면 모든 행에서 MATCH 절이 실행됩니다. 필자가 언급했듯이 FULLTEXT 인덱스를 사용하면 MySQL Query Optimizer가 시도하고 제공하는 이점을 모두 무효화하는 경향이 있습니다.


그래서 당신은 내 쿼리가 topic_id 때문에 post_id혼란스럽게 전체 테이블을 스캔한다고 말하고 싶 습니까? 이러한 열 (topic_id, post_id)에 대한 색인이 없어도 LIKE 쿼리가 작동하는 이유는 무엇입니까? MYSQL topic_id = 144017 AND post_id != 155352이 이러한 결과를 지능적으로 선택한 다음 브라우저 만 사용하는 이유는 무엇 입니까? 그리고 100k 개의 행에 전체 텍스트 검색 문자열이 포함되어 있으면 어떻게 post_text됩니까? 모두 선택하지 않습니까?
창세기

사실 나는 더 혼란스러워합니다. '% text %'와 마찬가지로 인덱스도 사용하지 않습니다. 이는 전체 테이블을 스캔한다는 것을 의미합니다. 왜 그렇게 빠릅니까?
창세기

업데이트를 살펴보십시오 . 정말 빨리 해결할 것이라고 생각합니다. 당신이 해결하면 내 담당자를 줄 것입니다.
창세기

두 번째 업데이트에 응답합니다. 두 번째 쿼리는 0.01ms 미만으로 실행되었으며 첫 번째 쿼리는 완료되지 않았습니다. 왜 "실행 시간이 동일하면 모든 행에서 MATCH 절이 실행되고 있습니다"라고 말한 이유는 무엇입니까? ? 그것이 있어야하는 것과 정확히 반대가 아닙니까? 당신이 여기 를 보면 , 당신은 내가이 문제에 유일하지 않다는 것을 알 것입니다
기원

첫 번째 업데이트에 응답합니다. 첫 번째 쿼리는 0.01ms, 0 개의 행에서 실행되었고 두 번째 쿼리는 "열 목록과 일치하는 FULLTEXT 인덱스를 찾을 수 없습니다"를 반환했습니다. 그러나 2 개의 하위 쿼리가있는 쿼리는 완벽하게 작동합니다!
창세기
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.