색인

모든 Datastore 모드의 Firestore 쿼리는 색인의 속성에 지정된 순서대로 항목 키와 항목의 선택적 상위를 포함하는 색인을 한 개 이상 사용하여 결과를 계산합니다. 색인은 애플리케이션이 해당 항목에 대해 수행하는 모든 변경 내용을 반영하도록 업데이트되므로 추가 계산 없이 모든 쿼리의 올바른 결과가 제공됩니다.

색인에는 다음과 같은 두 가지 유형이 있습니다.

내장 색인
기본적으로 Datastore 모드 데이터베이스는 각 항목 종류의 각 속성에 대한 색인을 자동으로 사전 정의합니다. 이러한 단일 속성 색인은 단순 유형의 쿼리에 적합합니다.
복합 색인
복합 색인은 색인이 생성된 항목당 여러 속성 값의 색인을 생성합니다. 복합 색인은 복합 쿼리를 지원하고 색인 구성 파일(index.yaml)에 정의됩니다.

이러한 유형의 색인에 대해서는 이 항목의 뒷부분에서 자세히 설명합니다.

색인 정의 및 구조

색인은 주어진 항목 종류의 속성을 각 속성의 해당 순서(오름차순 또는 내림차순)와 함께 표시한 목록에 정의됩니다. 상위 쿼리에 사용할 경우 색인은 항목의 상위 항목을 선택적으로 포함할 수도 있습니다.

색인 테이블은 색인 정의에서 명명된 모든 속성의 열을 포함합니다. 테이블의 각 행은 색인을 기반으로 하는 쿼리의 잠재적 결과인 항목을 나타냅니다. 항목은 색인에 사용된 모든 속성의 색인이 생성된 값이 설정되어 있는 경우에만 색인에 포함됩니다. 색인 정의가 항목에 값이 없는 속성을 나타내는 경우 해당 항목이 색인에 나타나지 않고 이런 이유로 인해 해당 항목은 색인을 기반으로 하는 쿼리의 결과로 반환되지 않습니다.

색인 테이블 행은 색인 정의에 지정된 순서대로 먼저 상위 항목별로 정렬된 다음 속성 값별로 정렬됩니다. 쿼리를 가장 효율적으로 실행할 쿼리의 완벽한 색인은 다음 속성에 다음 순서대로 정의됩니다.

  1. 균등 필터에 사용되는 속성
  2. 비균등 필터에 사용되는 속성(한 개 이내일 수 있음)
  3. 정렬 순서에 사용되는 속성
  4. 프로젝션에 사용되는 속성(아직 정렬 순서에 포함되지 않음)

이렇게 하면 쿼리의 모든 가능한 실행의 모든 결과가 테이블의 연속 행에 나타납니다. Datastore 모드 데이터베이스는 다음 단계에 따라 완벽한 색인을 사용하여 쿼리를 실행합니다.

  1. 쿼리의 종류, 필터 속성, 필터 연산자, 정렬 순서에 해당하는 색인을 식별합니다.
  2. 색인 시작 부분부터 쿼리 필터 조건을 모두 충족하는 첫 번째 항목까지 검색합니다.
  3. 색인 검색을 계속 진행하여 다음 경우가 될 때까지 각 항목을 차례로 반환합니다.
    • 필터 조건을 충족하지 않는 항목을 발견한 경우 또는
    • 색인 끝에 도달한 경우 또는
    • 쿼리에서 요청한 최대 개수의 결과를 수집한 경우

예를 들어 다음과 같은 쿼리를 살펴보겠습니다.

SELECT * FROM Task
WHERE category = 'Personal'
  AND priority < 3
ORDER BY priority DESC

이 쿼리의 완벽한 색인은 종류가 Task이고 categorypriority 속성 값 열이 있는 항목의 키 테이블입니다. 색인은 먼저 category에 따라 오름차순으로 정렬된 다음 priority에 따라 내림차순으로 정렬됩니다.

indexes:
- kind: Task
  properties:
  - name: category
    direction: asc
  - name: priority
    direction: desc

형식이 동일하지만 필터 값이 서로 다른 두 쿼리가 동일한 색인을 사용합니다. 예를 들어 다음 쿼리는 위와 동일한 색인을 사용합니다.

SELECT * FROM Task
WHERE category = 'Work'
  AND priority < 5
ORDER BY priority DESC

이 색인의 경우

