출처 : http://www.gpgstudy.com/forum/viewtopic.php?p=83676
1. 게임에 관련된 DB를 설계할 때 부하에 관련되어 고려해야 할 사항들이 어떤게 있나요?
모든 성능 이슈가 그러하지만 DB에게 있어서는 Trade-Off 가 대단히 중요합니다. 우선 내가 구현하고자 하는 DB가 어떤 목적의 DB인지 파악하는 것이 무엇보다도 중요하죠, 일반적으로 게임은 OLTP 입니다. 즉 Insert / Update / Delete 가 빈번히 발생하는 구조로 되어 있는 것이 일반적인 형태입니다.
즉 OLTP 환경에서는 단위 트랜잭션이 최대한 짧게 유지 되도록 하는 것이 대단히 중요합니다. 이 경우 Lock 조정을 위해서 ISOLATION LEVEL 을 조정하여 여러 트랜잭션이 블로킹을 발생 시키지 않도록 해주어야 합니다. 그러나 이 모든 것 보다 우선 하는 게 있으니 바로 모델링입니다. 우선 모델링을 잘 잡아 두면 후에 튜닝 하기가 상당히 수월 하기 때문에 모델링을 중점적으로 공부 하는 것이 중요 합니다.
보통 게임 DB는 구조는 매우 단순하다고 생각 할 수 있는데, 생각하기 나름입니다. 복잡하다고 치면 한없이 복잡한 게 게임 DB입니다. 그래서 스팩의 변화나 기획의 변화에 유연하게 대응 할 수 있는 구조로 설계를 하는게 중요 합니다. 튜닝은 그 다음이죠
2 . 게임에서 DB에 부하를 주는 부분이 어떤 부분이 있나요?
부하를 주는 부분은 정말 다양 하기 때문에 자신이 만들고자 하는 게임이나 데이터를 이용하는 스타일에 따라서 완전히 달라 질 수 있습니다.
3 . 테이블에 값들을 insert 문이나 delect 처럼 생성하고 제거하는 것보다 update문처럼 정보를 변경하는 것이 더 부하가 적게 걸린다고 하던데 왜 그런 것인지 그리고 실제 어느정도 차이가 나는 것인지요?
Insert & Delete VS Update 에 대한 이야기가 많은데, 이 문제는 테이블의 단편화 현상과 관련된 문제입니다. 먼저 DB의 성능은 일반적으로 면적을 컨셉으로 하여 이애 하는 것이 편리 합니다. 즉 면적이 넓어지면(데이터가 커지면) 속도가 그만큼 느려지게 됩니다.
일반적으로 OTLP 의 경우에 Key 가 되는 데이터에 인덱스를 걸어 두게 됩니다. 즉 데이터를 하나 넣으면 데이터 + 인덱스가 되는 형태이고 읽기 성능의 최대화를 위해서 물리적으로 데이터가 elevated sort 된 형태로 입력을 하는 경우가 많이 있습니다.
만일 새로운 데이터가 들어가면 데이터 페이지에 데이터를 넣어 두고 추가적으로 인덱스 정보를 기록 합니다. 또한 DB에서 잡아둔 하나의 Page 단위를 넘어서게 되면 새로운 페이지를 만드는 구조로 데이터저장 공간을 확장 하게 됩니다.
데이터를 직접적으로 지우면 인덱스 정보와 데이터 정보를 함께 지워야 하기 때문에 지울 때 시간이 오래 걸립니다. 또한 일반적인 DBMS 의 경우 데이터 A, B, C, D, E, F 데이터를 순서대로 넣고 그 중에서 C를 지우게 되면 D, E, F 을 위로 올리는 게 아니라 빈칸으로 두고 데이터를 검색 하게 됩니다. 이유는 모든 데이터를 앞으로 올리는 경우 Delete 시 부하가 높아 지기 때문에 비워두게 됩니다. 이를 Disk fragmentation 혹은 Data fragmentation 이라 하는데 fragmentation 이 심해지는 경우 데이터를 검색하기 위해서 검색을 해야 하는 면적이 넓어 지기 때문에 효율이 떨어지게 됩니다.
그렇기 때문에 데이터를 fragmentation 을 줄이고 Delete 시의 부하를 조금이라도 줄이기 위해서 데이터를 지웠다고 마 킹만 해두게 됩니다. 이 데이터는 정기 점검이나 패치 작업등 에 일괄적으로 삭제 해두고 Index 을 Rebuild 해주게 되면 단편화 현상을 해결 할 수 있습니다.
4. 제약이나 참조 키 , CASCASDE 같은 것을 사용하면 게임에 부하가 심해지나요?
편의성을 위해서 사용할려고 하는데 DB에 부하를 주는 부분이라면 사용을 피할려고 합니다. ( 근데 그렇게까지 부하를 주지 않을꺼 같은데... )
5. Primary key 와 foreign key를 사용해서 관리를 할 때 장점과 단점에 대해 알고 싶습니다.
특히 DB 부하에 관련되서 알고 싶습니다.
제약이나 참조 키의 경우에 데이터 입력 시에 PK 관의 무결 성을 검사하게 됩니다. 그래서 무결성에 위배가 되면 데이터를 입력하제 않게 되죠, 또한 Update 시에는 CASECADE 가 설정 되어 있는 경우 PK 을 수정 하면 FK 의 데이터를 수정 하도록 되어 부하가 높아 집니다. 이러한 이유로 3의 방법을 주로 이용 하는 것입니다.
일부 설계자나 개발자는 실 서비스의 FK을 모두 지우고 서비스를 하는 경우가 있는데 제 개인적인 생각으로는 올바르지 못하다고 생각 합니다. 후에 전문 DBA가 튜닝 시에 상당한 애를 먹게 되고 만일 논리적인 규약이 맞지 않는 경우 데이터의 무결 성 위배로 인한 중복 데이터의 삽입이 발생 할 수 있고 이를 개발자가 가드를 하지 못하는 경우 중복 또는 불필요한 데이터로 인해서 면적(DB Size) 가 커지게 되면 결국 DB는 느려지게 때문에 정규화를 최대한 지킬 필요가 있습니다.
실제로 게임 DB 튜닝을 나가면 이러한 경우가 대단히 많습니다. Table 정보를 Reverse Engineering 했을 때 ER-Win 등의 Case Tool 에서 테이블 정보가 평행선으로 쭉 나올 때의 당황스러움이란;;
개인적으로는 최대한 정규화를 하고 쪼갤 수 있는 만큼 쪼개고 그러다 안되면 비정규화를 해야 하는데 정규화 = 느리다 라는 선입견을 가진 분이 많아서 저 역시 이를 설득 하는데 제법 애를 먹습니다.
DB 에서 정답은 없습니다. 특히나 성능을 관점으로 바라보게 되는 경우 더 다양한 변수가 존재 하게 되고요, 개발자에 따라서 요구하는 데이터가 다르고 데이터를 수정 하거나 입력 하는 스타일이 모두 다릅니다. 개발자가 올바른 DB를 이해 하기 위해서는 기존의 절차적인 사고를 버리고 집합적인 사고로의 전환과, 꾸준한 모델링 그리고 서비스 되고 있는 DB에 대한 주기적인 관찰과 모니터링이 중요 하다고 생각 됩니다.