Cloud Datastore 색인

참고: 새로운 애플리케이션을 빌드하는 개발자에게는 NDB 클라이언트 라이브러리 사용을 적극 권장합니다. 기존 클라이언트 라이브러리에 비해 Memcache API를 통한 자동 항목 캐싱과 같은 여러 이점이 있습니다. 현재 기존 DB 클라이언트 라이브러리를 사용하는 중이라면 DB에서 NDB로의 이전 가이드를 참조하세요.

App Engine은 항목의 각 속성에 대해 간단한 색인을 사전 정의합니다. App Engine 애플리케이션은 index.yaml이라는 색인 구성 파일에서 커스텀 색인을 추가로 정의할 수 있습니다. 개발 서버는 기존 색인으로 실행할 수 없는 쿼리를 발견할 때 이 파일에 자동으로 제안 항목을 추가합니다. 애플리케이션을 업로드하기 전에 이 파일을 수정하여 색인을 수동으로 미세 조정할 수 있습니다.

참고: 색인 기준 쿼리 메커니즘은 다양한 쿼리를 지원하고 대부분의 애플리케이션에 적합하지만 다른 데이터베이스 기술에 일반적으로 사용되는 몇 가지 쿼리 종류를 지원하지 않습니다. 특히 조인 및 집계 쿼리는 Cloud Datastore 쿼리 엔진 내에서 지원되지 않습니다. Cloud Datastore 쿼리의 제한사항은 Datastore 쿼리 페이지를 참조하세요.

색인 정의 및 구조

색인은 지정된 항목 종류의 속성 목록에 대해 정의되며, 각 속성에 해당하는 순서(오름차순 또는 내림차순)가 있습니다. 상위 쿼리에 사용할 경우 색인에 항목의 상위 항목을 포함할 수도 있습니다.

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

참고: Cloud Datastore는 속성이 없는 항목과 null 값(None)이 있는 항목을 구분합니다. 항목 속성에 null 값을 명시적으로 할당하면 해당 항목이 해당 속성을 참조하는 쿼리의 결과에 포함될 수 있습니다.

참고: 여러 속성으로 구성된 색인을 사용하려면 각 개별 속성에 대해 색인이 해제되어 있지 않아야 합니다.

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

  1. 균등 필터에 사용되는 속성
  2. 비균등 필터에 사용되는 속성(한 개 이내일 수 있음)
  3. 정렬 순서에 사용되는 속성

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

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

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

SELECT * FROM Person WHERE last_name = "Smith"
                       AND height < 72
                  ORDER BY height DESC

이 쿼리의 완벽한 색인은 종류가 Person이고 last_nameheight 속성 값 열이 있는 항목의 키 테이블입니다. 색인은 먼저 last_name을 기준으로 오름차순으로 정렬된 다음 height를 기준으로 내림차순으로 정렬됩니다.

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

SELECT * FROM Person WHERE last_name = "Jones"
                       AND height < 63
                     ORDER BY height DESC

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

SELECT * FROM Person WHERE last_name = "Friedkin"
                       AND first_name = "Damian"
                     ORDER BY height ASC

SELECT * FROM Person WHERE last_name = "Blair"
                  ORDER BY first_name, height ASC

색인 구성

기본적으로 Cloud Datastore는 각 항목 종류의 각 속성에 대한 색인을 자동으로 사전 정의합니다. 이렇게 사전 정의된 색인만으로도 균등 전용 쿼리 및 단순 비균등 쿼리와 같은 여러 단순 쿼리를 실행할 수 있습니다. 다른 모든 쿼리의 경우 애플리케이션이 index.yaml이라는 색인 구성 파일에 필요한 색인을 정의해야 합니다. 애플리케이션이 사용 가능한 색인(사전 정의된 색인 또는 색인 구성 파일에 지정된 색인)으로 실행할 수 없는 쿼리를 실행하려고 하면 쿼리가 실패하고 NeedIndexError 예외가 발생합니다.

Datastore는 다음과 같은 형식의 쿼리에 대해 자동 색인을 작성합니다.

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

다음을 비롯한 다른 형식의 쿼리는 색인 구성 파일에 색인을 지정해야 합니다.

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

색인 및 속성

아래에서는 색인에 대해 고려해야 할 몇 가지 특이사항과 이러한 항목이 Cloud Datastore의 항목 속성과 어떻게 관련되는지 알아봅니다.

