12.9.1 자연 언어 텍스트 검색
기본 않거나 IN NATURAL LANGUAGE MODE
수식자가 지정된 경우, MATCH()
함수는 텍스트 컬렉션에 문자열 자연어 검색을 실행합니다. 컬렉션은 FULLTEXT
인덱스에 포함 된 하나 이상의 컬럼 세트입니다. 검색 문자열은 AGAINST()
의 인수로 지정됩니다. MATCH()
는 테이블의 각 행에 관련성의 값을 돌려줍니다. 즉, 검색 문자열과 MATCH()
목록에서 이름이 지정된 컬럼의 해당 행의 텍스트 사이에 유사성이 평가됩니다.
mysql>CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
) ENGINE=InnoDB;
Query OK, 0 rows affected (0.00 sec) mysql>INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...'),
('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial we will show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0 mysql>SELECT * FROM articles
WHERE MATCH (title,body)
AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----+-------------------+------------------------------------------+ | id | title | body | +----+-------------------+------------------------------------------+ | 1 | MySQL Tutorial | DBMS stands for DataBase ... | | 5 | MySQL vs. YourSQL | In the following database comparison ... | +----+-------------------+------------------------------------------+ 2 rows in set (0.00 sec)
기본적으로 대소 문자를 구분하는 방법으로 검색이 실행됩니다. 대문자와 대문자를 구분 된 전체 텍스트 검색을 수행하려면 인덱스 컬럼의 이진 데이터 정렬을 사용합니다. 예를 들어, 전체 텍스트 검색에서 대소 문자를 구별되도록, latin1
캐릭터 세트가 사용되는 컬럼에 latin1_bin
데이터 정렬을 지정할 수 있습니다.
이전 예제와 같이, MATCH()
이 WHERE
절에 사용하면 가장 관련성이 높은 행이 첫 번째로 반환되도록 자동으로 정렬됩니다. 관련성의 값은 음수가 아닌 부동 소수점 숫자입니다. 제로의 관련성은 유사성이 없다는 의미입니다. 관련성은 행의 단어 수, 해당 은행의 고유 한 단어의 수, 컬렉션 단어의 총 개수, 특정 단어가 포함 된 문서 (줄)의 수에 따라 계산됩니다.
단순히 일치를 계산하려면 다음과 같은 쿼리를 사용하십시오.
mysql>SELECT COUNT(*) FROM articles
WHERE MATCH (title,body)
AGAINST ('database' IN NATURAL LANGUAGE MODE);
+----------+ | COUNT(*) | +----------+ | 2 | +----------+ 1 row in set (0.00 sec)
다음과 같이 쿼리를 다시 작성하는 것이 더 빠를 수 있습니다.
mysql>SELECT
COUNT(IF(MATCH (title,body) AGAINST ('database' IN NATURAL LANGUAGE MODE), 1, NULL))
AS count
FROM articles;
+-------+ | count | +-------+ | 2 | +-------+ 1 row in set (0.03 sec)
첫 번째 쿼리에서는 몇 가지 추가 작업 (관련 성별 결과 정렬)가 실행되지만, WHERE
절에 따른 인덱스 검색을 사용할 수 있습니다. 인덱스 검색은 검색에서 대부분 행이 일치하지 않는 경우 첫 번째 쿼리가 빠를 수 있습니다. 두 번째 쿼리는 테이블 전체 스캔이 실행 된 대부분의 줄에 검색어가 존재하는 경우, 인덱스 검색보다 빠를 수 있습니다.
자연어 전문 검색은 MATCH()
함수에 이름이 지정된 컬럼은 테이블의 일부 FULLTEXT
인덱스에 포함 된 컬럼과 동일해야합니다. 위의 쿼리는 MATCH()
함수에 이름이 지정된 컬럼 ( title
과 body
)는 article
테이블의 FULLTEXT
인덱스 정의에 이름이 지정된 컬럼과 동일합니다. title
또는 body
를 개별적으로 검색하려면 컬럼에 대해 별도의 FULLTEXT
인덱스를 만듭니다.
boolean 검색 및 쿼리 확장을 사용한 검색을 수행 할 수 있습니다. 이러한 검색 유형은 섹션 12.9.2 "불리 안 전문 검색 ' 및 섹션 12.9.3 "쿼리 확장을 사용한 전문 검색 ' 으로 설명되어 있습니다.
인덱스를 사용하여 전체 텍스트 검색은 인덱스가 여러 테이블에 미칠 가능성은 없기 때문에 MATCH()
어구의 단일 테이블에있는 컬럼 만 이름을 넣을 수 없습니다. MyISAM
테이블에서는 인덱스가 존재하지 않는 경우에도 boolean 검색을 수행 할 수 있습니다 (그러나 느려집니다). 이 경우 여러 테이블의 컬럼을 지정할 수 있습니다.
위의 예에서는 관련성 내림차순으로 행을 반환 MATCH()
함수의 사용 방법에 대해 설명했습니다. 다음 예제에서는 관련성의 값을 명시 적으로 가져 오는 방법을 보여줍니다. SELECT
문에 WHERE
절을 ORDER BY
절을 포함하지 않기 때문에 반환되는 행은 정렬되지 않습니다.
mysql>SELECT id, MATCH (title,body)
AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE) AS score
FROM articles;
+----+---------------------+ | id | score | +----+---------------------+ | 1 | 0.22764469683170319 | | 2 | 0 | | 3 | 0.22764469683170319 | | 4 | 0 | | 5 | 0 | | 6 | 0 | +----+---------------------+ 6 rows in set (0.00 sec)
다음의 예는 더 복잡합니다. 이 쿼리는 관련성의 값을 반환 관련성 내림차순으로 행 정렬도 이루어집니다. 이 결과를 실현하려면, MATCH()
을 2 회 (1 회는 SELECT
목록에 한 번은 WHERE
절)입니다. MySQL 최적화 프로그램 2 회 MATCH()
호출이 같고, 전체 텍스트 검색 코드를 한 번만 실행되는 것을 감지되므로 추가 오버 헤드가 발생하지 않습니다.
mysql>SELECT id, body, MATCH (title,body) AGAINST
('Security implications of running MySQL as root'
IN NATURAL LANGUAGE MODE) AS score
FROM articles WHERE MATCH (title,body) AGAINST
('Security implications of running MySQL as root'
IN NATURAL LANGUAGE MODE);
+----+-------------------------------------+-----------------+ | id | body | score | +----+-------------------------------------+-----------------+ | 4 | 1. Never run mysqld as root. 2. ... | 1.5219271183014 | | 6 | When configured properly, MySQL ... | 1.3114095926285 | +----+-------------------------------------+-----------------+ 2 rows in set (0.00 sec)
MySQL FULLTEXT
구현에서는 트루 단어 문자 (문자, 숫자 및 밑줄)의 순서가 단어로 간주됩니다. 그 순서는 아포스트로피 ( ' '
')도 포함 할 수 있지만, 한 줄에 하나까지입니다. 즉, aaa'bbb
은 한 단어로 간주되지만 aaa''bbb
는 두 단어로 간주됩니다. 단어의 시작 또는 끝 아포스트로피는 FULLTEXT
파서에 의해 삭제됩니다. 'aaa'bbb'
는 aaa'bbb
로 해석됩니다.
FULLTEXT
파서는 특정 구분 문자 ( "
"(공백)" ,
"(쉼표)" .
"(마침표) 등)를 검색하여 단어의 시작과 끝을 결정합니다. 단어 구분자로 구분되지 않은 경우 (예를 들어 중국의 경우), FULLTEXT
파서는 단어의 시작과 끝을 알 수 없습니다. 이 같은 언어로 단어와 기타 인덱스의 단어를 FULLTEXT
인덱스에 추가하려면 " "
"등의 문자를 구분자로 구분되도록 전처리를해야합니다.
MySQL 5.6에서는 내장 전체 파서에서 대체 플러그인을 만들 수 있습니다 ( MyISAM
에서만 지원됩니다). 자세한 내용은 섹션 24.2 "MySQL 플러그인 API" 를 참조하십시오. 파서 플러그인 샘플 소스 코드는 MySQL 소스 배포판의 plugin/fulltext
디렉토리를 참조하십시오.
전문 검색에서는 일부 단어가 무시됩니다.
너무 짧은 단어는 무시됩니다. 전체 텍스트 검색에서 찾은 단어의 기본 최소 길이는
InnoDB
검색 인덱스의 경우 3 자MyISAM
의 경우는 4 자입니다. 인덱스를 생성하기 전에 구성 옵션 (InnoDB
검색 인덱스의 경우innodb_ft_min_token_size
구성 옵션MyISAM
의 경우는ft_min_word_len
)을 설정하면 차단을 제어 할 수 있습니다.스톱 워드리스트에있는 단어는 무시됩니다. 중지 단어는 의미 값이 제로라고 생각 될만큼 일반적인 단어 ( "the"와 "some")입니다. 내장 스톱 워드도 있지만, 사용자 정의 목록에서 무시할 수 있습니다. 스톱 워드리스트와 관련 구성 옵션은
InnoDB
검색 인덱스와MyISAM
검색 인덱스와 다릅니다. 불용어 처리는InnoDB
검색 인덱스의 경우 구성 옵션innodb_ft_enable_stopword
,innodb_ft_server_stopword_table
및innodb_ft_user_stopword_table
,MyISAM
검색 인덱스의 경우ft_stopword_file
의해 제어됩니다.
디폴트 스톱 워드 및 변경 방법을 표시하는 방법은 섹션 12.9.4 "전문 스톱 워드" 를 참조하십시오. 단어의 기본 최소 길이는 섹션 12.9.6 "MySQL의 전체 텍스트 검색 미세 조정" 에 설명 된대로 변경할 수 있습니다.
컬렉션 및 쿼리의 모든 정확한 단어는 컬렉션 또는 쿼리의 중요성에 따라 가중치합니다. 따라서 많은 문서 내에 존재하는 단어는이 특정 컬렉션의 의미 치가 낮기 때문에, 무게도 줄어 듭니다. 반대로 드문 단어는 높은 가중치가 매겨집니다. 단어의 가중치를 조합하는 것으로, 행의 관련성이 계산됩니다. 이 기술은 큰 컬렉션에서 최적으로 작동합니다.
아주 작은 테이블에서는 단어의 배포가 제대로 의미 값에 반영되지 않기 때문에이 모델에서는 MyISAM
테이블에서 검색 인덱스 비정상적인 결과가 생성 될 수 있습니다. 예를 들어, 이전에 보여준 articles
테이블의 모든 행은 "MySQL"이라는 단어가 존재하지만, MyISAM
검색 색인에서 단어를 검색해도 결과가 생성되지 않습니다.
mysql>SELECT * FROM articles
WHERE MATCH (title,body)
AGAINST ('MySQL' IN NATURAL LANGUAGE MODE);
Empty set (0.00 sec)
"MySQL"이라는 단어는 50 % 이상의 행에 존재하기 때문에 검색 결과가 비어 있습니다. 따라서 사실상 스톱 워드로 처리됩니다. 이 필터링 기술은 일반적인 단어에 대해 잘못된 결과가 생성 될 수있는 작은 데이터 세트보다 1G 바이트의 테이블에서 한 줄마다 결과 집합을 반환 할 수없는 큰 데이터 세트에 적합합니다.
전문 검색이 어떻게 작동하는지 확인하기 위해 먼저 시도하면 값이 50 % 인 것에 놀랄지도 모르지만, 이것에 의해 InnoDB
테이블이 전체 텍스트 검색에서의 실험에 의해 적합한 수 알 수 있습니다. MyISAM
테이블을 만들고이 두 줄의 텍스트를 삽입하려면 텍스트의 모든 단어가 50 % 이상 줄에 나타납니다. 그 결과 테이블에 더 많은 행이 포함될 때까지 검색 결과가 반환되지 않습니다. 50 %의 제한을 회피 할 필요가있는 사용자는 InnoDB
테이블에 검색 인덱스를 구축하고 섹션 12.9.2 "불리 안 전문 검색" 에서 설명한 boolean 검색 모드를 사용 할 수 있습니다.