2016-06-30 3 views
10

나는 전화 요금 청구 소프트웨어 시스템을 가지고 있습니다. 그것에는 사용자의 통화 기록이 매일 기록됩니다. 로그는 날짜 (월)별로 수평 분할됩니다. 각 파티션은 별도의 데이터베이스에 저장되며 여러 인스턴스로 분산 될 수 있습니다.수평 분할 된 데이터를 정렬하는 방법

UI에서 사용자는 기간을 지정합니다. 반환 된 데이터는 모든 필드에서 정렬 할 수 있습니다. 날짜 범위가 여러 파티션으로 확장 될 수 있습니다. 응용 프로그램은 날짜 범위의 데이터를 통해 페이징을 지원해야합니다.

정렬을 위해 너무 많은 레코드를 메모리에로드 할 수 없습니다. 쿼리 내에서 정렬을 수행하면 하나의 결과 집합 내에 정렬 된 데이터 만 제공됩니다.

그래서 개별적으로 정렬 된 여러 파티션의 데이터를 정렬해야합니다. 여러 정렬 된 결과 집합에서 정렬 된 레코드를 UI로 반환하려면 어떻게해야합니까?

편집 :이 문제에 대한 추가 분석을 마친 후에 더 많은 정보를 얻습니다. 페이지 매김의 요구 사항도 있습니다. 이 때문에 우리는 여러 결과 집합에 대해 실시간 정렬을 수행하는 한 가지 방법을 찾아야합니다.

+1

정렬 할 열과 레코드 ID 만로드 한 다음 정렬 된 ID를 기준으로 표시 할 레코드를 정렬하고 마지막으로로드 할 수 있습니다. DB 레벨에서 의미있는 인터리빙을 할 수 있는지 확신하지 못하기 때문에 코드에서 수행하는 것이 가장 쉬운 방법 인 것 같습니다. 또 다른 옵션은 메모리 매핑 된 파일에 (부분) 레코드를 쓰고 정렬하는 것일 수 있습니다.하지만 여기에는 고전적인 속도 - 대 메모리 상황이 모두있는 경우보다 많은 성능이 필요합니다. – Thomas

+0

첫 번째 접근법에 대해 논의했지만이 접근법의 단점은 ID를 사용하여 다시 쿼리해야한다는 것이며 UI에서 나온 것이므로 페이지 매김도 수행해야합니다. –

+1

우리는 모든 데이터를로드하는 데 너무 많은 메모리가 필요했던 비슷한 상황을 겪었습니다. 따라서 ID를 정렬하고 정렬하는 데이터 만 먼저로드 한 다음 ID 만 정렬하고 유지하는 방식을 따랐습니다. 그런 다음 페이징은 정렬 된 ID에 대해 작동하고 페이지의 ID에 해당하는 레코드 만 완전히로드됩니다. 물론 다시 쿼리해야하지만 페이징을 사용하면 어쨌든 그렇게해야합니다. 두 번째 (페이징) 쿼리 속도를 높이려면 원본 파티션을 저장하고 해당 파티션 만 쿼리하면됩니다. – Thomas

답변

2

메모리의 제한된 데이터를로드하는 ResultSet의 기능에 의존하여 동적 비교기를 사용하여 Java의 솔루션을 만들 수 있습니다. 해결 방법은 각 resultSet에서 첫 번째 레코드를 가져 와서 Java에서 정렬하고 정렬 된 데이터에서 첫 번째 요소를 반환하는 것입니다.

자세한 해결 방법 :

먼저 우리는 우리에게 화면에 choosed 할 기준에 따라 dymanic 비교기를 줄 수있는 프로그램을 만들었습니다.

둘째, 다른 파티션에서 ResultSet을 래핑하는 DAO에 하나의 AggregateResultSet 래퍼를 작성했습니다. 참고 : 이러한 개별 ResultSet은 이미 동일한 기준으로 정렬되어 있습니다. 그런 다음 AggregateResultSet에 동적 비교기가 제공됩니다.

이 AggregateResultSet에는 처음에는 각 결과 집합의 첫 번째 요소를 저장하는 데이터 구조가 있습니다. next() 호출시 다음 요소를 리턴합니다. 이 요소는 dynamicComparator에 따라 첫 번째 요소가됩니다. next() 호출 중에이 요소를 임시 데이터 구조에서 제거하고 같은 결과 집합의 다음 요소를 임시 데이터 구조에 삽입합니다. 이런 식으로 AggregateResultSet은 Java에서 매우 제한된 데이터를 병합/저장/정렬하여 예상 된 순서로 데이터를 반환합니다.

정렬에 숫자/문자열 데이터가 대부분 있기 때문에 비교 문제를받지 않기를 바랍니다.

+1

Java 애플리케이션에서 메모리 오버 헤드를 줄여야하는 흥미로운 솔루션처럼 들립니다. 이론적으로는 다음 요소를 빠르게 검색하기 위해 db의 캐시에 결과를 보관할뿐만 아니라 연결을 계속 열어 두어야하기 때문에 데이터베이스에 대한 영향을 알 수는 없습니다. 또한 db가 캐시에 유지하는 데이터가 업데이트되면 트랜잭션 문제가 발생할 수 있습니다. – Thomas

+0

@Thomas, 청구 시스템이므로 데이터가 다양한 수준에서 조정되고 절대로 업데이트 (보안) 된 후 데이터 (통화 기록)가 한 번만 (하루 +2) 업로드됩니다. –

+0

당신의 솔루션을 정확하게 이해한다면 페이징은 매우 비효율적 일 것입니다. 왜냐하면 페이지 n 전에 모든 n-1 페이지를 읽어야하기 때문입니다. –

관련 문제