2008-10-23 11 views
6

나는 다중 계층 데이터베이스 구동 웹 응용 프로그램 (SQL 관계형 데이터베이스, 중간 서비스 계층을위한 Java, UI 용 웹)을 디자인하고 있습니다. 언어는 별 문제가되지 않습니다.데이터베이스에서 거대한 결과 집합을 처리하는 방법

중간 서비스 계층은 데이터베이스의 실제 쿼리를 수행합니다. UI는 단순히 특정 데이터를 요청하고 데이터베이스에 의해 지원된다는 개념이 없습니다.

큰 데이터 세트는 어떻게 처리해야합니까? UI가 데이터를 요청하지만 결과가 너무 커서 메모리에 적합하지 않을 수 있습니다.

StreetSign getStreetSign(int identifier) 
Collection<StreetSign> getStreetSigns(Street street) 
Collection<StreetSign> getStreetSigns(LatLonBox box) 

UI 계층은 몇 가지 기준을 충족하는 모든 도로 표지판을 얻기 위해 요구 : 예를 들어, 거리 표지판 응용 프로그램의 서비스 계층이있을 수 있습니다. 기준에 따라 결과 세트가 커질 수 있습니다. UI 레이어는 결과를 별도의 페이지 (브라우저의 경우)로 나눌 수도 있고 모두 제시 할 수도 있습니다 (Goolge 지구까지 제공). 잠재적으로 큰 결과 집합은 성능 및 자원 문제 (메모리 부족) 일 수 있습니다.

한 가지 해결책은 완전히로드 된 객체 (StreetSign 객체)를 반환하지 않는 것입니다. 오히려 각 개별 객체를 느리게로드하는 일종의 결과 세트 또는 반복자를 반환하십시오. 난

getStreetSigns(box, 1, 1000000000) 

: 물론

Collection<StreetSign> getStreetSigns(LatLonBox box, int pageNumber, int resultsPerPage) 

는 UI가 여전히 큰 결과 집합을 요청할 수 있습니다

또 다른 해결책은 요청 된 데이터의 하위 집합을 반환하는 서비스 API를 변경하는 것입니다 이 시나리오의 표준 산업 디자인 패턴은 무엇입니까?

+0

'Collection getStreetSigns (Street street)'바로 그게 당신 문제입니다. 앱이 DB에 의해 지원된다는 사실을 모를 수도 있지만, 작동하는 컬렉션의 크기를 제어 할 수 있어야합니다. 그래서 그 고유 한 제한이 없다면, 응용 프로그램이 다음 중 하나를 지정하도록 허용해야합니다 :'Collection getStreetSigns (Street street, int maxResults, int firstResult)'. –

답변

0

ASP.NET에서는 사용자가 데이터 저장소에서 요청한 데이터 페이지 만 검색하는 서버 쪽 페이징을 사용합니다. 이는 전체 결과 집합을 검색하여 요청에 따라 메모리에 넣고 페이징하는 것과 반대입니다.

0

JSF 또는 JavaServerFaces에는 큰 결과 세트를 브라우저로 청크하기위한 위젯이 있습니다. 제안 된대로 매개 변수화 할 수 있습니다. 어떤 의미로든 "표준 산업 디자인 패턴"이라고 부르지는 않겠지 만 다른 사람이 문제를 어떻게 해결했는지 살펴볼 가치가 있습니다.

1

큰 데이터 세트가있을 가능성이있는 경우 페이징 경로로 이동하십시오.

MAX를 계속 설정할 수 있습니다.

E.G. SO는 15, 30, 50의 페이지 크기를 사용합니다 ...

0

이 유형의 문제를 처리 할 때 일반적으로 브라우저 (또는 씬 클라이언트/씩 (thick client), 귀하의 상황에 더 적합한 것)로 전송 된 데이터를 청크합니다. 특정 기준을 충족하는 데이터의 실제 총 크기에 관계없이 한 번에 모든 UI에서 사용할 수있는 부분은 아주 적습니다.

저는 Microsoft 환경에 살고 있기 때문에 제 1 차 환경은 ASP.Net with SQL Server입니다.Paging through lots of data efficiently (and in an Ajax way) with ASP.NET 2.0 Efficient Data Paging with the ASP.NET 2.0 DataList Control and ObjectDataSource

마이크로 소프트가 최근 출시 한 또 다른 메커니즘은 "Dynamic Data"자신의 생각 - 당신은 수도 : 여기에 도움이 될 수 (결과 집합을 통해 페이징에 대한 몇 가지 기술을 언급) 페이징에 대한이 기사는 그들이이 문제를 어떻게 다루고 있는지에 대한 지침을 얻기 위해 이것에 대한 내용을 확인하십시오.

0

저는 두 가지 제품에서 비슷한 작업을 수행했습니다. 일 경우, 데이터 소스는 선택적으로 페이지 매김 - 자바, 유사한 페이징 가능한 인터페이스를 구현한다 : 항목의 GET()를위한 또 다른 방법 및 페이징 데이터 소스의 구현을 구현

public interface Pageable 
{ 
    public void setStartIndex(int index); 
    public int getStartIndex(); 
    public int getRowsPerPage() throws Exception; 
    public void setRowsPerPage(int rowsPerPage); 
} 