indexes:
- kind: Task
  properties:
  - name: category
    direction: asc
  - name: priority
    direction: asc
  - name: created
    direction: asc

다음 두 쿼리도 형식이 서로 다르지만 동일한 색인을 사용합니다.

SELECT * FROM Task
WHERE category = 'Personal'
  AND priority = 5
ORDER BY created ASC

그리고

SELECT * FROM Task
WHERE category = 'Work'
ORDER BY priority ASC, created ASC

위에서 만든 색인은 이 두 쿼리를 모두 충족할 수 있습니다.

색인 구성

Firestore Datastore 모드는 내장 또는 다음 형식의 쿼리에 대한 자동 색인을 제공합니다.

  • 상위 및 키 필터만 사용하는 비구분 쿼리
  • 상위 및 균등 필터만 사용하는 쿼리
  • 비균등 필터만 사용하는 쿼리(단일 속성으로 제한됨)
  • 상위 필터, 속성의 균등 필터, 키의 비균등 필터만 사용하는 쿼리
  • 필터가 없고 속성의 정렬 순서 하나만(오름차순 또는 내림차순) 있는 쿼리

예를 들어 기본적으로 Datastore 모드 데이터베이스는 각 항목 종류의 각 속성에 대한 두 단일 속성 색인(하나는 오름차순으로, 다른 하나는 내림차순으로)을 자동으로 미리 정의합니다. 데이터베이스에서 속성의 색인을 유지하지 않도록 하려면 색인에서 속성을 제외합니다. 속성을 제외하면 모든 복합 색인에서 해당 속성이 제거됩니다.

내장 색인만으로도 균등 전용 쿼리 및 단순 비균등 쿼리와 같은 여러 단순 쿼리를 수행할 수 있습니다.

내장 색인은 Google Cloud Console의 색인 페이지에 표시되지 않습니다.

보다 복잡한 쿼리의 경우 애플리케이션은 복합 또는 수동 색인을 정의해야 합니다. 복합 색인은 다음 형식의 쿼리에 필요합니다.

  • 상위 및 비균등 필터가 있는 쿼리
  • 한 속성에 대한 하나 이상의 비균등 필터 및 다른 속성에 대한 하나 이상의 균등 필터가 있는 쿼리
  • 키의 내림차순 정렬 순서가 있는 쿼리
  • 여러 정렬 순서가 있는 쿼리
  • 하나 이상의 필터 및 하나 이상의 정렬 순서가 있는 쿼리

복합 색인은 애플리케이션의 색인 구성 파일(index.yaml)에 정의됩니다(내장 색인은 색인 구성 파일에 포함되지 않음).

복합 색인은 여러 속성으로 구성되며 각 개별 속성이 색인에서 제외되지 않아야 합니다.

복합 색인은 Cloud Console의 색인 페이지에서 볼 수 있습니다. Cloud Console을 사용하여 복합 색인을 만들거나 업데이트할 수 없습니다.

애플리케이션에서 사용 가능한 색인(색인 구성 파일에 지정되거나 내장된 색인)을 사용하여 실행할 수 없는 쿼리를 수행하려고 하면 쿼리가 실패합니다.

Datastore 모드 API는 대부분의 애플리케이션에 적합한 색인을 자동으로 제안합니다. 애플리케이션의 Datastore 모드 데이터베이스 사용 방식과 데이터의 크기 및 모양에 따라 색인을 수동으로 조정해야 할 수 있습니다. 예를 들어 속성 값이 여러 개인 항목을 작성할 때 스토리지 비용이 많이 드는 과도 색인이 발생할 수 있습니다.

Datastore 에뮬레이터를 사용하면 색인 구성 파일을 보다 쉽게 관리할 수 있습니다. 쿼리에 색인이 필요하지만 없는 경우 Datastore 에뮬레이터는 색인 구성을 생성하여 쿼리를 성공적으로 실행합니다. 애플리케이션의 로컬 테스트에서 필터와 정렬 순서의 모든 조합을 사용하여 애플리케이션에서 발생할 수 있는 모든 쿼리를 실행하는 경우 생성된 항목은 색인의 전체 집합을 나타냅니다. 테스트에서 가능한 쿼리 형식을 모두 실행하지는 않는 경우 색인을 업데이트하기 전에 색인 구성 파일을 검토하고 조정할 수 있습니다.

색인 구성에서 index.yaml에 대해 자세히 알아볼 수 있습니다.

색인 배포 또는 삭제

