상태 데이터베이스 질의

이 항목에는 블록체인 원장의 현재 상태 데이터가 저장되는 시/도 데이터베이스를 쿼리하는 방법을 이해하는 데 도움이 되는 정보가 포함되어 있습니다.

State Database란?

블록체인 원장의 현재 상태 데이터는 주 데이터베이스에 저장됩니다.

Oracle Blockchain Platform 체인코드를 개발할 때 리치 쿼리를 실행하여 상태 데이터베이스에서 데이터를 추출할 수 있습니다. Oracle Blockchain Platform은 SQL 리치 쿼리 구문과 CouchDB 찾기 표현식을 사용하여 리치 쿼리를 지원합니다. SQL 서식 있는 질의 구문CouchDB 서식 있는 질의 구문을 참조하십시오.

Hyperledger Fabric은 SQL 리치 쿼리를 지원하지 않습니다. Oracle Blockchain Platform 네트워크에 Hyperledger Fabric 참가자가 포함된 경우 다음을 수행해야 합니다.

  • 체인코드에 SQL 서식 있는 질의 구문이 포함된 경우 해당 체인코드는 Oracle Blockchain Platform을 사용하는 멤버 피어에만 설치됩니다.

  • 체인코드를 Oracle Blockchain Platform 및 Hyperledger Fabric 피어에 설치해야 하는 경우 체인코드에서 CouchDB 구문을 사용하고 Hyperledger Fabric 피어가 CouchDB을 상태 데이터베이스 저장소로 사용하도록 설정되었는지 확인합니다. Oracle Blockchain Platform은 CouchDB를 처리할 수 있습니다.

Oracle Blockchain Platform은 Berkeley DB에서 어떻게 작동합니까?

Oracle Blockchain Platform은 Oracle Berkeley DB를 상태 데이터베이스로 사용합니다. Oracle Blockchain Platform은 SQLite 확장을 기반으로 Berkeley DB에 관계형 테이블을 생성합니다. 이 구조는 SQL 리치 query를 검증할 수 있는 강력하고 성능이 뛰어난 방법을 제공합니다.

각 채널 체인 코드에 대해 Oracle Blockchain Platform에서 Berkeley DB 테이블을 생성합니다. 이 테이블은 상태 정보 데이터를 저장하며, JSON 형식 데이터를 사용 중인지 여부에 따라 이름이 key인 키 열과 이름이 value 또는 valueJson인 값 열을 포함합니다.

열 이름 유형 설명
key TEXT 상태 테이블의 키 열입니다.
value TEXT 상태 테이블의 값 열입니다.
valueJson TEXT 상태 테이블의 JSON 형식 값 열입니다.

valueJson 열과 value 열은 상호 배타적입니다. 따라서 체인코드가 키에 JSON 값을 지정할 경우 valueJson 열은 해당 값을 보유하며 값 열은 널로 설정됩니다. 체인코드가 비JSON 값을 키에 지정할 경우 valueJson 열이 널로 설정되고 값 열에 값이 포함됩니다.

상태 데이터베이스의 예

다음은 자동차 딜러 샘플 상태 데이터베이스의 키 및 해당 값의 예입니다.

