Databend에서 JSON 설계 및 쿼리
최근 몇 년 동안 데이터 볼륨이 급격히 증가함에 따라 많은 플랫폼에서 반구조화된 데이터 유형(예: JSON)을 사용하고 최대한 활용하기 시작했습니다. 예를 들어 개방형 인터페이스를 통해 다양한 플랫폼에서 공유되는 JSON 데이터와 JSON 형식으로 저장된 공용 데이터 세트 및 애플리케이션 로그가 있습니다.
Databend는 구조화된 데이터 유형과 JSON을 지원합니다. 이 게시물은 Databend의 JSON 데이터 유형에 대해 자세히 설명합니다.
Databend에서 JSON 작업
Databend는 반구조화된 데이터를 VARIANT(JSON이라고도 함) 데이터 유형으로 저장합니다.
CREATE TABLE test
(
id INT32,
v1 VARIANT,
v2 JSON
);
JSON 데이터는 "parse_json"또는 "try_parse_json"함수를 호출하여 생성해야 합니다. 입력 문자열은 Null, Boolean, Number, String, Array 및 Object를 포함하는 표준 JSON 형식이어야 합니다. 유효하지 않은 문자열로 인해 구문 분석에 실패한 경우 "parse_json"함수는 오류를 반환하고 "try_parse_json"함수는 NULL 값을 반환합니다.
INSERT INTO test VALUES
(1, parse_json('{"a":{"b":1,"c":[1,2]}}'), parse_json('[["a","b"],{"k":"a"}]')),
(2, parse_json('{"a":{"b":2,"c":[3,4]}}'), parse_json('[["c","d"],{"k":"b"}]'));
SELECT * FROM test;
+----+-------------------------+-----------------------+
| id | v1 | v2 |
+----+-------------------------+-----------------------+
| 1 | {"a":{"b":1,"c":[1,2]}} | [["a","b"],{"k":"a"}] |
| 2 | {"a":{"b":2,"c":[3,4]}} | [["c","d"],{"k":"b"}] |
+----+-------------------------+-----------------------+
JSON은 일반적으로 배열 또는 객체 유형의 데이터를 보유합니다. 중첩된 계층 구조로 인해 JSON PATH를 통해 내부 요소에 액세스할 수 있습니다. 구문은 다음 구분 기호를 지원합니다.
":": 콜론은 키로 개체의 요소를 가져오는 데 사용할 수 있습니다.
".": 점을 사용하여 키로 개체의 요소를 가져올 수 있습니다. 문에서 첫 번째 구분 기호로 점을 사용하지 마십시오. 그렇지 않으면 Databend가 점을 구분 기호로 간주하여 테이블 이름과 열 이름을 구분합니다.
"[]": 대괄호를 사용하여 키로 개체의 요소를 가져오거나 인덱스로 배열의 요소를 가져올 수 있습니다.
위의 세 가지 유형의 구분 기호를 혼합할 수 있습니다.
SELECT v1:a.c, v1:a['b'], v1['a']:c, v2[0][1], v2[1].k FROM test;
+--------+-----------+-----------+----------+---------+
| v1:a.c | v1:a['b'] | v1['a']:c | v2[0][1] | v2[1].k |
+--------+-----------+-----------+----------+---------+
| [1,2] | 1 | [1,2] | "b" | "a" |
| [3,4] | 2 | [3,4] | "d" | "b" |
+--------+-----------+-----------+----------+---------+
JSON PATH를 통해 추출된 내부 요소도 JSON 타입이며, 변환 연산자 “::”를 사용하거나 cast 함수를 통해 기본 타입으로 변환할 수 있습니다.
SELECT cast(v1:a.c[0], int64), v1:a.b::int32, v2[0][1]::string FROM test;
+--------------------------+---------------+------------------+
| cast(v1:a.c[0] as int64) | v1:a.b::int32 | v2[0][1]::string |
+--------------------------+---------------+------------------+
| 1 | 1 | b |
| 3 | 2 | d |
+--------------------------+---------------+------------------+
GitHub에서 JSON 파싱
많은 공개 데이터 세트는 JSON 형식으로 저장됩니다. 구문 분석을 위해 이러한 데이터를 Databend로 가져올 수 있습니다. 다음 소개에서는 GitHub 이벤트 데이터 세트를 예로 사용합니다.
GitHub 이벤트 데이터 세트(GH 아카이브에서 다운로드)는 다음 JSON 형식을 사용합니다.
{
"id":"23929425917",
"type":"PushEvent",
"actor":{
"id":109853386,
"login":"teeckyar-bot",
"display_login":"teeckyar-bot",
"gravatar_id":"",
"url":"https://api.github.com/users/teeckyar-bot",
"avatar_url":"https://avatars.githubusercontent.com/u/109853386?"
},
"repo":{
"id":531248561,
"name":"teeckyar/Times",
"url":"https://api.github.com/repos/teeckyar/Times"
},
"payload":{
"push_id":10982315959,
"size":1,
"distinct_size":1,
"ref":"refs/heads/main",
"head":"670e7ca4085e5faa75c8856ece0f362e56f55f09",
"before":"0a2871cb7e61ce47a6790adaf09facb6e1ef56ba",
"commits":[
{
"sha":"670e7ca4085e5faa75c8856ece0f362e56f55f09",
"author":{
"email":"[email protected]",
"name":"teeckyar-bot"
},
"message":"1662804002 Timehash!",
"distinct":true,
"url":"https://api.github.com/repos/teeckyar/Times/commits/670e7ca4085e5faa75c8856ece0f362e56f55f09"
}
]
},
"public":true,
"created_at":"2022-09-10T10:00:00Z",
"org":{
"id":106163581,
"login":"teeckyar",
"gravatar_id":"",
"url":"https://api.github.com/orgs/teeckyar",
"avatar_url":"https://avatars.githubusercontent.com/u/106163581?"
}
}
위의 데이터에서 "actor", "repo", "payload"및 "org"필드가 중첩된 구조를 가지며 JSON으로 저장될 수 있음을 알 수 있습니다. 다른 유형은 기본 데이터 유형으로 저장할 수 있습니다. 따라서 다음과 같은 테이블을 만들 수 있습니다.
CREATE TABLE `github_data`
(
`id` VARCHAR,
`type` VARCHAR,
`actor` JSON,
`repo` JSON,
`payload` JSON,
`public` BOOLEAN,
`created_at` timestamp(0),
`org` json
);
COPY INTO 명령을 사용하여 데이터를 로드합니다.
COPY INTO github_data
FROM 'https://data.gharchive.org/2022-09-10-10.json.gz'
FILE_FORMAT = (
compression = auto
type = NDJSON
);
다음 코드는 커밋이 가장 많은 상위 10개 프로젝트를 반환합니다.
SELECT repo:name,
count(id)
FROM github_data
WHERE type = 'PushEvent'
GROUP BY repo:name
ORDER BY count(id) DESC
LIMIT 10;
+----------------------------------------------------------+-----------+
| repo:name | count(id) |
+----------------------------------------------------------+-----------+
| "Lombiq/Orchard" | 1384 |
| "maique/microdotblog" | 970 |
| "Vladikasik/statistic" | 738 |
| "brokjad/got_config" | 592 |
| "yanonono/booth-update" | 537 |
| "networkoperator/demo-cluster-manifests" | 433 |
| "kn469/web-clipper-bed" | 312 |
| "ufapg/jojo" | 306 |
| "bj5nj7oh/bj5nj7oh" | 291 |
| "appseed-projects2/500f32d3-8019-43ee-8f2a-a273163233fb" | 247 |
+----------------------------------------------------------+-----------+
다음 코드는 포크가 가장 많은 상위 10명의 사용자를 반환합니다.
SELECT actor:login,
count(id)
FROM github_data
WHERE type='ForkEvent'
GROUP BY actor:login
ORDER BY count(id) DESC
LIMIT 10;
+-----------------------------------+-----------+
| actor:login | count(id) |
+-----------------------------------+-----------+
| "actions-marketplace-validations" | 191 |
| "alveraboquet" | 59 |
| "ajunlonglive" | 50 |
| "Shutch420" | 13 |
| "JusticeNX" | 13 |
| "RyK-eR" | 12 |
| "DroneMad" | 10 |
| "UnqulifiedEngineer" | 9 |
| "PeterZs" | 8 |
| "lgq2015" | 8 |
+-----------------------------------+-----------+
성능 최적화
JSON 데이터는 일반적으로 일반 텍스트 형식으로 저장되며 데이터를 읽을 때마다 serde_json::Value의 열거형 값을 생성하기 위해 구문 분석해야 합니다. 다른 기본 데이터 유형과 비교할 때 JSON 데이터를 처리하는 데 더 많은 구문 분석 시간이 걸리고 더 많은 메모리 공간이 필요합니다.
Databend는 다음 방법을 사용하여 JSON 데이터의 읽기 성능을 개선했습니다.
CREATE TABLE test
(
id INT32,
v1 VARIANT,
v2 JSON
);
INSERT INTO test VALUES
(1, parse_json('{"a":{"b":1,"c":[1,2]}}'), parse_json('[["a","b"],{"k":"a"}]')),
(2, parse_json('{"a":{"b":2,"c":[3,4]}}'), parse_json('[["c","d"],{"k":"b"}]'));
SELECT * FROM test;
+----+-------------------------+-----------------------+
| id | v1 | v2 |
+----+-------------------------+-----------------------+
| 1 | {"a":{"b":1,"c":[1,2]}} | [["a","b"],{"k":"a"}] |
| 2 | {"a":{"b":2,"c":[3,4]}} | [["c","d"],{"k":"b"}] |
+----+-------------------------+-----------------------+
SELECT v1:a.c, v1:a['b'], v1['a']:c, v2[0][1], v2[1].k FROM test;
+--------+-----------+-----------+----------+---------+
| v1:a.c | v1:a['b'] | v1['a']:c | v2[0][1] | v2[1].k |
+--------+-----------+-----------+----------+---------+
| [1,2] | 1 | [1,2] | "b" | "a" |
| [3,4] | 2 | [3,4] | "d" | "b" |
+--------+-----------+-----------+----------+---------+
SELECT cast(v1:a.c[0], int64), v1:a.b::int32, v2[0][1]::string FROM test;
+--------------------------+---------------+------------------+
| cast(v1:a.c[0] as int64) | v1:a.b::int32 | v2[0][1]::string |
+--------------------------+---------------+------------------+
| 1 | 1 | b |
| 3 | 2 | d |
+--------------------------+---------------+------------------+
많은 공개 데이터 세트는 JSON 형식으로 저장됩니다. 구문 분석을 위해 이러한 데이터를 Databend로 가져올 수 있습니다. 다음 소개에서는 GitHub 이벤트 데이터 세트를 예로 사용합니다.
GitHub 이벤트 데이터 세트(GH 아카이브에서 다운로드)는 다음 JSON 형식을 사용합니다.
{
"id":"23929425917",
"type":"PushEvent",
"actor":{
"id":109853386,
"login":"teeckyar-bot",
"display_login":"teeckyar-bot",
"gravatar_id":"",
"url":"https://api.github.com/users/teeckyar-bot",
"avatar_url":"https://avatars.githubusercontent.com/u/109853386?"
},
"repo":{
"id":531248561,
"name":"teeckyar/Times",
"url":"https://api.github.com/repos/teeckyar/Times"
},
"payload":{
"push_id":10982315959,
"size":1,
"distinct_size":1,
"ref":"refs/heads/main",
"head":"670e7ca4085e5faa75c8856ece0f362e56f55f09",
"before":"0a2871cb7e61ce47a6790adaf09facb6e1ef56ba",
"commits":[
{
"sha":"670e7ca4085e5faa75c8856ece0f362e56f55f09",
"author":{
"email":"[email protected]",
"name":"teeckyar-bot"
},
"message":"1662804002 Timehash!",
"distinct":true,
"url":"https://api.github.com/repos/teeckyar/Times/commits/670e7ca4085e5faa75c8856ece0f362e56f55f09"
}
]
},
"public":true,
"created_at":"2022-09-10T10:00:00Z",
"org":{
"id":106163581,
"login":"teeckyar",
"gravatar_id":"",
"url":"https://api.github.com/orgs/teeckyar",
"avatar_url":"https://avatars.githubusercontent.com/u/106163581?"
}
}
위의 데이터에서 "actor", "repo", "payload"및 "org"필드가 중첩된 구조를 가지며 JSON으로 저장될 수 있음을 알 수 있습니다. 다른 유형은 기본 데이터 유형으로 저장할 수 있습니다. 따라서 다음과 같은 테이블을 만들 수 있습니다.
CREATE TABLE `github_data`
(
`id` VARCHAR,
`type` VARCHAR,
`actor` JSON,
`repo` JSON,
`payload` JSON,
`public` BOOLEAN,
`created_at` timestamp(0),
`org` json
);
COPY INTO 명령을 사용하여 데이터를 로드합니다.
COPY INTO github_data
FROM 'https://data.gharchive.org/2022-09-10-10.json.gz'
FILE_FORMAT = (
compression = auto
type = NDJSON
);
다음 코드는 커밋이 가장 많은 상위 10개 프로젝트를 반환합니다.
SELECT repo:name,
count(id)
FROM github_data
WHERE type = 'PushEvent'
GROUP BY repo:name
ORDER BY count(id) DESC
LIMIT 10;
+----------------------------------------------------------+-----------+
| repo:name | count(id) |
+----------------------------------------------------------+-----------+
| "Lombiq/Orchard" | 1384 |
| "maique/microdotblog" | 970 |
| "Vladikasik/statistic" | 738 |
| "brokjad/got_config" | 592 |
| "yanonono/booth-update" | 537 |
| "networkoperator/demo-cluster-manifests" | 433 |
| "kn469/web-clipper-bed" | 312 |
| "ufapg/jojo" | 306 |
| "bj5nj7oh/bj5nj7oh" | 291 |
| "appseed-projects2/500f32d3-8019-43ee-8f2a-a273163233fb" | 247 |
+----------------------------------------------------------+-----------+
다음 코드는 포크가 가장 많은 상위 10명의 사용자를 반환합니다.
SELECT actor:login,
count(id)
FROM github_data
WHERE type='ForkEvent'
GROUP BY actor:login
ORDER BY count(id) DESC
LIMIT 10;
+-----------------------------------+-----------+
| actor:login | count(id) |
+-----------------------------------+-----------+
| "actions-marketplace-validations" | 191 |
| "alveraboquet" | 59 |
| "ajunlonglive" | 50 |
| "Shutch420" | 13 |
| "JusticeNX" | 13 |
| "RyK-eR" | 12 |
| "DroneMad" | 10 |
| "UnqulifiedEngineer" | 9 |
| "PeterZs" | 8 |
| "lgq2015" | 8 |
+-----------------------------------+-----------+
성능 최적화
JSON 데이터는 일반적으로 일반 텍스트 형식으로 저장되며 데이터를 읽을 때마다 serde_json::Value의 열거형 값을 생성하기 위해 구문 분석해야 합니다. 다른 기본 데이터 유형과 비교할 때 JSON 데이터를 처리하는 데 더 많은 구문 분석 시간이 걸리고 더 많은 메모리 공간이 필요합니다.
Databend는 다음 방법을 사용하여 JSON 데이터의 읽기 성능을 개선했습니다.
Reference
이 문제에 관하여(Databend에서 JSON 설계 및 쿼리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/databend/designing-and-querying-json-in-databend-1j07텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)