색인 구성 파일을 수정한 후 gcloud datastore indexes create 명령어를 실행하여 서비스에 색인을 사용합니다. 색인 업데이트에 대해 자세히 알아보세요.

더 이상 필요하지 않은 색인을 이전에 배포한 경우 사용하지 않는 색인을 삭제할 수 있습니다.

색인 및 속성

아래에서는 색인에 대해 고려해야 할 몇 가지 특수 상황과 이러한 상황이 항목 속성과 어떤 연관이 있는지 알아봅니다.

값 유형이 혼합된 속성

두 항목에 이름이 같지만 값 유형이 서로 다른 속성이 있으면 속성 색인이 항목을 먼저 값 유형별로 정렬한 다음 각 유형에 해당되는 두 번째 순서대로 정렬합니다. 예를 들어 두 항목에 각각 이름이 age이며 하나는 정수 값, 하나는 문자열 값을 가진 속성이 있는 경우 age 속성에 따라 정렬할 때 속성 값 자체와는 관계없이 항상 정수 값을 가진 항목이 문자열 값을 가진 항목보다 앞에 옵니다.

이는 특히 Datastore 모드에서 별도 유형으로 처리되는 정수와 부동 소수점 숫자의 경우에 주의해야 합니다. 모든 정수는 모든 부동 소수점 이전에 정렬되므로 정수 값 38의 속성이 부동 소수점 값 37.5인 속성보다 먼저 정렬됩니다.

제외된 속성

특정 속성을 필터링하거나 정렬할 필요가 없다고 판단되면 해당 속성을 색인에서 제외하여 Datastore 모드 데이터베이스에서 해당 속성의 색인 항목을 유지하지 않도록 지정할 수 있습니다. 이렇게 하면 색인 항목에 필요한 스토리지 크기를 줄여 애플리케이션 실행 비용을 절감할 수 있습니다. 제외된 속성이 있는 항목은 속성이 설정되지 않은 것처럼 작동합니다. 제외된 속성의 필터 또는 정렬 순서가 있는 쿼리는 이러한 항목과 일치하지 않습니다.

다음 예시의 description 속성은 색인에서 제외됩니다.

C#

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore C# API 참조 문서를 참조하세요.

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["category"] = "Personal",
    ["created"] = new DateTime(1999, 01, 01, 0, 0, 0, DateTimeKind.Utc),
    ["done"] = false,
    ["priority"] = 4,
    ["percent_complete"] = 10.0,
    ["description"] = new Value()
    {
        StringValue = "Learn Cloud Datastore",
        ExcludeFromIndexes = true
    },
};

Go

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Go API 참조 문서를 참조하세요.

type Task struct {
	Category        string
	Done            bool
	Priority        int
	Description     string `datastore:",noindex"`
	PercentComplete float64
	Created         time.Time
}
task := &Task{
	Category:        "Personal",
	Done:            false,
	Priority:        4,
	Description:     "Learn Cloud Datastore",
	PercentComplete: 10.0,
	Created:         time.Now(),
}

자바

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore 자바 API 참조 문서를 참조하세요.

Entity task = Entity.newBuilder(taskKey)
    .set("category", "Personal")
    .set("created", Timestamp.now())
    .set("done", false)
    .set("priority", 4)
    .set("percent_complete", 10.0)
    .set("description",
      StringValue.newBuilder("Learn Cloud Datastore").setExcludeFromIndexes(true).build())
    .build();

Node.js

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Node.js API 참조 문서를 참조하세요.

const task = [
  {
    name: 'category',
    value: 'Personal',
  },
  {
    name: 'created',
    value: new Date(),
  },
  {
    name: 'done',
    value: false,
  },
  {
    name: 'priority',
    value: 4,
  },
  {
    name: 'percent_complete',
    value: 10.0,
  },
  {
    name: 'description',
    value: 'Learn Cloud Datastore',
    excludeFromIndexes: true,
  },
];

PHP

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore PHP API 참조 문서를 참조하세요.

$task = $datastore->entity(
    $key,
    [
        'category' => 'Personal',
        'created' => new DateTime(),
        'done' => false,
        'priority' => 4,
        'percent_complete' => 10.0,
        'description' => 'Learn Cloud Datastore'
    ],
    ['excludeFromIndexes' => ['description']]
);

Python

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Python API 참조 문서를 참조하세요.

