참고: 새로운 애플리케이션을 빌드하는 개발자는 NDB 클라이언트 라이브러리를 사용하는 것이 좋습니다. NDB 클라이언트 라이브러리는 이 클라이언트 라이브러리와 비교할 때 Memcache API를 통한 자동 항목 캐싱과 같은 여러 이점이 있습니다. 현재 이전 DB 클라이언트 라이브러리를 사용 중인 경우 DB에서 NDB로의 마이그레이션 가이드를 참조하세요.
Datastore의 데이터 객체를 항목이라고 합니다. 항목에는 명명된 속성이 한 개 이상 있으며 각 속성에는 값이 한 개 이상 있을 수 있습니다. 같은 종류의 항목이라도 속성이 동일할 필요는 없으며, 항목의 특정 속성 값이 모두 동일한 데이터 유형이 아니어도 됩니다. 필요한 경우 애플리케이션이 자체 데이터 모델에 이러한 제한을 설정하고 시행할 수 있습니다.
Datastore는 다양한 속성 값 데이터 유형을 지원합니다. 여기에는 다음이 포함됩니다.
- 정수
- 부동 소수점 수
- 문자열
- 날짜
- 바이너리 데이터
전체 유형 목록은 속성 및 값 유형을 참조하세요.
Datastore의 각 항목에는 항목을 고유하게 식별하는 키가 있습니다. 키는 다음 구성요소로 구성됩니다.
- 멀티테넌시를 허용하는 항목의 네임스페이스
- Datastore 쿼리 목적으로 항목을 분류하는 항목의 종류
- 다음 중 하나에 해당하는 개별 항목의 식별자
- 키 이름 문자열
- 정수 숫자 ID
- Datastore 계층 구조에서 항목 위치를 나타내는 선택적 상위 경로
애플리케이션은 항목의 키를 사용하여 Datastore에서·개별 항목을 가져오거나 항목 키 또는 속성 값에 따라 쿼리를 실행하여 항목을 한 개 이상 검색할 수 있습니다.
Python App Engine SDK에는 Datastore 항목을 Python 클래스의 인스턴스로 나타내고, 이러한 인스턴스를 Datastore에 저장하고 검색하기 위한 데이터 모델링 라이브러리가 포함되어 있습니다.
Datastore 자체는 지정된 속성에 특정 유형의 값이 있는지 여부와 같은 항목 구조에 대한 제한을 적용하지 않습니다. 이 태스크는 애플리케이션과 데이터 모델링 라이브러리에 남습니다.
종류 및 식별자
각 Datastore 항목은 쿼리 목적으로 항목을 분류하는 특정 종류에 속합니다. 예를 들어 인사 관리 애플리케이션은 회사의 각 직원을 종류가 Employee
인 항목으로 나타낼 수 있습니다. Python Datastore API에서 항목 종류는 해당 모델 클래스에 따라 결정되며, 이러한 클래스는 애플리케이션에서 데이터 모델링 라이브러리 클래스인 db.Model
의 서브클래스로 정의합니다. 모델 클래스 이름은 여기에 속하는 항목의 종류가 됩니다. 밑줄(__
) 두 개로 시작하는 종류 이름은 모두 예약되어 있어 이를 사용할 수 없습니다.
다음 예시에서는 Employee
종류의 항목을 만들고 속성 값을 채우며 Datastore에 저장합니다.
import datetime
from google.appengine.ext import db
class Employee(db.Model):
first_name = db.StringProperty()
last_name = db.StringProperty()
hire_date = db.DateProperty()
attended_hr_training = db.BooleanProperty()
employee = Employee(first_name='Antonio',
last_name='Salieri')
employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True
employee.put()
Employee
클래스는 데이터 모델의 4가지 속성 first_name
, last_name
, hire_date
, attended_hr_training
을 선언합니다. Model
슈퍼클래스는 Employee
객체의 속성이 이 모델을 준수하도록 보장합니다. 예를 들어 hire_date
속성에 문자열 값을 할당하려고 하면 런타임 오류가 발생합니다. hire_date
의 데이터 모델이 db.DateProperty
로 선언되었기 때문입니다.
종류 외에도 각 항목에는 항목이 생성될 때 할당된 식별자가 있습니다. 식별자는 항목 키의 일부이므로 항목과 영구적으로 연관되며 변경할 수 없습니다. 식별자를 할당할 수 있는 두 가지 방법은 다음과 같습니다.
- 애플리케이션은 항목에 자체 키 이름 문자열을 지정할 수 있습니다.
- Datastore에서 항목에 정수 숫자 ID를 자동으로 할당하도록 할 수 있습니다.
항목에 키 이름을 할당하려면 항목을 만들 때 모델 클래스 생성자에 이름이 지정된 인수 key_name
을 제공합니다.
# Create an entity with the key Employee:'asalieri'.
employee = Employee(key_name='asalieri')
Datastore가 숫자 ID를 자동으로 할당하도록 하려면 key_name
인수를 생략합니다.
# Create an entity with a key such as Employee:8261.
employee = Employee()
식별자 할당
두 가지 자동 ID 정책을 사용하여 자동으로 ID를 생성하도록 Datastore를 구성할 수 있습니다.
default
정책은 거의 균일하게 분포한 미사용 ID의 임의 시퀀스를 생성합니다. 각 ID는 최대 16자리 숫자입니다.legacy
정책은 연속되지 않는 더 작은 정수 ID 시퀀스를 만듭니다.
사용자에게 항목 ID를 표시하거나 항목 ID의 순서를 결정하려는 경우 수동으로 할당하는 것이 좋습니다.
Datastore는 거의 균일하게 분포된 임의 순서의 미사용 ID를 생성합니다. 각 ID는 최대 16자리 숫자입니다.
상위 경로
Cloud Datastore의 항목은 파일 시스템의 디렉터리 구조와 유사한 계층 구조 형식의 공간을 형성합니다. 항목을 만들 때 선택적으로 다른 항목을 상위 요소로 지정할 수 있으며, 새 항목은 상위 항목의 하위 요소가 됩니다. 파일 시스템과 달리 상위 항목이 실제로 존재할 필요는 없습니다. 상위 요소가 없는 항목은 루트 항목입니다. 항목과 상위 요소 간의 연결은 영구적이며 항목이 생성되면 변경할 수 없습니다. Cloud Datastore는 상위 요소가 동일한 2개의 항목 또는 2개의 루트 항목(상위 요소가 없는 항목)에 동일한 숫자 ID를 할당하지 않습니다.
항목의 상위 요소, 상위 요소의 상위 요소 등은 재귀적으로 해당 항목의 상위가 되고, 항목의 하위 요소, 하위 요소의 하위 요소 등은 해당 항목의 하위가 됩니다. 루트 항목과 그 하위에 있는 모든 항목은 동일한 항목 그룹에 속합니다. 루트 항목에서 시작하여 상위 요소에서 하위 요소로 진행되고 지정된 항목까지 이어지는 항목의 시퀀스를 해당 항목의 상위 경로라고 합니다. 항목을 식별하는 전체 키는 상위 경로를 지정하고 항목 자체로 종료되는 종류-식별자 쌍의 시퀀스로 구성됩니다.
[Person:GreatGrandpa, Person:Grandpa, Person:Dad, Person:Me]
루트 항목의 경우 상위 경로는 비어 있으며 키는 항목의 고유한 종류 및 식별자로만 구성됩니다.
[Person:GreatGrandpa]
이 개념은 다음 다이어그램에서 설명합니다.
항목의 상위를 지정하려면 하위 항목을 만들 때 모델 클래스 생성자에 parent
인수를 사용합니다. 이 인수 값은 상위 항목 자체이거나 키일 수 있습니다. 상위 항목의 key()
메서드를 호출하여 키를 가져올 수 있습니다. 다음 예시에서는 Address
종류의 항목을 만들고 Employee
항목을 해당 상위로 지정하는 2가지 방법을 보여줍니다.
# Create Employee entity
employee = Employee()
employee.put()
# Set Employee as Address entity's parent directly...
address = Address(parent=employee)
# ...or using its key
e_key = employee.key()
address = Address(parent=e_key)
# Save Address entity to datastore
address.put()
트랜잭션 및 항목 그룹
항목을 생성, 업데이트 또는 삭제하려는 모든 시도는 트랜잭션의 관점에서 수행됩니다. 단일 트랜잭션에 포함할 수 있는 이러한 작업의 수에는 제한이 없습니다. 데이터의 일관성을 유지하기 위해 트랜잭션은 포함된 모든 작업을 Datastore에 하나의 단위로 적용합니다. 즉, 작업이 하나라도 실패하면 어떠한 작업에도 적용되지 않습니다. 또한 동일 트랜잭션 내에서 수행되는 모든 strong consistency를 가지는 읽기(상위 쿼리 또는 get)에서 데이터의 일관된 스냅샷이 관찰됩니다.
위에 언급한 대로 항목 그룹은 상위 항목을 통해 공통 루트 요소로 연결되는 항목 집합입니다. 데이터를 항목 그룹으로 구성하면 수행 가능한 트랜잭션을 제한할 수 있습니다.
- 트랜잭션에서 액세스하는 모든 데이터는 최대 25개의 항목 그룹에만 포함될 수 있습니다.
- 트랜잭션 내에서 쿼리를 사용하려면 올바른 데이터에 일치하는 상위 필터를 지정할 수 있는 방식으로 데이터가 항목 그룹으로 구성되어 있어야 합니다.
- 단일 항목 그룹 내에서는 쓰기 처리량 한도가 초당 약 1개의 트랜잭션으로 제한되어 있습니다. 이 한도가 존재하는 이유는 Datastore가 높은 안정성과 내결함성을 제공하기 위해 광범위한 지리적 영역에 걸쳐 각 항목 그룹의 마스터 없는 동기 복제 작업을 수행하기 때문입니다.
많은 애플리케이션에서 관련성이 없는 데이터를 포괄적으로 확인할 때는 eventual consistency(즉, 여러 항목 그룹에 걸친 비상위 쿼리로 약간 오래된 데이터를 반환할 수 있음)를 사용하고 관련성이 높은 단일 데이터 세트를 보거나 수정할 때는 strong consistency(상위 쿼리 또는 단일 항목의 get
)를 사용하는 것이 좋을 수 있습니다. 이러한 애플리케이션에서는 일반적으로 관련성이 높은 각 데이터 세트마다 별도의 항목 그룹을 사용하는 방식이 바람직합니다.
자세한 내용은 strong consistency를 위한 구조화를 참조하세요.
속성 및 값 유형
항목과 연관된 데이터 값은 하나 이상의 속성으로 구성됩니다. 각 속성에는 이름과 하나 이상의 값이 있습니다. 속성에는 둘 이상의 유형 값이 있을 수 있으며, 두 개의 항목에 동일한 속성의 서로 다른 유형 값이 있을 수 있습니다. 속성은 색인 생성되거나 색인 생성되지 않을 수 있으며, 속성 P를 기준으로 정렬 또는 필터링하는 쿼리는 P가 색인 생성되지 않은 항목을 무시합니다. 항목 하나에 포함될 수 있는 색인 생성된 속성은 최대 20,000개입니다.
값 유형 | Python 유형 | 정렬 순서 | 참고 |
---|---|---|---|
정수 | int long |
숫자 | 부호 있는 64비트 정수 |
부동 소수점 수 | float |
숫자 | 64비트 배정밀도, IEEE 754 |
불리언 | bool |
False <True |
|
텍스트 문자열(short) | str unicode |
유니코드 ( str 은 ASCII로 취급됨) |
최대 1500바이트 |
텍스트 문자열(long) | db.Text |
없음 | 최대 1MB 색인 생성되지 않음 |
바이트 문자열(short) | db.ByteString |
바이트순 | 최대 1500바이트 |
바이트 문자열(long) | db.Blob |
없음 | 최대 1MB 색인 생성되지 않음 |
날짜 및 시간 | datetime.date datetime.time datetime.datetime |
시간순 | |
지리적 지점 | db.GeoPt |
위도순 우선 적용 후 경도순 |
|
우편 주소 | db.PostalAddress |
Unicode | |
전화번호 | db.PhoneNumber |
Unicode | |
이메일 주소 | db.Email |
Unicode | |
Google 계정 사용자 | users.User |
이메일 주소 (유니코드 순서) |
|
채팅 메시지 핸들 | db.IM |
Unicode | |
링크 | db.Link |
Unicode | |
카테고리 | db.Category |
Unicode | |
평점 | db.Rating |
숫자 | |
Datastore 키 | db.Key |
경로 요소 기준 (종류, 식별자, 종류, 식별자...) |
|
Blobstore 키 | blobstore.BlobKey |
바이트순 | |
Null | NoneType |
없음 |
중요: UserProperty
에는 이메일 주소와 사용자의 고유 ID가 포함되어 있으므로 이를 저장하지 않는 것이 좋습니다. 사용자가 자신의 이메일 주소를 변경하고 이전에 저장한 User
값과 새 User
값을 비교하면 서로 일치하지 않게 됩니다.
텍스트 문자열 및 인코딩되지 않은 바이너리 데이터(바이트 문자열)에 대해 Datastore는 두 가지 값 유형을 지원합니다.
- short 문자열(최대 1500바이트)은 색인이 생성되고 쿼리 필터 조건 및 정렬 순서에 사용될 수 있습니다.
- long 문자열(최대 1MB)은 색인이 생성되지 않으며 쿼리 필터 및 정렬 순서에 사용될 수 없습니다.
Blob
으로 지정되지만 이 유형은 Blobstore API에 사용되는 blob과는 관련이 없습니다.
쿼리에 혼합 유형 값이 있는 필드가 있으면 Datastore는 내부 표시를 기준으로 확정된 순서를 사용합니다.
- Null 값
- 고정 소수점 수
- 정수
- 날짜 및 시간
- 평점
- 부울 값
- 바이트 시퀀스
- 바이트 문자열
- 유니코드 문자열
- Blobstore 키
- 부동 소수점 수
- 지리적 지점
- Google 계정 사용자
- Datastore 키
long 텍스트 문자열 및 long 바이트 문자열은 색인이 생성되지 않기 때문에 순서가 정의되지 않습니다.
항목 작업
애플리케이션은 Datastore API를 사용하여 항목을 생성, 검색, 업데이트, 삭제할 수 있습니다. 애플리케이션이 항목의 전체 키를 알고 있거나 상위 키, 종류, 식별자에서 파생시킬 수 있는 경우 키를 사용하여 항목에서 직접 작동할 수 있습니다. 또한 애플리케이션은 Datastore 쿼리의 결과로 항목 키를 가져올 수 있습니다. 자세한 내용은 Datastore 쿼리 페이지를 참조하세요.
항목 생성
Python에서는 모델 클래스의 인스턴스를 생성하고, 필요에 따라 속성을 채우고, Datastore에 저장하도록 put()
메서드를 호출하여 새 항목을 만듭니다. 항목의 키 이름을 지정하려면 생성자에 key_name 인수를 전달하면 됩니다.
employee = Employee(key_name='asalieri',
first_name='Antonio',
last_name='Salieri')
employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True
employee.put()
키 이름을 제공하지 않으면 Datastore가 항목 키의 숫자 ID를 자동으로 생성합니다.
employee = Employee(first_name='Antonio',
last_name='Salieri')
employee.hire_date = datetime.datetime.now().date()
employee.attended_hr_training = True
employee.put()
항목 검색
특정 키로 식별되는 항목을 검색하려면 Key
객체를 db.get()
함수에 인수로 전달합니다. Key.from_path()
클래스 메서드를 사용하여 Key
객체를 생성할 수 있습니다.
전체 경로는 상위 경로에 있는 항목 시퀀스이며, 각 항목은 해당 종류(문자열)와 해당 식별자(키 이름 또는 숫자 ID)로 표시됩니다.
address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
address = db.get(address_k)
db.get()
은 해당 모델 클래스의 인스턴스를 반환합니다. 검색 중인 항목의 모델 클래스를 가져왔는지 확인하세요.
항목 업데이트
기존 항목을 업데이트하려면 객체의 속성을 수정한 다음 put()
메서드를 호출합니다. 이렇게 하면 객체 데이터가 기존 항목을 덮어씁니다. put()
을 호출할 때마다 전체 객체가 Datastore로 전송됩니다.
속성을 삭제하려면 Python 객체에서 속성을 삭제합니다.
del address.postal_code
그런 다음 객체를 저장합니다.
항목 삭제
항목의 키가 제공되면 db.delete()
함수를 사용하여 항목을 삭제할 수 있습니다.
address_k = db.Key.from_path('Employee', 'asalieri', 'Address', 1)
db.delete(address_k)
또는 항목의 자체 delete()
메서드를 호출하여 삭제할 수 있습니다.
employee_k = db.Key.from_path('Employee', 'asalieri')
employee = db.get(employee_k)
# ...
employee.delete()
일괄 작업
db.put()
, db.get()
, db.delete()
함수 및 비동기 함수 db.put_async()
, db.get_async()
, db.delete_async()
는 목록 인수를 수락하여 단일 Datastore 호출로 여러 항목에 작업을 수행할 수 있습니다.
# A batch put.
db.put([e1, e2, e3])
# A batch get.
entities = db.get([k1, k2, k3])
# A batch delete.
db.delete([k1, k2, k3])
일괄 작업을 수행해도 비용은 변하지 않습니다. 각 키가 있는지 여부와 관계없이 일괄 처리된 작업에서 모든 키에 요금이 부과됩니다. 작업과 관련된 항목 크기는 비용에 영향을 주지 않습니다.
대량 항목 삭제
다수의 항목을 삭제해야 하는 경우 Dataflow를 사용하여 항목을 일괄 삭제하는 것이 좋습니다.
빈 목록 사용
NDB 인터페이스에서 Datastore는 지금까지 정적 및 동적 속성 모두에 대해 빈 목록을 생략된 속성으로 작성했습니다. 하위 호환성 유지를 위해 이 동작은 계속 기본적으로 적용됩니다. 이를 전역으로 또는 ListProperty별 기준에 따라 재정의하려면 속성 클래스에서 write_empty_list 인수를true
로 설정합니다. 그러면 빈 목록이 Datastore에 작성되고 빈 목록으로 읽힐 수 있습니다.
DB 인터페이스의 경우 빈 목록 쓰기는 속성이 동적인 경우 지금까지 전혀 허용되지 않았으며, 이를 시도하면 오류가 발생했습니다. 즉, DB 동적 속성의 경우 하위 호환성을 위해 보존해야 할 기본 동작이 없습니다. 따라서 동적 모델에서는 특별한 변경사항 없이도 단순히 빈 목록을 쓰고 읽을 수 있습니다.
하지만 DB 정적 속성의 경우에는 빈 목록이 생략된 속성으로 작성되었습니다. 이 동작은 하위 호환성을 위해 계속 유지됩니다.
DB 정적 속성에 빈 목록을 설정하려면 속성 클래스에서 write_empty_list 인수를 true
로 사용합니다. 그러면 빈 목록이 Datastore에 작성됩니다.