많은 애플리케이션에서 데이터베이스를 쿼리하여 애플리케이션의 단일 페이지를 채웁니다. 이러한 애플리케이션에서는 일치 항목 전부가 아닌 색인 정렬 순서를 기반으로 한 Top-K 일치 항목만 필요합니다. 검색 색인은 이러한 유형의 검색을 매우 효율적으로 구현할 수 있습니다. 이 페이지에서는 Top-K 일치 항목이 있는 색인을 만들고 검색하는 방법을 설명합니다.
Top-K 일치 항목의 검색 색인 만들기
Top-K 일치를 위해 검색 색인을 구성하려면 ORDER BY를 사용하여 특정 열을 기준으로 검색 색인을 정렬합니다. 쿼리에는 검색 색인 정렬 순서(오름차순 및 내림차순 방향 포함)와 정확하게 일치하는 ORDER BY 절과 Top-K 일치 행을 찾은 후 쿼리를 중지하도록 요청하는 LIMIT 절이 있어야 합니다.
이러한 절을 사용하여 페이지로 나누기를 구현할 수도 있습니다. 자세한 내용은 검색 쿼리 페이지로 나누기를 참고하세요.
일부 사용 사례에서는 다양한 열로 정렬된 여러 검색 색인을 유지하는 것이 합리적일 수 있습니다. 파티셔닝과 마찬가지로 스토리지 및 쓰기 비용과 쿼리 지연 시간 간에 절충이 이루어집니다.
ListenTimestamp별 정렬 순서를 요청하는 쿼리는 Top-K 쿼리를 효율적으로 실행하지 못합니다. 일치하는 모든 앨범을 가져와 ListenTimestamp,별로 정렬하고 상위 10개를 반환해야 합니다. 이러한 쿼리는 'happy'라는 용어가 포함된 문서가 많으면 리소스를 더 많이 사용합니다.
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["이해하기 어려움","hardToUnderstand","thumb-down"],["잘못된 정보 또는 샘플 코드","incorrectInformationOrSampleCode","thumb-down"],["필요한 정보/샘플이 없음","missingTheInformationSamplesINeed","thumb-down"],["번역 문제","translationIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-09(UTC)"],[],[],null,["# Perform efficient top-k retrieval\n\n| **Note:** This feature is available with the Spanner Enterprise edition and Enterprise Plus edition. For more information, see the [Spanner editions overview](/spanner/docs/editions-overview).\n\n\u003cbr /\u003e\n\nMany applications query a database to populate a single page in their\napplications. In such applications, the application doesn't need all of the\nmatches, but only the top-k matches based on index sort order. Search indexes\ncan implement this type of search very efficiently. This page describes how to\ncreate and search an index that has top-k matching.\n\nCreate search indexes for top-k matches\n---------------------------------------\n\nTo configure a search index for top-k matching, use `ORDER BY` to order the\nsearch index by a specific column. Queries need to have an `ORDER BY` clause\nthat exactly matches the search index sort order (including ascending versus\ndescending direction) and a `LIMIT` clause that requests the query to stop after\nfinding k-matching rows.\n\nYou can also implement pagination using these clauses. For more information, see\n[Paginate search queries](/spanner/docs/full-text-search/paginate-search-results).\n\nFor some use cases, it might make sense to maintain multiple search indexes\nsorted by different columns. Like\n[partitioning](/spanner/docs/full-text-search/partition-search-index),\nit's a trade-off between storage and write cost versus query latency.\n\nFor example, consider a table that uses the following schema: \n\n### GoogleSQL\n\n CREATE TABLE Albums (\n AlbumId STRING(MAX) NOT NULL,\n RecordTimestamp INT64 NOT NULL,\n ReleaseTimestamp INT64 NOT NULL,\n ListenTimestamp INT64 NOT NULL,\n AlbumTitle STRING(MAX),\n AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN\n ) PRIMARY KEY(AlbumId);\n\n CREATE SEARCH INDEX AlbumsRecordTimestampIndex\n ON Albums(AlbumTitle_Tokens, SingerId_Tokens)\n STORING (ListenTimestamp)\n ORDER BY RecordTimestamp DESC\n\n CREATE SEARCH INDEX AlbumsReleaseTimestampIndex\n ON Albums(AlbumTitle_Tokens)\n STORING (ListenTimestamp)\n ORDER BY ReleaseTimestamp DESC\n\n### PostgreSQL\n\n CREATE TABLE albums (\n albumid character varying NOT NULL,\n recordtimestamp bigint NOT NULL,\n releasetimestamp bigint NOT NULL,\n listentimestamp bigint NOT NULL,\n albumtitle character varying,\n albumtitle_tokens spanner.tokenlist\n GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,\n PRIMARY KEY(albumid));\n\n CREATE SEARCH INDEX albumsrecordtimestampindex\n ON Albums(albumtitle_tokens, singerid_tokens)\n INCLUDE (listentimestamp)\n ORDER BY recordtimestamp DESC\n\n CREATE SEARCH INDEX albumsreleasetimestampindex\n ON Albums(albumtitle_tokens)\n INCLUDE (listentimestamp)\n ORDER BY releasetimestamp DESC\n\nQuery search indexes for top-k matches\n--------------------------------------\n\nAs stated previously, queries need to have an `ORDER BY` clause\nthat exactly matches the search index sort order (including ascending versus\ndescending direction) and a `LIMIT` clause that requests the query to stop after\nfinding k-matching rows.\n\nThe following list analyzes the efficiency of some common queries.\n\n- This query is very efficient. It selects the `AlbumsRecordTimestampIndex`\n index. Even if there are many albums with the word \"happy\", the query only\n scans a small number of rows:\n\n ### GoogleSQL\n\n SELECT AlbumId\n FROM Albums\n WHERE SEARCH(AlbumTitle_Tokens, 'happy')\n ORDER BY RecordTimestamp DESC\n LIMIT 10\n\n ### PostgreSQL\n\n SELECT albumid\n FROM albums\n WHERE spanner.search(albumtitle_tokens, 'happy')\n ORDER BY recordtimestamp DESC\n LIMIT 10\n\n- The same query, requesting sort order by `ReleaseTimestamp` in descending\n order, uses the `AlbumsReleaseTimestampIndex` index and is equally\n efficient:\n\n ### GoogleSQL\n\n SELECT AlbumId\n FROM Albums\n WHERE SEARCH(AlbumTitle_Tokens, 'happy')\n ORDER BY ReleaseTimestamp DESC\n LIMIT 10\n\n ### PostgreSQL\n\n SELECT albumid\n FROM albums\n WHERE spanner.search(albumtitle_tokens, 'happy')\n ORDER BY releasetimestamp DESC\n LIMIT 10\n\n- A query that requests sort order by `ListenTimestamp` doesn't execute a\n top-k query efficiently. It has to fetch all matching albums, sort them by\n `ListenTimestamp,` and return the top 10. Such a query uses more resources\n if there's a large number of documents that contain the term \"happy\".\n\n ### GoogleSQL\n\n SELECT AlbumId\n FROM Albums\n WHERE SEARCH(AlbumTitle_Tokens, 'happy')\n ORDER BY ListenTimestamp DESC\n LIMIT 10\n\n ### PostgreSQL\n\n SELECT albumid\n FROM albums\n WHERE spanner.search(albumtitle_tokens, 'happy')\n ORDER BY listentimestamp DESC\n LIMIT 10\n\n- Similarly, a query doesn't run efficiently if it requests that results are\n ordered using the `RecordTimestamp` column in ascending order. It scans all\n rows with the word \"happy\", despite having a `LIMIT`.\n\n ### GoogleSQL\n\n SELECT AlbumId\n FROM Albums\n WHERE SEARCH(AlbumTitle_Tokens, 'happy')\n ORDER BY RecordTimestamp ASC\n LIMIT 10\n\n ### PostgreSQL\n\n SELECT albumid\n FROM albums\n WHERE spanner.search(albumtitle_tokens, 'happy')\n ORDER BY recordtimestamp ASC\n LIMIT 10\n\nWhat's next\n-----------\n\n- Learn about [full-text search queries](/spanner/docs/full-text-search/query-overview).\n- Learn how to [rank search results](/spanner/docs/full-text-search/ranked-search).\n- Learn how to [paginate search results](/spanner/docs/full-text-search/paginate-search-results).\n- Learn how to [mix full-text and non-text queries](/spanner/docs/full-text-search/mix-full-text-and-non-text-queries).\n- Learn how to [search multiple columns](/spanner/docs/full-text-search/search-multiple-columns)."]]