task = datastore.Entity(key, exclude_from_indexes=["description"])
task.update(
    {
        "category": "Personal",
        "description": "Learn Cloud Datastore",
        "created": datetime.datetime.utcnow(),
        "done": False,
        "priority": 4,
        "percent_complete": 10.5,
    }
)

Ruby

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Ruby API 참조 문서를 참조하세요.

task = datastore.entity "Task" do |t|
  t["category"] = "Personal"
  t["created"] = Time.now
  t["done"] = false
  t["priority"] = 4
  t["percent_complete"] = 10.0
  t["description"] = "Learn Cloud Datastore"
  t.exclude_from_indexes! "description", true
end

GQL

해당 없음

description 속성이 제외된 경우 다음 예시의 쿼리는 결과를 반환하지 않습니다.

C#

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore C# API 참조 문서를 참조하세요.

Query query = new Query("Task")
{
    Filter = Filter.Equal("description", "Learn Cloud Datastore")
};

Go

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Go API 참조 문서를 참조하세요.

query := datastore.NewQuery("Tasks").Filter("Description =", "A task description")

자바

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore 자바 API 참조 문서를 참조하세요.

Query<Entity> query = Query.newEntityQueryBuilder()
    .setKind("Task")
    .setFilter(PropertyFilter.eq("description", "A task description"))
    .build();

Node.js

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Node.js API 참조 문서를 참조하세요.

const query = datastore
  .createQuery('Task')
  .filter('description', '=', 'A task description.');

PHP

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore PHP API 참조 문서를 참조하세요.

$query = $datastore->query()
    ->kind('Task')
    ->filter('description', '=', 'A task description.');

Python

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Python API 참조 문서를 참조하세요.

query = client.query(kind="Task")
query.add_filter("description", "=", "Learn Cloud Datastore")

Ruby

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Ruby API 참조 문서를 참조하세요.

query = datastore.query("Task")
                 .where("description", "=", "A task description.")

GQL


# Will not return any results!
SELECT * FROM Task WHERE description = 'A task description.'

나중에 속성을 색인이 생성된 속성으로 다시 변경할 수 있습니다.

그러나 속성을 제외한 속성에서 색인이 생성된 속성으로 변경하는 경우 변경 작업이 수행되기 전에 만들어졌을 수도 있는 기존 항목에는 영향을 주지 않습니다. 속성에서 쿼리 필터링하면 이러한 기존 항목이 반환되지 않습니다. 이러한 항목은 만들어졌을 때 쿼리의 색인에 작성되지 않았기 때문입니다. 향후 쿼리에서 액세스할 수 있는 항목을 만들려면 해당 항목이 적합한 색인에 입력되도록 항목을 데이터베이스에 다시 작성해야 합니다. 즉, 이러한 기존 항목 각각에 대해 다음을 수행해야 합니다.

  1. 항목을 조회합니다(get).
  2. 항목을 데이터베이스에 다시 씁니다(put).

마찬가지로 속성을 색인이 생성된 속성에서 제외된 속성으로 변경하는 경우 이후에 데이터베이스에 작성된 항목에만 영향을 줍니다. 해당 속성이 있는 기존 항목의 색인 항목은 항목이 업데이트되거나 삭제될 때까지 계속 존재합니다. 원하는 결과를 얻으려면 코드에서 속성(지금은 제외된 속성임)별로 필터링하거나 정렬하는 모든 쿼리를 삭제해야 합니다.

색인 제한

Datastore 모드의 Firestore는 단일 항목과 연결할 수 있는 색인 항목의 수와 전체 크기를 제한합니다. 이러한 제한 사항은 크며 대부분의 애플리케이션은 영향을 받지 않습니다. 그러나 이러한 제한이 발생할 수 있는 상황이 있습니다.

위에서 설명한 대로 Datastore 모드 데이터베이스는 색인에서 제외된 것으로 명시적으로 선언한 항목을 제외한 모든 항목의 모든 속성에 대해 미리 정의된 색인에서 항목을 만듭니다. 이 속성은 색인 구성 파일(index.yaml)에 선언된 추가 커스텀 색인에 포함될 수도 있습니다. 항목에 목록 속성이 없다면 항목에는 해당 커스텀 색인(비상위 색인용) 각각에 대해 최대 한 개의 항목 또는 항목의 상위 항목(상위 색인용) 각각에 대해 최대 한 개의 항목이 지정됩니다. 속성 값이 변경될 때마다 이러한 색인 항목이 각각 업데이트되어야 합니다.