값 유형이 혼합된 속성

두 항목에 이름이 같지만 값 유형이 서로 다른 속성이 있으면 속성 색인이 항목을 먼저 값 유형별로 정렬한 다음 각 유형에 적절한 2차 순서대로 정렬합니다. 예를 들어 두 항목 각각에 이름이 age인 속성이 있는데 하나에는 정수 값이 있고 다른 하나에는 문자열 값이 있을 경우 age 속성별로 정렬하면 속성 값 자체에 상관없이 정수 값이 있는 항목이 항상 문자열 값이 있는 항목보다 먼저 나열됩니다.

이는 특히 Cloud Datastore에서 별도의 유형으로 처리되는 정수와 부동 소수점 숫자가 나올 때 기억하면 유용합니다. 모든 정수는 모든 부동 소수점보다 먼저 정렬되므로 정수 값 38이 있는 속성이 부동 소수점 값 37.5가 있는 속성보다 먼저 정렬되기 때문입니다.

색인이 생성되지 않은 속성

특정 속성을 기준으로 필터링하거나 정렬할 필요가 없다고 판단되면 색인이 생성되지 않은 속성으로 선언하여 Cloud Datastore에서 해당 속성의 색인 항목을 유지하지 않도록 지정할 수 있습니다. 이렇게 하면 수행해야 하는 Cloud Datastore 쓰기 횟수를 줄여 애플리케이션 실행 비용을 절감할 수 있습니다. 색인이 생성되지 않은 속성이 있는 항목은 속성이 설정되지 않은 것처럼 동작합니다. 즉, 색인이 생성되지 않은 속성의 필터 또는 정렬 순서를 사용하는 쿼리는 이러한 항목과 일치하지 않습니다.

참고: 여러 속성으로 구성된 색인에 속성이 나타날 경우 이를 색인이 생성되지 않은 속성으로 설정하면 구성된 색인에서 해당 속성의 색인이 생성되지 않습니다.

예를 들어 항목에 ab 속성이 있고 WHERE a ="bike" and b="red" 같은 쿼리를 충족할 수 있는 색인을 만들려고 한다고 가정해 보겠습니다. 또한 WHERE a="bike"WHERE b="red" 쿼리를 고려하지 않는다고 가정하겠습니다. a를 색인이 생성되지 않은 속성으로 설정하고 ab를 위한 색인을 만들면 Cloud Datastore가 ab 색인을 위한 색인 항목을 만들지 않으므로 WHERE a="bike" and b="red" 쿼리가 작동하지 않습니다. Cloud Datastore가 ab 색인을 위한 항목을 만들려면 ab 모두에 대해 색인을 만들어야 합니다.

다음과 같이 속성 생성자에서 indexed=False를 설정하여 색인이 생성되지 않은 속성을 선언합니다.

class Person(db.Model):
  name = db.StringProperty()
  age = db.IntegerProperty(indexed=False)

이후에 indexed=True로 이 생성자를 다시 호출하여 속성을 색인이 생성된 속성으로 다시 변경할 수 있습니다.

class Person(db.Model):
  name = db.StringProperty()
  age = db.IntegerProperty(indexed=True)

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

  1. Cloud Datastore에서 항목을 검색합니다(가져오기).
  2. 항목을 Cloud Datastore에 다시 작성합니다(배치).

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

색인 제한

Datastore는 단일 항목과 연결할 수 있는 색인 항목의 수 및 전체 크기에 제한을 적용합니다. 이러한 제한 값은 크기 때문에 대부분의 애플리케이션이 영향을 받지 않습니다. 하지만 이러한 제한에 도달하게 될 수도 있는 상황이 있습니다.

에 설명된 대로 Cloud Datastore는 긴 텍스트 문자열(Text) 및 긴 바이트 문자열(Blob) 속성과 명시적으로 색인이 생성되지 않은 속성으로 선언한 속성을 제외하고 모든 항목의 모든 속성에 대해 사전 정의된 색인에서 항목을 만듭니다. 이 속성은 index.yaml 구성 파일에 선언된 추가 커스텀 색인에 포함될 수 있습니다. 항목에 목록 속성이 없다면 항목에는 해당 커스텀 색인(비상위 색인용) 각각에 대해 최대 한 개의 항목 또는 항목의 상위 항목(상위 색인용) 각각에 대해 최대 한 개의 항목이 지정됩니다. 속성 값이 변경될 때마다 이러한 색인 항목 각각을 업데이트해야 합니다.

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

