database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
ㆍPostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
PostgreSQL Q&A 7646 게시물 읽기
No. 7646
최근 삽질 이야기2
작성자
신기배(소타)
작성일
2009-03-12 15:57
조회수
9,478

pgsql, mysql, ldap, pgsql+slony-I을 지나 도저히 RDBMS로는 해결할 수 없을 것 같아서 파일 기반 DB엔진들을 알아보았습니다.

Tokyo Cabinet(이하 TC)이라는 일본의 mixi에서 쓰는 엔진의 성능이 좋아 보여서 바로 설치해서 포함된 테스팅 툴을 돌렸습니다.

1억건 채우는데 400초가 걸리더군요. 옳다쿠나 싶어서 이걸 기반으로 미들웨어를 만들었습니다.

필요한 구조는

ID, URL 두가지로 조회가 일어나고 두가지 값 중 하나로 검색을 하면 입력 시 넘겨준 데이터 내용을 주기만 하면 됩니다.

그래서 ID-DATA 해시 테이블, URL-ID 해시 테이블. 이렇게 두개를 만들어서 하기로 했습죠..

 

처음에는 엄청난 속도로 입력이 되기 시작했습니다. 드디어 고생끝이다 싶었는데 천만건을 넘어가면서 속도가 1/10으로 줄어들었습니다.

그래서 여기저기 튜닝도 해보고 테스트 셋인 1억건에 맞춰서 hash bucket도 늘리고 이짓 저짓을 다 했습니다.

근데 중요한게 이 서버의 메모리가 15기가 뿐이라서 이 영역을 넘어서는 데이터 크기가 되면 무조건 느려졌습니다.

하나의 파일을 mmap으로 처리하는 놈이라 디스크 IO에 영향을 많이 받겠구나 싶어서 중간에 메모리 해시 테이블을 두고 일단 메모리에 넣은 다음에 background writer가 파일에 싱크하는 방식도 해봤는데 메모리와 디스크의 속도 차가 너무 커서 결국 포기

 

이거 이틀만에 GG

 

그다음 솔루션은 Berkeley DB였습니다. 오라클에서 지원하고 있고 문서도 풍부하고 튜닝 포인트도 많고 해서 선택했습니다.

저장 레이어를 TC에서 BDB로 바꾸고 다시 테스트를 돌리는데 캐쉬를 12기가를 주고 page size 조절하고 DB_ENV가지고 뭐도 해보고 다 해봐도 TC만큼 나오지 않았습니다. 입력, 조회 속도가 느린데다 메모리도 많이 먹더군요..

필요한 성능은 초당 5천~1만건 입력입니다... 턱도 안되는 성능을 보여줘서 GG..

 

그래서 어쩔수 없이 low level을 직접 만들기로 했습니다.

요구치는 10억건의 데이터를 store한다. 인데 목표치를 낮췄습니다;; 3억건으로.

3억건의 데이터 중 필요한 데이터를 찾아내는데 필요한 ID, URL인덱스에 메모리 9기가를 주고 나머지 메모리는 파일 캐싱과 OS, 미들웨어가 사용한다고 가정하고 데이터 구조를 만들기 시작했습니다.

1억건의 데이터가 100바이트만 사용해도 10기가 입니다.. 3억건이 9기가의 메모리 내에서 처리하려면 하나의 인덱스가 30바이트를 넘어서는 안됩니다.. =_=; 데이터 구조를 만들다 보니 임베디드 환경도 아니고 엄청나게 제약적인 환경이 되더군요..

 

ID인덱스 (10바이트)

ID: unsigned int32(4바이트)

데이터 파일 ID: unsigned int16(2바이트)

데이터 파일 내의 데이터 위치 offset: unsigned int32(4바이트)

 

URL인덱스 (20바이트)

URL hash: char[16] (16바이트 md5)

ID: unsigned int32(4바이트)

 

사실 ID인덱스는 9바이트 였습니다; 마지막 offset의 경우 2의 24승으로 충분히 표현할 수 있어서 int24를 구현했는데 개발 환경이랑 실제 서비스랑 바이트 오더가 달라서 문제가 자꾸 생겨서 그냥 4바이트로 감.. 메모리 300메가 낭비 ㅠ

 

URL로 검색이 들어오면 ID를 찾아서 ID인덱스에서 뒤지는 구조입니다.

 

두 종류의 인덱스는 각각 3억건에 해당하는 내용을 담을 파일을 수만개로 나눠서 mmap으로 열고 있습니다. 처음에는 무심코 65,536개씩으로 했다가 max open file에 걸려서 부랴부랴 수정함;; 두 인덱스 합쳐서 약 4만개의 수백KB의 파일로 나눔

ID인덱스는 어차피 정수형이고 3억건이 limit이기 때문에 들어오면 2차원 배열처럼 된 메모리에 바로 매핑됩니다. 수치가 어떻든 찾아서 데이터 얻는데 걸리는 시간이 매우 빠르고 같습니다.

