jisoo_lee@cloudshell:~$ git clone https://github.com/onlybooks/bigquery # 다운로드
# Cloning into 'bigquery'...remote: Enumerating objects: 986, done.remote: Counting objects: 100% (986/986), done.remote: Compressing objects: 100% (731/731), done.remote: Total 986 (delta 282), reused 915 (delta 217), pack-reused 0Receiving objects: 100% (986/986), 18.48 MiB | 10.20 MiB/s, done.Resolving deltas: 100% (282/282), done.
jisoo_lee@cloudshell:~$ cd bigquery
jisoo_lee@cloudshell:~/bigquery$ ls
# appendix bigquery_cover.jpg blogs ch01 ch02 ch03 ch04 ch05 ch06 ch07 ch08 ch09 ch10 README.md set_env.md
jisoo_lee@cloudshell:~/bigquery$ cd ..
jisoo_lee@cloudshell:~$ cd bigquery/ch04
jisoo_lee@cloudshell:~/bigquery/ch04$ zless college_scorecard.csv.gz
# 압축파일 내용 확인 > space로 내용 확인 > q로 Fin.
bq --location=US mk ch04
# 데이터셋 위치 US로 지정(default 값이 US)
# 특정 region만 선택해서 생성 가능함 us-east4
bq
: BigQuery 서비스를 사용하기 위한 명령들 제공 > bq 명령으로 행할 수 있는 작업들은 REST API 혹은 GCP 클라우드 콘솔로도 가능함
DataSet
- 테이블, 뷰, 머신러닝 모델 등을 정리 및 접근성을 제어하기 위한 Top 폴더처럼 작동
- 현재 프로젝트에 생성되며, 데이터셋 내 테이블에 대한 스토리지 비용은 프로젝트에 청구됨
- Region이 다른 테이블 간 join은 불가
bq --location=US \
load --null_marker=NULL --replace \
--source_format=CSV --autodetect \
ch04.college_scorecard \
./college_scorecard.csv.gz
# 원본이 CSV형식 + 스키마를 자동으로 탐색(컬럼별 데이터 형식)
# college_scorecard 테이블을 ch04 데이터셋 안에 생성하고,
# 데이터는 현재 디렉토리의 college_scorecard.csv.gz 파일에서 찾아라
Question.
load --null_marker=NULL --replace \ --source_format=CSV --autodetect \ ch04.college_scorecard \ ./college_scorecard.csv.gz
이건 되고
왜 \없이 일자로 쭉 나열한건 안되지???
문제는 테이블 안에 NULL값이 존재할 경우 테이블 생성이 불가능함, 해결방법은 아래와 같음
1) 각 칼럼의 스키마를 직접 명시, Null 값 허용하도록 컬럼 타입을 문자열로 변경
2) --max_bad_records=20
과 같은 파라미터를 이용해 문제있는 레코드는 pass 설정
3) 로드 프로그램에게 특정 파일은 null값을 문자열 NULL로 표현하고 있다고 인지[Best Option]
본래 CSV 파일의 NULL 값은 빈칸으로 세팅함
주의사항 : Project에 해당하는 terminal에서 데이터를 로드해야 함
ALTER TABLE SET OPTIONS
으로 테이블 만료일 지정할 수 있음 압축된 파일에서 특정 문자열을 NULL로 바꾸는 명령
zless ./college_scorecard.csv.gz | \ sed 's/PrivacySuppressed/NULL/g' | \ gzip > /tmp/college_scorecard.csv.gz
-문자열 편집기
sed
를 이용하여 PrivacySuppressed 문자열을 NULL로 변환
bq show --format prettyjson --schema ch04.college_scorecard
# Schema 파일로 저장
bq show --format prettyjson --schema ch04.college_scorecard > schema.json
<dataset>.INFORMATION_SCHEMA
를 이용하여 All Table의 Schema를 얻음INFORMATION_SCHEMA
로 데이터셋의 메타데이터들을 확인할 수 있음TO_JSON_STRING
을 사용하면 스키마 정보를 JSON 형식으로 변환함SELECT
TO_JSON_STRING(
ARRAY_AGG(STRUCT(
IF(is_nullable = 'YES', 'NULLABLE', 'REQUIRED') AS mode,
column_name AS name,
data_type AS type)
ORDER BY ordinal_position), TRUE) AS schema
텍스트 편집기(ex. cloud shell의 pen 아이콘 > 기본 편집기)를 열어 필요에 따라 컬럼의 타입 변경
Question
이거 정확히 어디에서 진행하는지 확인하기 > 그리고 다른 텍스트 편집기 어떻게 쓰는지 확인하기
수정 후 데이터 로드 시 스키마 파일도 함께 지정해주기
load --null_marker=NULL --replace \
--source_format=CSV \
--schema=schema.json --skip_leading_rows = 1
ch04.college_scorecard \
./college_scorecard.csv.gz
SAFE_CAST
를 하나 하나 지정할 필요 없음 CREATE TABLE
이용CREATE OR REPLACE TABLE ch04.college_scorecard_etl AS
SELECT 블라블라
FROM ch04.college_scorecard
bq rm <dataset>.<table> # 하나 table 제거
bq rm -r -f <dataset> # -r : 재귀적으로 -f : 경고 없이 dataset 안의 모든 table 삭제
bq rm -r <folder> # folder 삭제시 -r 필수적
DROP TABLE IF EXISTS <dataset>.<table>
ALTER TABLE SET OPTION
ALTER TABLE <dataset>.<table>
SET OPTIONS(
expiration_timestamp = TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 7 DAYS),
description = "블라블라"
)
DELETE FROM <dataset>.<table>
WHERE <row> IS NULL
CREATE TABLE
,ALTER TABLE
,DROP TABLE
> 이런 애들은 DDL(Data Definition Language) 데이터 정의 언어
INSERT <dataset>.<table>
(원래있던 컬럼 이름들,
블라블라)
VALUES(각 컬럼에 들어갈 데이터들),
(각 컬럼에 들어갈 데이터들)
INSERT <dataset>.<table>
SELECT *
FROM <dataset><table2>
WHERE col_a IS NULL
DELETE
,INSERT
,MERGE
> DML(Data Manipulation Language) 데이터 조작 언어
bq cp
_ -a
| --append_table
: 첨부 // -noappend_table
: 교체bq cp
가 쿼리 비용이 들지 않고 메타데이터만 복사하기 때문에 빠름 bq cp <dataset>.<table>
someds.<table2>
CSV : 비효율적이며 배열이나 구조체를 표현할 수 없어서 표현력이 떨어짐
AVRO 아브로
- 빅쿼리로 데이터를 로드하고 파일 삭제할 경우 선택
장점
- 바이너리 파일 사용
- 계층구조 표현
- 블록단위로 분리되어 압축 가능
- 데이터를 병력로 로드 및 병렬로 내보낼 수 있음
- 데이터 용량이 적어짐
- 자기 기술적(스키마 지정하지 않아도 됨, 파일 자체가 스키마를 포함하고 있음)
단점
- 사람이 읽을 수 없는 형식
- 줄 단위로 저장됨
Parquet 파케이
- 통합 쿼리를 위해 파일 계속 보유시 파케이 선택
장점
- 아브로 장점 동일 : 바이너리형식, 블록 단위, 작은 크기, 계층 구조, 자기 기술적
- 컬럼 단위 저장
단점
- 보통 데이터 로드시에 모든 컬럼을 읽어야 하기 때문에 컬럼 단위 저장 방식이 데이터 로드에는 덜 효율적
그러나 통합쿼리 실행시에는 컬럼형 파일 형식인 파케이가 아브로보다 나음
ORC(Optimized Row Columnar) : 파케이와 비슷
JSON : 가독성과 표현력이 중요할 경우 선택, 그러나 용량 큼
현재 압축된 CSV, JSON 파일의 로딩은 최대 4GB. 그보다 큰 데이터셋이면 여러개로 분할해야 함
gsutil cp
로 여러 스레드를 활용해 데이터 업로드 가능 bq load
로 업로드 가능 gsutil -m cp *.csv gs://파일_위치
bq load ... gs://파일_위치/*.csv
파일을 GCS에 스테이징하고 데이터를 로드하는 경우가 존재하고, GCS에 스테이징 하지 않고 데이터를 로드하는 경우가 존재
파일을 GCS에 스테이징하면 최소한 빅쿼리가 로드 작업을 완료하기 전까지 스토리지 비용이 청구됨
GCS에 스테이징된 데이터를 로드하면 네트워크 전송 시간이 소요되고, 빅쿼리로의 로드 시간이 소요됨
압축하지 않은 파일을 빅쿼리로 데이터를 로드하면 빠르지만, 파일을 네트워크로 전송하는 시간이 느려서 해당 장점을 상쇄GCS 스테이징 데이터 > 네트워크 전송 > 빅쿼리로 로드 > 데이터 로드 완료
bq mkdef
(테이블 정의 생성) > bq mk
테이블 생성하고 외부 테이블 정의 전달 > 테이블 쿼리UI로 테이블 생성: 꼭 외부 테이블 Type을 선택해야 함
terminal 사용
bq mkdef
로 테이블 정의를 생성(테이블 정의 파일을 standard output에 출력) > 해당 출력 결과 파일에 기록 후 테이블 생성하는 bq mk
명령 실행시 param으로 전달
- 아래 코드를 통해 <테이블명> 테이블을 쿼리할 수 있지만 이건 GCS에 저장된 CSV 파일 대상이 아니고, 데이터 자체도 빅쿼리의 Native Storage에 적재되지 않음
bq mkdef --source_format=CSV \ # 테이블 정의 생성
--autodetect \
gs://파일위치/파일명.csv \ # *로 정의에 맞는 모든 파일을 참조하는 테이블을 만들 수도 있음
> /tmp/테이블이름.json
bq mk --external_table_definiton = /tmp/테이블이름.json \
<데이터셋>.<테이블명>
mkdef
, mk
, query
를 한번에(테이블 정의 param + query) 전달하면 쿼리가 실행되는 동안에만 테이블 정의 사용 가능함 LOC="--location US"
INPUT=gs://bigquery-oreilly-book/college_scorecard.csv
SCHEMA=$(gsutil cat $INPUT | head -1 | awk -F, '{ORS=","}{for (i=1; i <= NF; i++){ print $i":STRING"; }}' | sed 's/,$//g'| cut -b 4- )
bq $LOC query \
--external_table_definition=cstable::${SCHEMA}@CSV=${INPUT} \
'SELECT SUM(IF(SAT_AVG != "NULL", 1, 0))/COUNT(SAT_AVG) FROM cstable'
# 이미 테이블 정의 파일 갖고 있으면 아래와 같이 지정할 수 있음
# --external_table_definition=cstable;;${DEF}
Question SCHEMA 이거 무슨 뜻이야 > 미리 지정해놓은 variable은 $variable_name 해놓으면 가져와지는거 같긴한데
bq mkdef --source_format=PARQUET gs://폴더/files* > table_def.json
bq mk --external_table_definiton = table_def.json <dataset>.<table>
외부 데이터베이스의 쿼리를 실행하고 그 결과를 빅쿼리에 저장된 데이터의 결과와 유기적으로 결합
현재는 Cloud SQL내의 MySQL과 PostgresSQL 데이터베이스 지원
외부 쿼리를 사용하려면 빅쿼리 안에 연결 자원 생성 > 사용자에게 권한 할당
외부 데이터 베이스의 성능에 의존하고, 임시 테이블을 사용하기 때문에 클라우드 SQL이나 빅쿼리에서 실행되는 쿼리보다 느림
그러나 데이터를 옮길 필요가 없어서 ETL, 예약, Orchestration이 불필요하고 실시간으로 RDBMS에 저장된 데이터를 쿼리할 수 있는 장점
외부 데이터베이스와 빅쿼리 데이터를 연결해서 쿼리 날릴 수 있음
EXTERNAL_QUERY
로 사용
SELECT * FROM EXTERNAL_QUERY(<외부 데이터베이스 이름>, cloud_sql_query)
SELECT
c.customer_id
, c.gift_card_balance
, rq.latest_order_date
FROM ch04.gift_cards AS c
LEFT OUTER JOIN EXTERNAL_QUERY(
'<외부 데이터베이스 이름>',
'''SELECT customer_id, MAX(order_date) AS latest_order_date
FROM orders
GROUP BY customer_id''') AS rq ON rq.customer_iㅉd = c.customer_id
WHERE c.gift_card_balance > 100
ORDER BY rq.latest_order_date ASC;
# Google Sheet 데이터를 a_dataset이라는 데이터셋, b_table 이라는 테이블로 만들었을 때 아래와 같이 쿼리
SELECT * FROM a_dataset.b_table
Cloud BigTable은 관리형 NoSQL 데이터베이스 서비스(구글운영)