속성이 여러 개인 항목이 있는 경우 상황이 더 악화될 수 있습니다. 이러한 속성 각각에 여러 값이 사용될 수 있기 때문입니다. 이러한 항목을 수용하려면 색인에 모든 가능한 속성 값의 조합을 위한 항목을 포함해야 합니다. 각각 값이 여러 개인 여러 속성을 참조하는 커스텀 색인은 조합을 통해 '과도'해질 수 있습니다. 이 경우 상대적으로 적은 수의 가능한 속성 값만 있는 항목에 많은 수의 항목이 필요해집니다. 이러한 과도 색인은 업데이트해야 하는 많은 수의 색인 항목 때문에 Cloud Datastore에 항목을 작성하는 비용을 크게 증가시킬 수 있으며, 이로 인해 항목이 색인 항목 또는 크기 제한을 쉽게 초과할 수 있습니다.

쿼리 살펴보기

SELECT * FROM Widget WHERE x=1 AND y=2 ORDER BY date

이 쿼리를 실행하면 SDK에서 다음 색인을 제안합니다.

indexes:
- kind: Widget
  properties:
  - name: x
  - name: y
  - name: date
이 색인은 각 항목마다 총 |x| * |y| * |date|개의 색인 항목을 필요로 합니다. 여기서 |x|x 속성에 대해 항목과 연결된 값의 수를 나타냅니다. 다음 코드를 예로 들겠습니다.
class Widget(db.Expando):
  pass

e2 = Widget()
e2.x = [1, 2, 3, 4]
e2.y = ['red', 'green', 'blue']
e2.date = datetime.datetime.now()
e2.put()

이 코드는 x 속성 값이 4개이고 ydate 속성의 3개 값이 현재 날짜로 설정된 항목을 만듭니다. 이 경우 가능한 속성 값 조합마다 하나씩, 총 12개의 색인 항목이 필요합니다.

(1, "red", <now>)(1, "green", <now>)(1, "blue", <now>)

(2, "red", <now>)(2, "green", <now>)(2, "blue", <now>)

(3, "red", <now>)(3, "green", <now>)(3, "blue", <now>)

(4, "red", <now>)(4, "green", <now>)(4, "blue", <now>)

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

indexes:
- kind: Widget
  properties:
  - name: x
  - name: date
- kind: Widget
  properties:
  - name: y
  - name: date
이렇게 하면 필요한 항목 수가 12개 대신 (|x| * |date| + |y| * |date|)개 또는 7개 항목으로 줄어듭니다.

(1, <now>)(2, <now>)(3, <now>)(4, <now>)

("red", <now>)("green", <now>)("blue", <now>)

색인이 색인 항목 또는 크기 제한을 초과하게 만드는 모든 put 작업은 실패하며, [`BadRequestError`](exceptions#BadRequestError) 예외가 발생합니다. 예외 텍스트를 통해 초과한 제한("Too many indexed properties" 또는 "Index entries too large")과 원인으로 작용한 커스텀 색인을 확인할 수 있습니다. 빌드 시 항목의 제한이 초과되는 새 색인을 만들면 해당 색인에 대한 쿼리가 실패하고 색인이 GCP 콘솔에서 Error 상태로 표시됩니다. Error 상태의 색인을 해결하는 방법은 다음과 같습니다.

  1. index.yaml 파일에서 Error 상태의 색인을 삭제합니다.

  2. index.yaml이 위치한 디렉토리에서 다음 명령어를 실행하여 Cloud Datastore에서 해당 색인을 삭제합니다.

    gcloud datastore cleanup-indexes index.yaml
    
  3. 오류의 원인을 해결합니다. 예를 들면 다음과 같습니다.

    • 색인 정의와 해당 쿼리를 다시 작성합니다.
    • 과도 색인을 발생시키는 항목을 삭제합니다.
  4. index.yaml 파일에 다시 색인을 추가합니다.

  5. index.yaml이 위치한 디렉토리에서 다음 명령어를 실행하여 Cloud Datastore에서 색인을 만듭니다.

    gcloud datastore create-indexes index.yaml
    

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

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

App Engine standard environment for Python 2