항목마다 단일 값을 포함하는 속성의 경우 가능한 각각의 값은 속성의 미리 정의된 색인에 항목당 한 번씩만 저장되어야 합니다. 이렇게 해도 이러한 단일 값 속성이 매우 많은 항목이 색인 항목 또는 크기 제한을 초과할 수 있습니다. 마찬가지로 동일한 속성의 여러 값을 포함할 수 있는 항목의 경우 각 값에 별도의 색인 항목이 필요합니다. 다시 말해 가능한 값 수가 크면 이러한 항목이 항목 제한을 초과할 수 있습니다.

속성이 여러 개인 항목이 있는 경우 상황이 악화될 수 있습니다. 이러한 속성 각각 여러 값을 사용할 수 있기 때문입니다. 이러한 항목을 수용하려면 색인에 속성 값의 모든 가능한 조합에 대한 항목이 포함되어야 합니다. 각각 값이 여러 개인 여러 속성을 참조하는 커스텀 색인은 조합을 통해 '과도'해질 수 있습니다. 이 경우 상대적으로 적은 수의 가능한 속성 값만 있는 항목에 많은 수의 항목이 필요해집니다. 이러한 과도 색인은 저장되어야 하는 많은 수의 색인 항목으로 인해 항목의 스토리지 크기를 크게 늘릴 수 있습니다. 또한 과도 색인으로 인해 항목이 색인 항목 개수 또는 크기 제한을 쉽게 초과할 수 있습니다.

다음 코드를 살펴보세요.

C#

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore C# API 참조 문서를 참조하세요.

Entity task = new Entity()
{
    Key = _db.CreateKeyFactory("Task").CreateKey("sampleTask"),
    ["tags"] = new ArrayValue() { Values = { "fun", "programming", "learn" } },
    ["collaborators"] = new ArrayValue() { Values = { "alice", "bob", "charlie" } },
    ["created"] = DateTime.UtcNow
};

Go

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Go API 참조 문서를 참조하세요.

task := &Task{
	Tags:          []string{"fun", "programming", "learn"},
	Collaborators: []string{"alice", "bob", "charlie"},
	Created:       time.Now(),
}

자바

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore 자바 API 참조 문서를 참조하세요.

Entity task = Entity.newBuilder(taskKey)
    .set("tags", "fun", "programming", "learn")
    .set("collaborators", "alice", "bob", "charlie")
    .set("created", Timestamp.now())
    .build();

Node.js

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Node.js API 참조 문서를 참조하세요.

const task = {
  method: 'insert',
  key: datastore.key('Task'),
  data: {
    tags: ['fun', 'programming', 'learn'],
    collaborators: ['alice', 'bob', 'charlie'],
    created: new Date(),
  },
};

PHP

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore PHP API 참조 문서를 참조하세요.

$task = $datastore->entity(
    $datastore->key('Task'),
    [
        'tags' => ['fun', 'programming', 'learn'],
        'collaborators' => ['alice', 'bob', 'charlie'],
        'created' => new DateTime(),
    ]
);

Python

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Python API 참조 문서를 참조하세요.

task = datastore.Entity(client.key("Task"))
task.update(
    {
        "tags": ["fun", "programming", "learn"],
        "collaborators": ["alice", "bob", "charlie"],
        "created": datetime.datetime.utcnow(),
    }
)

Ruby

Cloud Datastore용 클라이언트 라이브러리를 설치하고 사용하는 방법은 Cloud Datastore 클라이언트 라이브러리를 참조하세요. 자세한 내용은 Cloud Datastore Ruby API 참조 문서를 참조하세요.

task = datastore.entity "Task" do |t|
  t["tags"] = ["fun", "programming", "learn"]
  t["collaborators"] = ["alice", "bob", "charlie"]
  t["created"] = Time.now
end

GQL

해당 없음

이 코드는 tags 속성 값이 3개이고 collaborators 속성 값이 3개이며, created가 현재 날짜로 설정된 Task 항목을 만듭니다. 이 경우 속성 값의 가능한 조합 각각에 하나씩 총 9개의 색인 항목이 필요합니다.

('fun', 'alice', NOW())
('fun', 'bob', NOW())
('fun', 'charlie', NOW())

('programming', 'alice', NOW())
('programming', 'bob', NOW())
('programming', 'charlie', NOW())

