bq 명령으로 schema_update_option을 지정하면 열 추가 작업이 쉽습니다.

8086 단어 gcpBigQuery

요약


  • schema_update_option 에 ALLOW_FIELD_ADDITION 를 지정하면, 컬럼이 추가되었을 경우에서도, 별도 table의 schema update 작업을 하지 않아도 된다고 하는 이야기.
  • 날짜별 파티셔닝 테이블에 일차로 CSV 데이터를 투입해 가는 시스템을 상정하고 있다.
  • 공식 문서의 기재는 여기
  • 이번 BQ 커멘드로 하고 있지만, 당연히 API로서 제공되고 있으므로, 각종 SDK를 사용한 Load에서도 같을 수 있습니다(Embulk라든지에서도)
  • Embulk의 예는 여기


  • 실험한 환경



    테이블 이름
  • foobar

  • 테이블 작성 명령
    bq mk --table --require_partition_filter --time_partitioning_type=DAY 'project_id:dataset_id.foobar'
    

    Day 1



    일반적으로 다음과 같이 Load되어 있다고 합니다.

    테이블 스키마

    foobar.schema1.json
    [
      {
        "mode": "NULLABLE",
        "name": "a",
        "type": "STRING"
      },
      {
        "mode": "NULLABLE",
        "name": "b",
        "type": "INTEGER"
      }
    ]
    

    투입 데이터

    foobar1.csv
    
    "a","b"
    "abc",1
    "xyz",9
    

    Load 명령
    bq load \
    --source_format=CSV --skip_leading_rows 1 \
    'project_id:dataset_id.foobar$20200610' ./foobar1.csv ./foobar.schema1.json
    

    중간부터 컬럼이 증가



    중간에서 읽을 CSV 열이 증가했다고 가정합니다.
    이 경우,
  • schema 파일 변경
  • bq update (table schema update)

  • 두 가지가 필요하지만 schema_update_option에 ALLOW_FIELD_ADDITION를 지정하면 bq update(table schemaのupdate)가 필요하지 않습니다.

    Day 2



    테이블 스키마
  • c라는 컬럼이 추가되었습니다

  • foobar.schema2.json
    [
      {
        "mode": "NULLABLE",
        "name": "a",
        "type": "STRING"
      },
      {
        "mode": "NULLABLE",
        "name": "b",
        "type": "INTEGER"
      },
      {
        "mode": "NULLABLE",
        "name": "c",
        "type": "STRING"
      }
    ]
    

    투입 데이터
  • c라는 컬럼이 추가되었습니다

  • foobar2.csv
    "a","b","c"
    "abc",1,"zzz"
    "xyz",9,"zzz"
    

    Load 명령
  • 새 스키마를 지정합니다
  • bq load \
    --source_format=CSV --skip_leading_rows 1 \
    --schema_update_option ALLOW_FIELD_ADDITION \
    'project_id:dataset_id.foobar$20200611' ./foobar2.csv ./foobar.schema2.json
    

    로드 결과



    예상대로 Day2에서 늘어난 컬럼에 과거 분에는 null이 들어 있습니다.

    재실행시의 주의점



    rerun 하는 경우, load 하기 전에 파티션을 삭제하지 않으면 이중으로 데이터가 들어 버리므로 주의

    재실행 전에 파티션 지우기
    bq rm --force 'project_id:dataset_id.foobar$20200611'
    

    그리고 이것을 썼을 때 --replace 옵션으로 비슷한 것을 할 수 있다는 것을 알았습니다. Day2의 쿼리에 --replace를 붙이는 것만으로 좋을 것 같습니다.
    bq load \
    --replace \
    --source_format=CSV --skip_leading_rows 1 \
    --schema_update_option ALLOW_FIELD_ADDITION \
    'project_id:dataset_id.foobar$20200611' ./foobar2.csv ./foobar.schema2.json
    

    요약



    그렇기 때문에, 실제의 운용상은, 일차로 이하와 같은 bq 커멘드를 돌리면 하고 싶을 수가 있을 것 같습니다.
    export LOAD_FILE="./foobar2.csv"
    export TARGET_TABLE="'project_id:dataset_id.foobar$20200611'"
    export SCHEMA="./foobar.schema2.json"
    bq load \
    --replace \
    --source_format=CSV --skip_leading_rows 1 \
    --schema_update_option ALLOW_FIELD_ADDITION \
    ${TARGET_TABLE} ${LOAD_FILE} ${SCHEMA}
    

    좋은 웹페이지 즐겨찾기