redis 대량 데이터 입력
redis 대량 데이터 입력
이 글은
https://gist.github.com/Squab/52d42652719cc28451d7
코드의 사용법에 대한 이야기입니다.
1. redis-cli --pipe 이야기
redis에서 자료를 입력하는 방법은 여러가지가 있습니다.
가장 간단하게,
일반 텍스트 파일에 redis-cli 에서 사용하는 명령 구문 형태로 자료 입력 명령을 쭉 입력하고, OS 파이프 기능을 이용해서, 표준 출력 내용을 redis-cli 쪽 표준 입력으로 보내서 자료를 입력하는 방법입니다.
$ cat medi_code.txt
HSET medi_code 100 의료보험
HSET medi_code 110 직장
HSET medi_code 120 지역
HSET medi_code 130 "공무원 및 사립학교 교원"
HSET medi_code 200 의료보호
HSET medi_code 210 1종보호
HSET medi_code 211 거택보호자
HSET medi_code 212 시설보호자
HSET medi_code 213 국가유공자
HSET medi_code 214 월남귀순자
HSET medi_code 215 인간문화재
HSET medi_code 216 성병감염자
HSET medi_code 217 의사상자
HSET medi_code 218 이재자
HSET medi_code 220 2종보호
HSET medi_code 221 자활보호자
HSET medi_code 230 의료부조
HSET medi_code 231 기타보호자
$ time redis-cli < medi_code.txt
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
(integer) 1
real 0m0.005s
user 0m0.000s
sys 0m0.004s
5ms 걸렸네요.
여기서 하나 기억해야 할 것은 redis-cli 명령에서 하나의 속성 값 안에 공백 문자가 있다면,
"공무원 및 사립학교 교원" 처럼 큰 따옴표로 둘러싸 이것이 하나의 속성 값으로 처리하도록 해야 한다는 점입니다.
문제는 이렇게 입력해야 할 자료가 100만 건 경우, 이 방법은 그 다지 좋은 방법이 아닙니다.
공동데이터포털 상가 정보 자료 (https://www.data.go.kr/dataset/15012005/fileData.do)를 대상으로
상점 고유 번호와 상점명만을 추출 해서 100만 건 자료를 만들고 자료를 위와 같은 방법으로 넣어보면,
$ wc -l kostore01.txt
1000000 kostore01.txt
$ tail kostore01.txt
HSET kostore 25779768 "청산전통시장"
HSET kostore 25612795 "원주옻진액"
HSET kostore 25619783 "일영첨성대불한증막"
HSET kostore 25673160 "호곡리손칼국수"
HSET kostore 25681491 "대광기계"
HSET kostore 25757971 "해뜨는집"
HSET kostore 25757966 "부자세탁소"
HSET kostore 25723808 "새한태권도"
HSET kostore 25773734 "선화공주"
HSET kostore 25786315 "대동설렁탕"
$ time redis-cli < kostore01.txt...
(integer) 1
(integer) 1
real 0m48.909s
user 0m10.349s
sys 0m20.190s
$ redis-cli HLEN kostore
(integer) 1000000
49초 걸렸습니다. 초당 약 2만 건 정도의 자료가 들어갑니다. 뭐 나쁜 속도는 아니지만, 이 정도 성능을 쓰려고 redis를 사용하는 것은 아닙니다. 왜냐 하면, PostgreSQL에서도 이런 자료라면, 2초면 입력할 수 있기 때문입니다. (OS 디스크 캐시에 해당 자료가 있다고 가정 했을 때)
기본 개념은 입력되는 자료는 이미 redis 클라이언트-서버간 프로토콜을 저수준 양식에 맞춰있고,
client를 그냥 서버로 보내고, 서버는 받으면 그냥 저장하는 식입니다.
2. redis 자료 입력 저수순 양식
이 내용은
https://redis.io/topics/mass-insert
페이지에서 자세히 다루고 있습니다.
이것 기반으로
https://gist.github.com/Squab/52d42652719cc28451d7
페이지에서 python 코드 하나가 만들어졌고,
이것을 사용하면 됩니다.
단, python 3.x 버전에는 멀티바이트 문자 처리가 기본 유니코드로 바뀌어, 손을 좀 봐야합니다.
OS 기본 내장된 2.x 버전에서 코드 수정 없이 바로 쓸 수 있습니다.
하지만, 위에 큰 따옴표로 둘러싸는 경우 처럼 한 속성에 공백 문자가 있는 경우는
맨 마지막 줄에 있는
print proto(line.rstrip().split(' ')),
부분을
print proto(line.rstrip().split('\t')),
로 바꿔서 각 명령 속성은 탭문자로 분리한다고 변경 해서 사용하는 것이 편합니다.
자료 준비를 다시 합니다. 이번에는 tab 구분으로.
$ wc -l kostore02.txt
1000000 kostore02.txt
$ tail kostore02.txt
HSET kostore 25008500 에코맘에프에스
HSET kostore 24902357 햇살홈케어
HSET kostore 24882499 이리온샵
HSET kostore 25036790 터울림
HSET kostore 24987409 테라아로마
HSET kostore 20768375 강일렌트카
HSET kostore 22079059 지에스카넷
HSET kostore 20507522 애플빈
HSET kostore 24995995 코리아세븐청원오송생명점
HSET kostore 25000634 에스에이치종합상사
$ wc -l kostore02.txt
1000000 kostore02.txt
$ time python redis-mass.py /tmp/kostore02.txt | tail
*4
$4
HSET
$7
kostore
$8
25000634
$27
에스에이치종합상사
real 0m4.471s
user 0m4.519s
sys 0m0.119s
$ time python redis-mass.py /tmp/kostore02.txt | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000
real 0m5.054s
user 0m5.117s
sys 0m0.411s
탭 문자로 분리된 자료를 redis 저수준 명령 구문으로 변환하는데, 약 4.6초, 전체 처리가 5초, 즉, redis 작업은 0.5초에 끝납니다. 놀랄만한 속도입니다.