데이터 소스를 단지 현재 페이지를 반환합니다. 따라서 시작 인덱스를 설정하고 컨트롤러에서 페이지를 가져올 수 있습니다.

한 가지 고려해야 할 사항은 커서 서버 측을 캐시하는 것입니다. 웹 앱의 경우 만료해야하지만 실적이 현저히 도움이됩니다.

0

fedora digital repository 프로젝트는 result-set-id를 사용하여 최대 개수의 결과를 반환합니다. 다음 쿼리에서 result-set-id를 제공하는 다음 청크를 요청하여 나머지 결과를 얻습니다. 쿼리 외부에서 검색 또는 정렬을 수행하지 않으려면 괜찮습니다.

2

이 상황에서 가장 자주 보인 패턴은 일종의 페이징으로, 일반적으로 서버 측에서 처리하여 정보를 줄입니다. 여기

는 거리 표지판 예제와 함께 (임시 테이블보다 일반적으로 더 빠르게) 테이블 변수를 사용하여 SQL Server 2000의 예입니다 : SQL Server 2005에서

CREATE PROCEDURE GetPagedStreetSigns 
(
    @Page int = 1, 
    @PageSize int = 10 
) 
AS 
    SET NOCOUNT ON 

    -- This memory-variable table will control paging 
    DECLARE @TempTable TABLE (RowNumber int identity, StreetSignId int) 

    INSERT INTO @TempTable 
    (
    StreetSignId 
) 
    SELECT [Id] 
    FROM StreetSign 
    ORDER BY [Id] 

    -- select only those rows belonging to the requested page 
    SELECT SS.* 
    FROM StreetSign SS 
     INNER JOIN @TempTable TT ON TT.StreetSignId = SS.[Id] 
    WHERE TT.RowNumber BETWEEN ((@Page - 1) * @PageSize + 1) 
         AND (@Page * @PageSize) 

, 당신은 일반적인 같은 물건을 더 영리 얻을 수 있습니다 테이블 표현식 및 새로운 SQL 순위 지정 기능 하지만 일반적인 주제는 서버를 사용하여 현재 페이지에 속한 정보 만 반환한다는 것입니다.

최종 사용자가보고있는 데이터에 직접 필터를 적용 할 수 있도록 허용하는 경우이 접근법이 지저분해질 수 있습니다.

6

매우 첫 번째 질문은 다음과 같아야합니다

¿ 사용자가 필요로하거나 할 수는 데이터의 양을 관리?

잠재적 인 크기가 너무 큰 경우 결과 집합을 페이징해야하지만 대답은 "아마도 그렇지 않을"것이므로 UI는 표시하려고 시도해서는 안됩니다.

엄청난 양의 저장된 데이터 (말 그대로 수백만 명의 환자, 방문, 양식 등)를 다루는 Healthcare Systems의 J2EE 프로젝트에서 일했으며 일반적인 규칙은 100 개 또는 200 개의 행을 사용자 검색을 통해 이러한 일련의 기준을 통해 사용자가 이해할 수있는 더 많은 정보를 얻을 수 있다고 조언합니다.

구현 방법은 프로젝트마다 다릅니다. UI를 실행하기 전에 쿼리의 크기를 서비스 계층에 요청하도록하거나, 서비스 계층에서 Exception을 throw 할 수 있습니다 결과 세트가 너무 많이 증가합니다 (그러나이 방법은 제한된 UI 구현으로 서비스 계층을 결합합니다).

주의하십시오!이것은 결과가 100보다 큰 경우 서비스 계층의 모든 메소드가 예외를 throw해야한다는 것을 의미하지는 않습니다.이 일반 규칙은 사용자에게 직접 표시되는 결과 세트에만 적용됩니다. 즉 UI에 컨트롤을 배치하는 것이 더 나은 이유입니다 대신 서비스 계층에 있습니다.

1

자구급 클래스와 작업 할 때주의해야 할 것은 개발자 (개발자)가 알지 못하는 상태에서 데이터베이스를 추가로 호출하는 코드입니다. 예를 들어 Person 객체의 컬렉션을 반환하는 메소드를 호출하고 후드에서 진행되는 유일한 작업이 단일 "SELECT * FROM PERSONS"호출이라고 생각할 수 있습니다. 실제로, 호출하는 메서드는 반환 된 Person 개체 컬렉션을 반복하고 각 Person의 Orders 컬렉션을 채우기 위해 추가 DB 호출을 수행 할 수 있습니다.

당신이 말했듯이 해결책 중 하나는 완전히로드 된 객체를 반환하지 않는 것이므로이 잠재적 인 문제점을 알고있을 것입니다. 행 랩퍼를 사용하지 않으려하는 이유 중 하나는 응용 프로그램을 조정하고 데이터베이스 트래픽의 크기와 빈도를 최소화하는 것을 어렵게 만드는 것입니다.

0

datay retrieval 레이어에서 표준 디자인 패턴은 모두 하나의 블록 크기에 대해 하나씩 두 개의 메소드 인터페이스를 갖는 것입니다.

원하는 경우 페이징하는 구성 요소를 레이어 할 수 있습니다.