TClientDataSet은 델파이/C++빌더에서 3티어 데이터베이스 연결에서 클라이언트 쪽 DB 처리를 위해서도 많이 사용되지만, 메모리 데이터셋으로도 많이 사용됩니다. TClientDataSet에서 FileName 속성을 지정하거나 LoadFromFile / SaveToFile 메소드를 이용하면 로컬의 파일을 자체 메모리 내에 로드하여 메모리에서 동작하는 빠른 데이터셋을 구현할 수 있죠.
100% 메모리에서 동작하므로 파라독스나 SQLite 같은 로컬DB를 쓰는 것보다 당연히 압도적으로 빠릅니다. 요즘 PC들의 메모리 사양을 고려하면, 수 MB 이내의 데이터라면 다른 방법들보다 TClientDataSet을 쓰는 것이 훨씬 좋겠습니다.
물론 좀 더 전문적인 서드파티의 메모리 데이터셋들이 있기는 합니다만, TClientDataSet은 델파이/C++빌더의 다른 부분들과의 연동 측면에서 더 유리합니다. TClientDataSet으로 개발한 루틴은 조금만 손대면 dbExpress, DataSnap 루틴으로 쉽게 업그레이드할 수 있죠. 더욱이 기본 컴포넌트이기 때문에 델파이/C++빌더 자체 이외에 추가 설치 없이 바로 쓸 수 있다는 점은 부가적인 장점입니다. 저도 이런 저런 목적으로 TClientDataSet을 엄청 많이 씁니다.
또한 저장되는 파일 포맷은 바이너리인 cds와 xml 두가지 중에 선택할 수 있는데, xml은 호환성이 더 좋고 반면 cds 파일은 파일 크기가 더 작아집니다.
그런데, 만약 TClientDataSet을 lookup 목적 등으로 읽기 전용 테이블로 쓴다면 겪지 못할 문제이겠지만, TClientDataSet을 읽고 쓰고 하는 테이블로 쓰다보면, 어느 순간 데이터 파일의 크기가 엄청나게 늘어나 있는 것을 보실 수 있을 겁니다. 몇개의 레코드만 수정해도 원래의 파일보다 두배 이상 커지는 경우도 있습니다.
TClientDataSet 파일의 크기가 이렇게 급격하게 커지는 이유는, ChangeLog가 함께 저장되기 때문입니다. TClientDataSet은 3티어에서 로컬 데이터 사본을 다루는 목적도 가지고 있고, 그럴 때 로컬 데이터의 변경 내용들을 가지고 있어야 합니다. 보통 델타(delta)라고 하죠. 그리고 이런 델타 값들은 사용자가 서버쪽에 반영을 요구하거나(ApplyUpdates) 혹은 Undo(CancelUpdates)를 하면 당연히 사라지게 됩니다.
물론 이런 델타 값은 프로그램 실행중에 메모리에만 존재하지만, ApplyUpdates() 혹은 CancelUpdates()를 하지 않은 상태에서 데이터를 파일로 저장하면 그대로 파일에 함께 저장됩니다. 실제 여러 차례 수정된 TClientDataSet의 xml 파일을 열어보면, 실제 데이터 외에 ChangeLog라는 태그에 엄청난 분량의 델타 데이터들이 들어가있는 것을 볼 수 있습니다.
그런데 TClientDataSet을 3티어가 아닌 로컬 메모리 테이블로 사용할 때는, 델타를 반영할 서버측 Provider가 없으므로 ApplyUpdates() 호출을 할 수가 없습니다. (실제 호출하면 Provider가 없다고 에러가 나죠) 그렇다고 델타 값을 없애기 위해 데이터들에 Undo를 할 수도 없겠구요.
TClientDataSet에서 델타 값을 없애려면 두 가지 방법이 있습니다. 첫번째는, TClientDataSet의 델타 값을 유지할 지 여부를 결정하는 LogChanges 속성을 false로 설정하는 것입니다. 이 속성의 디폴트 값은 물론 true 입니다. 이 속성은 published가 아닌 public 속성이기 때문에 오브젝트 인스펙터에서는 보이지 않으며, 코드로 설정해야 합니다. 주의할 점 하나는, 반드시 Active 상태에서만 호출할 수 있습니다. 즉, Open을 하거나 CreateDataSet을 호출한 직후에 설정하면 됩니다.
다른 한가지 방법은, TClientDataSet의 MergeChangeLog 메소드를 호출하는 것입니다. 이름 그대로 체인지로그, 즉 델타 값을 병합하고 없애줍니다. 이 메소드는 파일로 저장되기 전에 호출해주면 되겠지요.
두 방법 모두 유효하지만, 각각 장단점들이 있습니다. LogChanges 속성을 false로 설정하면 항상 델타 값들을 관리하지 않으므로 아무래도 TClientDataSet이 조금 더 빨라집니다. 또 MergeChangeLog 메소드를 사용하면 중간중간에 Undo 기능을 활용할 수 있다는 장점이 있죠. 어떤 방법을 사용할지는 이런 특성에 따라 선택하면 되겠습니다.
아~ 저는 ClientDataSet을 쓰면서 메모리가 증가하는지도 모르고있었네요…
ㅠㅠ 좋은 정보 감사합니다. ^^
근데 임프님… 제가 메일보냈는데 답장이없어서요~
혹시 메일서버가 잘못되서 못받으신건가요?? 아니면…
바쁘신분이신데 무례하게 보였다면 죄송합니다.
이야.. 이런게 있었네요.. 감사합니다 잘보고 갑니다 ^^