Redshift 는 PostgreSQL 계열 프로토콜을 쓰지만 SAS 에서는 두 방식 중 하나로 붙는다. 어느 쪽인지에 따라 필요한 라이선스와 설정이 달라진다.
REDSHIFT 엔진을 쓴다. Redshift 전용이라 타입 변환과 대량 적재가 맞춰져 있다.ODBC 엔진으로 Redshift ODBC 드라이버를 통해 붙는다. 전용 인터페이스가 없을 때의 대안이다.들고 있는 라이선스를 먼저 확인한다.
proc setinit;
run;
로그의 제품 목록에 SAS/ACCESS Interface to Amazon Redshift 가 없으면 ODBC 경로만 쓸 수 있다.
5439), 데이터베이스 이름, 스키마SAS/ACCESS Interface to Amazon Redshift 가 자체 드라이버를 함께 설치하는지는 릴리스와 설치 형태에 따라 다르다. 설치본의 배포 문서에서 확인한다 (확인 필요).
연결 자체가 되는지부터 확인한다.
nc -vz redshift-cluster.example.ap-northeast-2.redshift.amazonaws.com 5439
libname redlib redshift
server='redshift-cluster.example.ap-northeast-2.redshift.amazonaws.com'
port=5439
database='analytics'
schema='public'
user="&rsuser"
password="${MASKED}";
비밀번호를 소스에 평문으로 두지 않는다. PROC PWENCODE 로 인코딩한 값을 쓴다.
proc pwencode in='${PASSWORD}' method=sas004;
run;
로그에 찍힌 {SAS004}... 문자열을 password= 에 넣는다. 인코딩은 암호화가 아니므로 소스 파일 자체의 접근 권한도 함께 좁힌다.
리눅스에서는 드라이버와 DSN 정의가 따로 있다.
[Amazon Redshift ODBC Driver]
Description = Amazon Redshift ODBC Driver
Driver = /opt/amazon/redshiftodbc/lib/64/libamazonredshiftodbc64.so
위 블록은 /etc/odbcinst.ini 에 넣고, DSN 은 /etc/odbc.ini 에 넣는다.
[RedshiftDSN]
Driver = Amazon Redshift ODBC Driver
Server = redshift-cluster.example.ap-northeast-2.redshift.amazonaws.com
Port = 5439
Database = analytics
SAS 실행 계정이 이 파일들을 읽을 수 있어야 한다. 표준 경로가 아닌 곳에 두었다면 환경 변수로 알려 준다.
export ODBCINI=/opt/sas/odbc/odbc.ini
export ODBCSYSINI=/opt/sas/odbc
이 변수는 SAS 프로세스가 보는 환경에 있어야 하므로 Object Spawner 기동 스크립트나 sasenv_local 에 넣는다. 대화형 셸에만 넣으면 서버 세션에는 전달되지 않는다.
libname redlib odbc dsn='RedshiftDSN' schema='public'
user="&rsuser" password="${MASKED}";
proc datasets library=redlib;
run;
quit;
proc sql;
select count(*) from redlib.sales;
quit;
큰 테이블을 통째로 DATA 스텝으로 끌어오면 전부 네트워크를 타고 넘어온다. 집계는 PROC SQL 로 밀어 넣어 Redshift 쪽에서 계산하게 한다. 밀어 넣기가 실제로 일어났는지 로그로 확인한다.
options sastrace=',,,d' sastraceloc=saslog nostsuffix;
명시적 패스스루로 쓰면 SQL 이 그대로 넘어간다.
proc sql;
connect to redshift as rs (server='redshift-cluster.example.ap-northeast-2.redshift.amazonaws.com'
port=5439 database='analytics'
user="&rsuser" password="${MASKED}");
create table work.summary as
select * from connection to rs
(select region, sum(amount) as total from sales group by region);
disconnect from rs;
quit;