CSV 파일을 데이터 웨어하우스(redshift)에 로드할 때 주의사항
1. CSV delimeter를 확인하였는가? - comma(,) vs vertical bar(|)
# json 처리
response_json = json.loads(api_response.content)
datas = []
location = response_json["iss_position"]
datas.append(location["latitude"])
datas.append(location["longitude"])
datas.append(response_json["timestamp"])
print(datas)
export_file = "export_file.csv"
with open(export_file, "a", newline="") as fp:
csvw = csv.writer(fp, delimiter="|")
csvw.writerows([datas]) # 2차원 리스트로 처리
fp.close()
-> 이런 Python 코드가 있을 때, delimiter = "|"로 설정하지 않으면 CSV 파일은 기본적으로
10, 10, 150000000
이런 식으로 쉼표를 이용하여 데이터가 필드 별로 저장된다.
그런데 이런 상황에서
sql = "COPY public.Timelines"
sql += " from %s"
sql += " iam_role %s;"
cur.execute(sql, (file_path, role_string))
rs_conn.commit()
이런 코드로 redshift에 COPY를 시도하게 되면
-> cur.execute(sql, (file_path, role_string))
psycopg2.errors.InternalError_: Load into table 'timelines' failed. Check 'stl_load_errors' system table for details.
이런 오류가 발생하시게 되어 망함.
stl_load_errors를 확인해서 왜 망했는지 살펴보면 Delimeter not found라는 오류를 확인할 수 있다.
해결법은 크게 2가지인데
1) COPY 쿼리 구문에 DELIMETER ','; 옵션을 줘서 csv 딜리미터를 바꿔주는 방법이 있다.
2) csv 만들때 애초에 delimeter를 버티컬 바로 바꿔서 만드는 방법이 있다.
이중에서 2번을 살펴본다.
애초에 csv delimiter copy에 주어진 기본 값이 Vertical Bar(|)이기 때문에 이 방법을 택한 것이고,
comma를 선택하면 만약 데이터 자체에 comma가 들어갈 때 해당 데이터 값을 따로 처리해야하는 귀찮음이 발생하므로
쉼표 문제를 방지하기 위해 버티컬 바를 기본 delimeter로 선택한다.
해결 방법은 간단하다.
with open(local_filename, 'w') as fp:
csv_w = csv.writer(fp, delimiter='|')
csv_w.writerows(results)
fp.close()
이처럼 python으로 csv 파일을 쓸 때, delimiter = '|' 값을 주면 된다.
(그렇지 않으면, comma로 데이터가 구분된다.)
이거 때문에 시간 좀 썼는데, 다른 분들은 귀중한 시간을 아끼시길 바란다..^^
2. 전체 추출 시 중복 주의
S3에서 redshift로 데이터를 로드할 때
만약 증분 추출이 아닌 전체 추출이라면, 그냥 COPY를 하게 될텐데
여기서 주의할 점은 COPY 작업을 실행하기 전에 Redshift에서 대상 테이블을 삭제해야 한다.
# example code
# 커서 오픈
cur = rs_conn.cursor()
# 전체 추출의 경우, 테이블을 잘라내지 않으면 중복이 된다.
sql = "TRUNCATE public.Timelines;"
cur.execute(sql)
안그러면 데이터가 중복되어 담긴다.