2017-12-04 1 views
0

mysql에서 자동 완성 (> 1M 레코드)에 사용할 대형 데이터 세트가 있습니다. 예를 들어 내가 "메탄올"을 입력하고 선행 입력 제안을 걸려으로 대용량 텍스트 데이터 세트에서 왼쪽으로 가중치가 빠른 검색 - Mysql

..

현재 내가 가진

이 멋지게 일을하지만, 느린 비트입니다
select AgentReferenceName as name 
from tblAgentReference 
where AgentReferenceName like '%methan%' 
order by instr(AgentReferenceName,'methan'), char_length(AgentReferenceName) 
limit 10; 

+-------------+ 
| name  | 
+-------------+ 
| Methan  | 
| Methane  | 
| Methane  | 
| Methane  | 
| Methanal | 
| Methanol | 
| Methanol | 
| Methanide | 
| Methanamine | 
| Methanamine | 
+-------------+ 
10 rows in set (3.52 sec) 

필드에 전체 텍스트 색인이 있지만 일반적인 전체 텍스트 가중 검색을 실행할 때 큰 단어가 부풀어 오릅니다.

select AgentReferenceName as name from tblAgentReference where match(AgentReferenceName) against ('methano*' in boolean mode) order by match(AgentReferenceName) against ('methano*') limit 10;  
+----------------------------------------------------------------------------------------------------------+ 
| name                          | 
+----------------------------------------------------------------------------------------------------------+ 
| 2,4-Methanoacridin-9-amine, 8-fluoro-1,2,3,4-tetrahydro-, 2-hydroxy-1,2,3-propanetricarboxylate (3:2) | 
| 9-Amino-8-fluoro-1,2,3,4-tetrahydro-2,4-methanoacridine             | 
| 9-Amino-8-fluoro-1,2,3,4-tetrahydro-2,4-methanoacridine             | 
| 2,4-Methanoadamantane                     | 
| 2,4-Methanoadamantane                     | 
| 2-Amino-4,5-methanoadipate                    | 
| 1,4-Methanoanthra(2,3-c)oxepin-7,12-dione, 1,3,4,5-tetrahydro-4,6,13-trihydroxy-3,11-dimethoxy-3-methyl- | 
| 1,4-Methanoanthracene-9,10-dione, 1,2,3,4-tetrahydro-             | 
| 1,4-Methanoanthracene-9,10-dione, 1,2,3,4-tetrahydro-             | 
| 1,4-Methanoanthracene-9,10-dione, 1,2,3,4,4a,9a-hexahydro-            | 
+----------------------------------------------------------------------------------------------------------+ 
10 rows in set (0.13 sec) 

그래서 속도는 훌륭하지만 결과는 끔찍

내 질문 - 어떻게 전체 텍스트 하나의 속도에 가깝게 등 쿼리와 유사한 반환하지만 빠른 검색을 수행하려면?

답변

0

(어떤 임의 생각 ...)

WHERE MATCH(...) AGAINST(...) 
    AND ... LIKE ... 

FULLTEXT 먼저 사용 필터 다음에, 또 LIKE 통해 필터링한다.

하지만 ... 나는 현재 코드에 의문을 가지고 있습니다. 첫 번째 예제 (instr 사용) 으로 으로 시작하여 "Methan"으로 시작하는 경향이 있습니다. 즉,이 훨씬 더 효율적으로

AgentReferenceName LIKE 'Methan%' 

당신이 INDEX(AgentReferenceName). If AgentReferenceName is TEXT and not VARCHAR`이 가정을 수행 할 수 있습니다, 다음 색인 단지 짧은 이름을 가진 여분의 열을 고려한다. 아마도 응용 프로그램 코드에서 -

그런 다음 더 정렬 (10로 바뀌며) 20 행에 당신을 줄 것이다

(SELECT ... WHERE ... LIKE 'Methan%' ... LIMIT 10) 
UNION DISTINCT 
(SELECT ... WHERE MATCH ... LIMIT 10) 

을 고려하십시오.

+0

tblAgentReference에서 이름으로 AgentReferenceName을 선택하려고합니다 (부울 모드의 'methano *')와 일치하고 (AgentReferenceName, 'methan') limit 10 인 AgentReferenceName LIKE 'methano %'순서 10; 나에게 1.17 초의 훨씬 빠른 검색을 주었다 - 나는 내가 이것과 함께 잠시 동안 갈 것이라고 생각한다. 나는 나중에 추가적인 열을 시도 할 것이다. –

0

이 정확한 문제를 해결했습니다. 여기 내가 한 일이있다.

사용자가 제공 한 자동 완성 문자열이 1 ~ 2 자이면 무시하십시오. 자동 완성을 시도하지 마십시오 (사용자의 이전 검색 기록이없는 경우).

사용자가 제공 한 자동 완성 문자열이 비교적 짧으면 (6자를 사용) WHERE name LIKE CONCAT(:userstring, '%')을 사용하면 자로 시작하여으로 사용자가 원하는 내용을 검색 할 수 있습니다. 그것은 색인을 이용할 수 있습니다. 사용자가 원하는 문자열을 찾고 선택하면 완료됩니다.

사용자가 제공 한 문자열이 더 길면 WHERE name LIKE CONCAT('%', :userstring, '%')과 다른 쿼리를 사용하십시오. 더 긴 문자열의 경우에만 %과 함께 성능이 저하되는 검색 기능을 제공합니다. 성능은 여전히 ​​악취는 나지만 기능이 덜 자주 사용됩니다.

릭 제임스가 언급 한 것처럼 으로 시작하는 문자열을 포함하는 테이블을 만드는 것이 가장 좋을 것입니다. 그렇다면 언제든지 LIKE 'searchterm%'을 사용하고 %을 피할 수 있습니다.

FULLTEXT는 자동 완성을 위해 몇 가지 제한 사항을 발견했습니다.

+0

나는 첫 번째 대답과 함께이 하나를 좋아한다. PHP 쪽에서 할 것이다. 대신 생각해라. .. –

관련 문제