쿼리 개요

이 페이지에서는 Spanner 테이블에서 전체 텍스트 검색 쿼리를 수행하는 데 사용되는 SEARCH 함수와 향상된 쿼리 모드를 설명합니다.

검색 색인 쿼리

Spanner는 검색 색인 쿼리에 사용할 SEARCH 함수를 제공합니다. 한 가지 사용 사례는 사용자가 검색창에 텍스트를 입력하면 애플리케이션이 사용자 입력을 SEARCH 함수로 직접 전송하는 애플리케이션입니다. 그러면 'SEARCH' 함수가 검색 색인을 사용하여 해당 텍스트를 찾습니다.

SEARCH 함수에는 두 가지 인수가 필요합니다.

  • 검색 색인 이름
  • 검색어

SEARCH 함수는 검색 색인이 정의된 경우에만 작동합니다. SEARCH 함수는 필터, 집계 또는 조인과 같은 임의의 SQL 구성과 결합될 수 있습니다.

SEARCH 함수는 트랜잭션 쿼리와 함께 사용할 수 없습니다.

다음 쿼리는 SEARCH 함수를 사용하여 제목에 friday 또는 monday가 있는 모든 앨범을 반환합니다.

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'friday OR monday')

검색어

검색어는 기본적으로 원시 검색어 형식이지만 dialect 인수를 사용하여 쿼리 형식을 변경할 수 있습니다.

rquery 언어

기본 방언은 원시 검색어입니다. Spanner는 rquery라는 도메인별 언어 (DSL)를 사용합니다.

rquery 언어는 입력 검색어를 구별되는 검색어로 분할할 때 일반 텍스트 토크나이저와 동일한 규칙을 따릅니다. 여기에는 아시아 언어 세분화가 포함됩니다.

rquery 사용에 관한 자세한 내용은 rquery 문법을 참조하세요.

단어 방언

단어 방언은 rquery와 비슷하지만 더 간단합니다. 특수 연산자를 사용하지 않습니다. 예를 들어 OR는 불리언 연산자가 아닌 검색어로 취급됩니다. 큰따옴표는 구문 검색이 아닌 구두점으로 처리되며 무시됩니다.

단어 방언을 사용하면 AND가 모든 용어에 암시적으로 적용되며 일치하는 동안 필요합니다. 입력 검색어를 검색어로 분할할 때 일반 텍스트 토크나이저와 동일한 규칙을 따릅니다.

단어 방언 사용에 관한 자세한 내용은 단어 문법을 참고하세요.

words_phrase dialect

words_phrase 방언은 특수 연산자를 사용하지 않으며 모든 용어가 구문으로 취급됩니다. 즉, 용어가 나란히 있고 지정된 순서여야 합니다.

rquery와 마찬가지로 words_phrase 방언은 입력 검색어를 검색어로 분할할 때 일반 텍스트 토크나이저와 동일한 규칙을 따릅니다.

words_phrase 방언 사용에 관한 자세한 내용은 단어 구문 문법을 참고하세요.

향상된 쿼리 모드

Spanner는 기본 토큰 기반 검색과 enhance_query라고 하는 고급 모드의 두 가지 전체 텍스트 검색 모드를 제공합니다. 사용 설정하면 enhance_query가 검색어를 확장하여 관련 검색어와 동의어를 포함하므로 관련 검색 결과를 찾을 가능성이 높아집니다.

이 옵션을 사용 설정하려면 SEARCH 함수에서 선택적 enhance_query=>true 인수를 설정합니다. 예를 들어 hotl cal 검색어는 Hotel California 앨범과 일치합니다.

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'hotl cal', enhance_query=>true)

enhance_query 모드는 쿼리 시간 옵션입니다. 토큰화에는 영향을 미치지 않습니다. enhance_query 유무와 관계없이 같은 검색 색인을 사용할 수 있습니다.

Google은 쿼리 개선 알고리즘을 지속적으로 개선하고 있습니다. 따라서 enhance_query == true가 포함된 쿼리는 시간이 경과하면 약간 다른 결과를 생성할 수 있습니다.

enhance_query 모드를 사용 설정하면 SEARCH 함수가 찾는 검색어 수가 늘어나고 지연 시간이 약간 늘어날 수 있습니다.

예를 들어 다음 쿼리에서는 3초 제한 시간을 사용하며 enhance_query를 사용할 수 없으면 실패합니다.

@{require_enhance_query=true, enhance_query_timeout_ms=3000}
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'fast car', enhance_query=>true)

enhance_query 옵션 사용에 관한 자세한 내용은 SEARCH 함수를 참조하세요.

SQL 쿼리 요구사항

검색 색인을 사용하려면 SQL 쿼리에서 충족해야 하는 몇 가지 조건이 있습니다. 이러한 조건이 충족되지 않으면 쿼리는 대체 쿼리 계획을 사용하거나 대체 계획이 없으면 실패합니다.