('learn', 'alice', NOW())
('learn', 'bob', NOW())
('learn', 'charlie', NOW())

동일한 속성이 여러 번 반복되면 Datastore 모드의 Firestore에서 과도 색인을 감지하고 대체 색인을 제안할 수 있습니다. 그러나 다른 모든 상황(예: 이 예시에 정의된 쿼리)에서는 Datastore 모드 데이터베이스가 과도 색인을 생성합니다. 이 경우 색인 구성 파일에서 수동으로 색인을 구성하여 과도 색인을 우회할 수 있습니다.

indexes:
- kind: Task
  properties:
  - name: tags
  - name: created
- kind: Task
  properties:
  - name: collaborators
  - name: created

이렇게 하면 필요한 항목 수가 9개가 아닌 6개((|tags| * |created| + |collaborators| * |created|))로 줄어듭니다.

('fun', NOW())
('programming', NOW())
('learn', NOW())

('alice', NOW())
('bob', NOW())
('charlie', NOW())

색인이 색인 항목 또는 크기 제한을 초과할 모든 commit 작업이 실패합니다. 오류 텍스트를 통해 초과한 제한("Too many indexed properties" 또는 "Index entries too large")과 원인으로 작용한 커스텀 색인을 확인할 수 있습니다. 빌드 시 항목 제한을 초과하는 새 색인을 만들면 해당 색인에 대한 쿼리가 실패하고 색인은 Cloud Console에서 Error 상태로 표시됩니다. 이러한 Error 색인을 처리하려면 다음 안내를 따르세요.

  1. 색인 구성 파일(index.yaml)에서 해당 색인을 제거합니다.
  2. gcloud 명령줄 도구에서 사용되지 않는 색인 삭제에 설명된 대로 vacuum_indexes 옵션을 사용하여 색인을 삭제합니다.
  3. 다음 중 하나를 수행합니다.
    • 색인 정의 및 해당 쿼리 다시 작성
    • 색인 과도화를 유발하는 항목 제거
  4. 색인을 index.yaml에 다시 추가합니다.
  5. gcloud 명령줄 도구에서 색인 업데이트에 설명된 대로 update_indexes 옵션을 사용하여 색인을 업데이트합니다.

목록 속성을 사용하여 커스텀 색인을 필요로 하는 쿼리를 방지하여 색인 과도화를 피할 수 있습니다. 위에서 설명한 대로 여기에는 균등 필터와 비균등 필터가 혼합된 쿼리 또는 여러 정렬 순서의 쿼리가 포함됩니다.

프로젝션 색인

프로젝션 쿼리를 사용하려면 프로젝션에 지정된 모든 속성이 색인에 포함되어야 합니다. Datastore 에뮬레이터는 애플리케이션과 함께 업로드되는 색인 구성 파일인 index.yaml에서 필요한 색인을 자동으로 생성합니다.

필요한 색인 수를 최소화하는 한 가지 방법은 모든 속성이 항상 필요하지 않더라도 동일한 속성을 일관적으로 프로젝션하는 것입니다. 예를 들어 다음 쿼리에는 별도의 색인 두 개가 필요합니다.

SELECT priority, percent_complete FROM Task

SELECT priority, percent_complete, created FROM Task

그러나 항상 priority, percent_complete, created 속성을 프로젝션하면 created가 필요하지 않는 경우에도 한 개의 색인만 필요합니다.

기존 쿼리를 프로젝션으로 변환하려면 프로젝션의 속성이 쿼리의 다른 부분에 이미 포함되어 있지 않은 경우 새 색인을 빌드해야 할 수도 있습니다. 예를 들어 다음과 같은 기존 쿼리가 있다고 가정합니다.

SELECT * FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

이러한 쿼리에는 다음과 같은 색인이 필요합니다.

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete

이를 다음 프로젝션 쿼리 중 하나로 변환합니다.

SELECT created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

SELECT priority, percent_complete, created FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

새 속성(created)을 도입합니다. 그러면 새 색인을 빌드해야 합니다.

indexes:
- kind: Task
  properties:
  - name: priority
  - name: percent_complete
  - name: created

그러나

SELECT priority, percent_complete FROM Task
WHERE priority > 1
ORDER BY priority, percent_complete

이 쿼리의 경우 프로젝션된 속성 prioritypercent_complete가 이미 기존 쿼리에 포함되어 있기 때문에 필수 색인을 변경하지 않습니다.