value valueJson
abg1234 {"docType": "vehiclePart", "serialNumber": "abg1234", "어셈블러": "파나마 부품", "assemblyDate": 1502688979, "이름": "에어백 2020", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}
abg1235 {"docType": "vehiclePart", "serialNumber": "abg1235", "어셈블러": "파나마 부품", "assemblyDate": 1502688979, "이름": "에어백 4050", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}
ser1236 {"docType": "vehiclePart", "serialNumber": "ser1236", "어셈블러": "파나마 부분", "assemblyDate": 1502688979, "이름": "좌석 벨트 10020", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}
bra1238 {"docType": "vehiclePart", "serialNumber": "bra1238", "어셈블러": "관찰 비트", "assemblyDate": 1502688979, "이름": "브레이크패드 4200", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}
dtrt10001 {"docType": "차량", "chassisNumber": "dtrt10001", "제조업자": "Detroit Auto", "model": "a coupe", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "owner": "Sam Dealer", "recall": false, "recallDate": 1502688979

콘솔의 서식 있는 질의

관리자는 콘솔에서 다양한 쿼리를 실행하고 분석할 수 있습니다.

  1. 콘솔로 이동하여 Channels(채널) 탭을 선택합니다.
  2. 채널 테이블에서 질의를 실행할 채널을 찾고 채널 작업 더 보기 단추를 누른 다음 서식 있는 질의 분석을 누릅니다. 서식 있는 질의 분석 대화상자가 표시됩니다.
  3. 상태 데이터베이스에 대해 서식 있는 질의를 실행하려면 질의 실행을 선택합니다.
    1. 체인코드의 경우 질의할 채널에 배포된 체인코드를 선택합니다.
    2. 피어의 경우 질의할 피어를 선택합니다.
      선택한 체인 코드를 실행 중인 현재 조직의 피어만 사용할 수 있습니다.
    3. 서식 있는 질의의 경우 실행 및 분석할 서식 있는 질의를 입력합니다.
      조회 형식은 서식 있는 조회 구문을 따라야 합니다. 서식 있는 질의 구문에 대한 자세한 내용은 지원되는 서식 있는 질의 구문을 참조하십시오.
    4. 결과 행 제한의 경우 가져올 최대 결과 행 수로 슬라이더를 이동합니다. 최대 50개 행의 결과를 인출할 수 있습니다.
  4. 질의에 대한 실행 계획을 가져오려면 질의 계획 설명을 선택합니다. 질의 실행 계획은 질의를 실행하기 위해 수행된 일련의 작업입니다.
    1. 체인코드의 경우 질의할 채널에 배포된 체인코드를 선택합니다.
    2. 피어의 경우 질의할 피어를 선택합니다.
    3. 모음의 경우 상태 데이터베이스 또는 프라이빗 데이터 수집을 선택합니다.
    4. 서식 있는 질의에 서식 있는 질의를 입력합니다.
      이 질의에는 explain 키워드가 필요하지 않습니다.
      예: select * from <state>
  5. 실행을 누릅니다. 결과 필드에는 질의 결과 테이블 또는 실행 계획이 표시됩니다. 결과 테이블을 .csv 파일로 익스포트하려면 익스포트를 누릅니다.
    결과 테이블 크기는 1MB로 제한됩니다. 이 제한을 초과하지 않도록 질의를 세분화해야 할 수 있습니다.

지원되는 Rich Query 구문

Oracle Blockchain Platform은 상태 데이터베이스를 쿼리하는 데 사용할 수 있는 두 가지 유형의 리치 쿼리 구문(SQL 리치 쿼리 및 CouchDB 리치 쿼리)을 지원합니다.

SQL 서식 있는 질의 구문

Berkeley DB JSON 확장은 SQL 함수의 형식입니다.

시작하기 전에

다음 정보에 유의하십시오.

  • 질의를 실행 중인 채널 체인 코드(<STATE>)에만 액세스할 수 있습니다.
  • SELECT 문만 지원됩니다.
  • 상태 데이터베이스 테이블을 수정할 수 없습니다.
  • 서식 있는 질의 표현식은 하나의 SELECT 문만 가질 수 있습니다.
  • 이 항목의 예제는 서식 있는 질의를 작성할 수 있는 몇 가지 방법일 뿐입니다. SQL 데이터베이스를 질의하기 위한 일반적인 전체 SQL 구문에 액세스할 수 있습니다.
  • JSON1 확장(SQLite 확장)에 액세스할 수 있습니다. JSON1 ExtensionSQL As Understood by SQLite를 참조하십시오.

체인코드 작성 및 테스트에 대한 자세한 내용은 체인코드 개발을 참조하십시오.

질의에서 상태 데이터베이스를 참조하는 방법

상태 데이터베이스 테이블 이름은 Oracle Blockchain Platform에서 내부적으로 관리되므로 체인코드를 작성할 때 상태 데이터베이스의 물리적 이름을 알 필요가 없습니다.

대신 <STATE> 별칭을 사용하여 테이블 이름을 참조해야 합니다. 예: select key, value from <STATE>.

<STATE> 별칭은 대소문자를 구분하지 않으므로 <state>, <STATE> 또는 <StAtE>와 같은 이름을 사용할 수 있습니다.

모든 키 검색

다음 구문을 사용합니다.

SELECT key FROM <STATE>

예를 들어, 이 구문을 사용하여 자동차 딜러 샘플을 쿼리하면 다음과 같은 키 목록이 표시됩니다.

abg1234

abg1235

ser1236

bra1238

dtrt10001

키별로 알파벳순으로 정렬된 모든 키 및 값 검색

다음 구문을 사용합니다.

SELECT key AS serialNumber, valueJson AS details FROM  <state> ORDER BY key

예를 들어, 이 구문을 사용하여 자동차 딜러 샘플을 쿼리하면 다음과 같은 결과가 나타납니다.

serialNumber 세부정보
abg1234 {"docType": "vehiclePart", "serialNumber": "abg1234", "어셈블러": "파나마 부품", "assemblyDate": 1502688979, "이름": "에어백 2020", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}
abg1235 {"docType": "vehiclePart", "serialNumber": "abg1235", "어셈블러": "파나마 부품", "assemblyDate": 1502688979, "이름": "에어백 4050", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}
bra1238 {"docType": "vehiclePart", "serialNumber": "bra1238", "어셈블러": "관찰 비트", "assemblyDate": 1502688979, "이름": "브레이크패드 4200", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}
dtrt10001 {"docType": "차량", "chassisNumber": "dtrt10001", "제조업자": "Detroit Auto", "model": "a coupe", "assemblyDate": 1502688979, "airbagSerialNumber": "abg1235", "owner": "Sam Dealer", "recall": false, "recallDate": 1502688979
ser1236 {"docType": "vehiclePart", "serialNumber": "ser1236", "어셈블러": "파나마 부분", "assemblyDate": 1502688979, "이름": "좌석 벨트 10020", "소유자": "Detroit Auto", "recall": false, "recallDate": 1502688979}

"abg"로 시작하는 모든 키 및 값 검색

다음 구문을 사용합니다.

SELECT key AS serialNumber, valueJson AS details FROM <state> WHERE key LIKE 'abg%'SELECT key, value FROM <STATE>

예를 들어, 이 구문을 사용하여 자동차 딜러 샘플을 쿼리하면 다음과 같은 결과가 나타납니다.

serialNumber 세부정보
abg1234 {"docType": "vehiclePart", "serialNumber": "abg1234", "어셈블러": "파나마 부품", "assemblyDate": "1502688979", "이름": "에어백 2020", "소유자": "Detroit Auto", "회수": "거짓", "recallDate": "1502688979"}
abg1235 {"docType": "vehiclePart", "serialNumber": "abg1235", "어셈블러": "파나마 부품", "assemblyDate": "1502688979", "이름": "에어백 4050", "소유자": "Detroit Auto", "회수": "거짓", "recallDate": "1502688979"}

"Detroit Auto"에서 소유한 차량 부품이 포함된 값이 있는 모든 키 검색

다음 구문을 사용합니다.

SELECT key FROM <state> WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'

예를 들어, 이 구문을 사용하여 자동차 딜러 샘플을 쿼리하면 다음과 같은 키 목록이 표시됩니다.

abg1234

abg1235

ser1236

bra1238

"Sam Dealer"가 소유한 모든 자동차에 대한 모델 및 제조업체 검색

다음 구문을 사용합니다.

SELECT json_extract(valueJson, '$.model') AS model, json_extract(valueJson, '$.manufacturer') AS manufacturer FROM <state> WHERE json_extract(valueJson, '$.docType') = 'vehicle' AND json_extract(valueJson, '$.owner') = 'Sam Dealer'

예를 들어, 이 구문을 사용하여 자동차 딜러 샘플을 쿼리하면 다음과 같은 결과가 나타납니다.

모델 제조업체
쿠페 디트로이트 오토

상태 값이 JSON 배열인 경우 이 구문을 사용하여 "Sam Dealer"가 소유한 모든 자동차에 대한 모델 및 제조업체를 검색할 수 있습니다.

SELECT json_extract(j.value, '$.model') AS model, json_extract(j.value, '$.manufacturer') AS manufacturer FROM <state> s, json_each(json_extract(s.valueJson,'$')) j WHERE json_valid(j.value) AND json_extract(j.value, '$.owner') = 'Sam Dealer'

CouchDB 서식 있는 질의 구문

CouchDB 구문이 포함된 체인코드를 Oracle Blockchain Platform으로 마이그레이션하거나 Oracle Blockchain Platform 네트워크에 참여하는 Hyperledger Fabric 피어에 설치할 체인코드를 작성해야 하는 경우 이 항목의 정보를 사용합니다.

새 체인코드를 작성하는 경우 Oracle은 SQL 리치 쿼리를 사용하여 Berkeley DB가 제공하는 Oracle Blockchain Platform의 성능 이점을 활용할 것을 권장합니다.

체인코드 작성 및 테스트에 대한 자세한 내용은 체인코드 개발을 참조하십시오.

지원되지 않는 질의 매개변수 및 선택기 구문

Oracle Blockchain Platformuse_index 매개변수를 지원하지 않습니다. 사용되는 경우 Oracle Blockchain Platform은 이 매개변수를 무시하고 해당 StateDB에 정의된 인덱스를 자동으로 선택합니다.

매개변수 유형 설명
use_index json 특정 인덱스를 사용하도록 query에 지시합니다.

소유자별로 모든 모델, 제조업자 및 자동차 소유자 검색 및 주문

다음 식을 사용합니다.

{ 
  "fields": ["model", "manufacturer", "owner"], 
  "sort": [   
    "owner" 
   ]
}

"Sam Dealer"가 소유한 모든 자동차에 대한 모델 및 제조업체 검색

다음 식을 사용합니다.

{ 
  "fields": ["model", "manufacturer"], 
  "selector": {   
    "docType"  : "vehicle",
     "owner" : "Sam Dealer" 
  }
}

상태 데이터베이스 인덱스

상태 데이터베이스에는 많은 양의 데이터가 포함될 수 있습니다. 이 경우 Oracle Blockchain Platform은 인덱스를 사용하여 데이터 액세스를 개선합니다.

기본 인덱스

체인코드가 배포되면 Oracle Blockchain Platform에서 두 개의 인덱스를 생성합니다.

  • 키 인덱스 — 키 열에 생성됩니다.

  • 값 인덱스 — 값 열에 생성됩니다.

사용자정의 인덱스

경우에 따라 사용자 정의 인덱스를 생성해야 할 수도 있습니다. 이러한 인덱스는 상태 테이블의 컨텍스트에서 분석할 수 있는 표현식을 사용하여 정의합니다. Berkeley DB에 대해 생성된 사용자 정의 인덱스는 SQLite 구문을 사용하지만, 그렇지 않으면 Hyperledger Fabric에서 제공하는 것과 동일한 CouchDB 구현을 따릅니다.

커스텀 인덱스를 사용하여 대용량 데이터 집합에서 WHERE 및 ORDER BY 문의 성능을 크게 향상시킬 수 있습니다. 사용자 정의 인덱스를 사용하면 데이터 삽입 속도가 느려지므로 신중하게 사용해야 합니다.

각 커스텀 인덱스는 하나의 파일 내에 JSON 문서로 표현되는 복합 인덱스를 지원하는 표현식 배열로 정의됩니다(파일당 하나의 인덱스가 있음). statedb/relationaldb/indexes 디렉토리 구조의 "indexes" 폴더에 체인 코드를 사용하여 이 파일을 패키지화해야 합니다. 체인 코드 설치 중 CouchDB 인덱스를 추가하는 방법을 참조하십시오.

사용자정의 인덱스 예

이 섹션의 사용자 지정 색인 예에서는 자동차 딜러 샘플을 사용합니다.

예 1 —이 예제는 WHERE 및 ORDER BY 표현식의 컨텍스트에서 json_extract 표현식 사용을 인덱스화합니다.

{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}

예:

SELECT … FROM … ORDER BY json_extract(valueJson, '$.owner')

예 2 — 이 예제는 WHERE 및 ORDER BY 표현식의 컨텍스트에서 두 json_extract 표현식의 복합 사용을 인덱스화합니다.

{"indexExpressions": ["json_extract(valueJson, '$.docType')", "json_extract(valueJson, '$.owner')"]}

예:

SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto'

예 3 — 이 예에서는 Example 1에 설명된 인덱스와 Example 2에 설명된 인덱스의 두 인덱스를 만듭니다. 각 JSON 구조는 별도의 파일에 포함되어야 합니다. 각 파일은 단일 인덱스(예제 1과 같은 단순 인덱스 또는 예 2와 같은 복합 인덱스)를 설명합니다.

인덱스 1: {"indexExpressions": ["json_extract(valueJson, '$.owner')"]}

인덱스 2: {"indexExpressions": ["json_extract(valueJson, '$owner')", "json_extract(valueJson, '$.docType')"]}

다음 예에서는 인덱스 2가 질의의 WHERE 부분에 있는 AND 표현식에 적용되고 인덱스 1이 ORDER BY 표현식에 적용됩니다.

SELECT … FROM … WHERE json_extract(valueJson, '$.docType') = 'vehiclePart' AND json_extract(valueJson, '$.owner') = 'Detroit Auto' ORDER BY json_extract(valueJson, '$.owner')

JSON 문서 형식

JSON 문서는 다음 형식이어야 합니다.

{"indexExpressions": [expr1, ..., exprN]}

예:

{"indexExpressions": ["json_extract(valueJson, '$.owner')"]}

Rich Query의 검증 차이점

경우에 따라 CouchDB 리치 쿼리를 사용하는 표준 Hyperledger Fabric과 Oracle Berkeley DB 리치 쿼리가 다르게 동작합니다.

CouchDB가 있는 표준 Hyperledger Fabric에서 쿼리에서 반환된 각 키 및 값 쌍은 트랜잭션의 읽기 세트에 추가되며 쿼리를 재실행하지 않고 검증 시 검증됩니다. Berkeley DB에서 반환된 키 및 값 쌍은 읽기 세트에 추가되지 않지만 서식 있는 질의의 결과는 Merkle 트리에서 해시되고 검증 시 질의 재실행에 대해 검증됩니다.

네이티브 Hyperledger Fabric은 리치 쿼리에 대한 데이터 보호를 제공하지 않습니다. 그러나 Berkeley DB에는 읽기 세트에 Merkle 트리 해시 값을 추가하고, 서식 있는 쿼리를 다시 실행하고, 검증 단계에서 Merkle 트리 값을 다시 계산하여 서식 있는 쿼리를 보호하고 검증하는 기능이 포함되어 있습니다. Berkeley DB를 사용하는 Oracle Blockchain Platform에서 검증이 더 정확하기 때문에 체인코드 호출에 더 빈번한 팬텀 읽기가 표시되기도 합니다.