쿼리는 다음 조건을 충족해야 합니다.

  • SEARCHSEARCH_SUBSTRING 함수를 사용하려면 검색 색인이 필요합니다. Spanner는 기본 테이블이나 보조 색인에 대한 쿼리에서 이러한 함수를 지원하지 않습니다.

  • 파티셔닝된 색인에는 쿼리의 WHERE 절에 있는 등식 조건으로 바인딩된 모든 파티션 열이 있어야 합니다.

    예를 들어 검색 색인이 PARTITION BY x, y로 정의된 경우 쿼리에 있는 x = <parameter or constant> AND y = <parameter or constant>WHERE 절에는 접속어가 있어야 합니다. 이 조건이 누락되면 검색 색인은 쿼리 최적화 도구에서 고려되지 않습니다.

  • SEARCHSEARCH_SUBSTRING 연산자가 참조하는 모든 TOKENLIST 열은 같은 검색 색인에서 색인화되어야 합니다.

    예를 들어 다음 테이블과 색인 정의를 고려하세요.

    CREATE TABLE Albums (
        AlbumId STRING(MAX) NOT NULL,
        AlbumTitle STRING(MAX),
        AlbumStudio STRING(MAX),
        AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
        AlbumStudio_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumStudio)) HIDDEN
      ) PRIMARY KEY(AlbumId);
    
      CREATE SEARCH INDEX AlbumsTitleIndex ON Albums(AlbumTitle_Tokens);
      CREATE SEARCH INDEX AlbumsStudioIndex ON Albums(AlbumStudio_Tokens);
    

    AlbumTitle_TokensAlbumStudio_Tokens 모두 색인화하는 단일 검색 색인이 없으므로 다음 쿼리는 실패합니다.

    SELECT AlbumId
    FROM Albums
    WHERE SEARCH(AlbumTitle_Tokens, @p1) AND SEARCH(AlbumStudio_Tokens, @p2)
    
  • 정렬 순서 열에 NULL이 허용되면 스키마와 쿼리 모두 정렬 순서 열이 NULL인 행을 제외해야 합니다. 자세한 내용은 검색 색인 정렬 순서를 참조하세요.

  • 검색 색인이 NULL 필터링이면 색인에 사용된 것과 동일한 NULL 필터링 표현식이 쿼리에 포함되어야 합니다. 자세한 내용은 NULL 필터링 검색 색인을 참조하세요.

  • DML, 파티션을 나눈 DML 또는 파티션을 나눈 쿼리에서는 검색 색인검색 함수가 지원되지 않습니다.

  • 검색 색인검색 함수는 일반적으로 읽기 전용 트랜잭션에서 사용됩니다. 애플리케이션 요구사항에서 비활성 결과를 허용하면 비활성 기간을 10초 이상으로 설정하여 검색 쿼리를 실행하는 것이 좋습니다. 자세한 내용은 비활성 데이터 읽기를 참고하세요. 이는 특히 Paxos 그룹 여러 개로 분산되는 대규모 검색 쿼리에 유용합니다.

    읽기-쓰기 트랜잭션에서는 검색 색인검색 함수를 사용하지 않는 것이 좋습니다. 실행 중에 검색 쿼리는 전체 색인 파티션을 잠급니다. 따라서 읽기-쓰기 트랜잭션에서 검색 쿼리의 비율이 높으면 잠금 충돌이 발생하여 지연 시간이 갑자기 길어질 수 있습니다. 기본적으로 읽기-쓰기 트랜잭션에서는 검색 색인이 자동으로 선택되지 않습니다. 쿼리가 읽기-쓰기 트랜잭션에서 검색 색인을 사용하도록 강제되면 기본적으로 실패합니다. 쿼리에 검색 함수가 포함된 경우에도 실패합니다. 이 동작은 @{ALLOW_SEARCH_INDEXES_IN_TRANSACTION=TRUE} 문 수준 힌트를 통해 재정의될 수 있지만 쿼리에서 계속 잠금 충돌이 발생할 수 있습니다.

색인 자격 요건 조건이 충족되면 쿼리 최적화 도구는 텍스트가 아닌 쿼리 조건(예: Rating > 4)을 가속화하려고 합니다. 검색 색인에 적절한 TOKENLIST 열이 포함되어 있지 않으면 조건은 가속화되지 않고 잔여 조건으로 유지됩니다.

쿼리 매개변수

검색 쿼리 인수는 리터럴 또는 쿼리 매개변수로 지정됩니다. 인수가 쿼리 매개변수 값을 허용하는 경우 전체 텍스트 검색에는 문자열 리터럴 대신 쿼리 매개변수를 사용하는 것이 좋습니다.

색인 선택

Spanner는 일반적으로 비용 기반 모델링을 사용하여 쿼리에 가장 효율적인 색인을 선택합니다. 하지만 FORCE_INDEX 힌트는 Spanner에 특정 검색 색인을 사용하도록 명시적으로 지시합니다. 예를 들어 다음에서는 Spanner가 AlbumsIndex를 강제로 사용하도록 하는 방법을 보여줍니다.

SELECT AlbumId
FROM Albums @{FORCE_INDEX=AlbumsIndex}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

지정된 검색 색인을 사용할 수 없으면 사용 가능한 다른 검색 색인이 있더라도 쿼리가 실패합니다.

검색 결과의 스니펫

스니펫은 특정 문자열에서 추출된 텍스트로, 사용자에게 검색 결과에 포함된 내용과 검색 결과가 쿼리와 관련된 이유를 알려줍니다.

예를 들어 Gmail은 스니펫을 사용하여 검색어와 일치하는 이메일의 일부를 나타냅니다.

스니펫 목록

데이터베이스에서 스니펫을 생성하면 다음과 같은 이점이 있습니다.

  1. 편의성: 검색어에서 스니펫을 생성하는 로직을 구현할 필요가 없습니다.
  2. 효율성: 스니펫은 서버의 출력 크기를 줄입니다.

SNIPPET 함수는 스니펫을 만듭니다. 강조 표시할 문자의 위치와 함께 원래 문자열 값의 관련 부분을 반환합니다. 그러면 클라이언트는 최종 사용자에게 스니펫을 표시하는 방법(예: 텍스트 강조 표시 또는 텍스트 굵게 표시)을 선택할 수 있습니다. SNIPPET 함수는 원래 문자열에서 모든 HTML 태그를 삭제합니다.

예를 들어 다음은 SNIPPET를 사용하여 AlbumTitle에서 텍스트를 검색합니다.

SELECT AlbumId, SNIPPET(AlbumTitle, "Fast Car")
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "Fast Car")

다음 단계