URL쪽 인덱스가 문제인데 어떤 URL이 들어올 지 몰라서; ID인덱스 처럼 공간을 미리 할당해 놓을 수가 없습니다. 그리고 MD5로 URL을 해싱해서 하기 때문에 데이터 충돌이 날 수 있습니다.. 통계 상 3억건의 MD5에서 충돌이 발생할 확율이 매우(0.000...0???) 낮기 때문에 무시하기로 함 -_);;;

새로운 URL이 들어오면 mmap으로 매핑된 URL인덱스 파일에서 20바이트씩 seek 하면서 데이터를 찾습니다... 이놈이 성능이 쥐약임 ㅠ 이거 개선해야 함.... 그래서 ID를 찾으면 ID인덱스에서 데이터 파일에 대한 정보 얻음

 

그래서 파일 ID와 파일 offset을 찾아내면 4메가마다 블럭단위로 증가하는 데이터 파일을 열어서 해당 offset에서 [내용길이,내용..] 으로 되어 있는 블럭을 읽어서 sendfile로 클라이언트에게 전송.

데이터 파일은 한 번 쓰여지면 삭제 마킹되거나 수정하지 않고 새로운 내용이나 갱신된 내용이 들어오면 현재 열려있는 마지막 데이터 파일 맨 밑에 붙입니다.

 

요 며칠 삽질이고 아직 얼마나 잘 돌아가는지는 확인해보지 못 했습니다. 아직도 테스트 중;

신경 쓴 부분입니다.

1. 데이터를 찾아가는 복잡도를 0에 가깝게 한다 -> ID 인덱스

2. 다른 엔진처럼 디스크를 아끼기 위한 삽질을 하지 않는다 -> 무조건 마지막 데이터 파일에 append

3. 메모리를 아끼기 위해 가능하면 zero copy -> 전송은 sendfile

4. 인덱스만 메모리에 올리고 데이터 파일은 가능하면 캐싱되지 않도록 한다. -> 쓰기 위한 마지막 데이터 파일을 제외하고는 요청시 읽어서 sendfile하고 끝

 

가장 힘든건 뭐 바꾸고 나면 성능 잘 나오는지 알아보기 위해서 하염없는 데이터 입력 테스트를 기다려야 한다는 것 ㅠ

 

이걸로 끝이 났으면 좋겠네요 ㅠㅠㅠㅠㅠ;

 

 

이 글에 대한 댓글이 총 3건 있습니다.

좋은 자료네요.

우리 동네 개발자 아저씨한테 보여줘야겠습니다.

제가 계속 메모리DB 만들어달라고 꼬득이고 있거든요.

도통 기대에 부응하고 있지는 않지만.


김상기(ioseph)님이 2009-03-12 17:45에 작성한 댓글입니다.

ㅎㅎ 완전히 뭐 빠지게 해보시는군요.

 

일단 데이터 량이 10억건이라 가정하고 하겠습니다.

 

저도 low level db를 만든기억에 막 떠오르네요 ^^:

 

일단 url hash를 b+tree로 변경해서 해보시기 바랍니다.

 

그렇게만 하시면 원하는 성능 충분히 나올거라 보입니다.

 

문제는 insert시 sort문제인데 이건 고민을 해야겠군요 ㅎㅎ

 

이리저리 고민하시다 보면 DBMS 만들고 계실거입니다 ㅎㅎ

 

그럼

김병석(byung82)님이 2009-03-12 18:53에 작성한 댓글입니다.

우아.. 드디어 스트레스 테스트는 통과입니다.. ㅠㅠㅠㅠㅠ

2억 3천만건 들어가고도 안정적으로 입력이 계속되어서 다음 단계로 넘어가기로 했음 ㅎㅎ

입력은 초반에 만건 이상씩 들어가더니 억 넘어가고는 초당 4천 정도가 되더라구요.

조회는 세션이 많지 않을 땐 초당 7천~만 건 정도 됩니다.

이거땜에 속이 타서 똥색도 까매졌지 말입니다 ㅠ

잘 마무리 되어가서 다행이네요..

아직 URL 인덱스 효율 개선은 하지 않았습니다. 이놈이 시피유를 많이 먹던데 조만간 개선해야겠습니다 ^^;

신기배(소타)님이 2009-03-13 17:34에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
7649데이터-스트링스에 기호(; / 등)사용이 허용되는지요? [1]
이길호
2009-03-16
6681
7648내장 SQL에서 테이블명을 호스트 변수로 썼으나...
디비는어렵다;;
2009-03-13
7757
7647기초적인 질문 몇가지 [2]
집에가자
2009-03-13
7956
7646최근 삽질 이야기2 [3]
신기배
2009-03-12
9478
7645김상기님 감사합니다. ^ ^ - 추가 질문 ㅎㅎ [2]
이진영
2009-03-12
7687
7644postgres 이중화에 대하여 [1]
김태규
2009-03-12
10719
7643커서 open시에 프로그램이 멈춥니다...
양영광
2009-03-11
6931
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2023 DSN, All rights reserved.
작업시간: 0.051초, 이곳 서비스는
	PostgreSQL v16.1로 자료를 관리합니다