2013-02-26 7 views
2

집계 함수가 SQL 데이터베이스 (예 : Oracle 또는 SQL Server)에 구현 된 방법을 알 수 있습니다.SQL 집계 함수는 어떻게 작동합니까?

이 데이터베이스는 select 절에 집계 함수가있을 때 내부 데이터 구조 나 알고리즘을 사용합니다.

Java ArrayList에 100,000 개의 레코드가 있고 모든 값의 합계를 시도 할 때 약 1 분이 걸리지 만 동일한 100,000 개의 레코드가 DB에 저장되어 있고 합계를 사용하기 때문에이 질문을하는 이유는 (column_nm) 거의 1/4의 시간에 실행됩니다.

비슷한 방식으로 내 Java 코드 성능을 향상시키고 싶습니다. SQL 집계 함수 내부를 알고 싶습니다.

감사합니다. 당신이 작업의 복잡성에 대해 얘기하는 경우 (이것은 거의 항상 O입니다,

+0

ArrayList의 백만 레코드까지 합산하는 데 1 분은 _horribly_ slow로 들립니다. 먼저 데이터베이스에서 모든 레코드를 가져 오는 데 걸리는 시간을 포함합니까? –

+0

그건 백만 건이 아니라 십만 (1 lakh) 기록입니다. – minopret

+0

죄송합니다. 10,00,000 개의 레코드를 의미하고 DB 작업이 없지만 중간에 다른 메모리 작업이 하나 있습니다. – ABose

답변

0

집계는 일반적으로 단지 결과 집합을 반복하고는 집계를 수행, 그것은 합계, 평균인지, 또는 계산 n) 여기서 n은 단순 집계의 결과 집합에있는 레코드 수입니다.

Java에서 RDBMS처럼 디스크에서 읽는 것보다 빠른 것이 주 메모리로 인스턴스화되기 때문에 왜 그렇게 오래 걸릴지 모르겠다. 솔직히 RDBMS의 집계는 arraylist 집계보다 약간 느려야합니다.

확장하려면 특정 항목 (PK 또는 색인 포함)에 대해 하나의 행을 원하는 경우 arraylist의 경우 O (1)이고 적절한 색인이있는 RDBMS의 경우 O (1)가됩니다. 표준 연결 목록의 경우 해당 행을 가져 오는 것은 o (n)이지만 집계의 경우 arraylist와 동일합니다. 전체 데이터 집합 (배열 또는 테이블 일 수 있음)을 반복하고 집계를 수행하는 것은 거의 항상 O (n)입니다.

2

내부적으로 정의 된 집계 방식과 정확히 일치하지는 않지만 SQL Server에서는 user-defined aggregates을 만들 수 있습니다. 그러한 집계를 정의해야하는 어떤 방법을 볼 유익 할 수

  • Init :

쿼리 프로세서 응집의 연산을 초기화하는데 이러한 방법을 사용한다. 이 메서드는 쿼리 프로세서에서 집계하는 각 그룹에 대해 한 번 호출됩니다. 쿼리 프로세서는 여러 그룹의 집계를 계산하기 위해 집계 클래스의 동일한 인스턴스를 다시 사용하도록 선택할 수 있습니다. Init 메서드는이 인스턴스의 이전 사용에서 필요에 따라 정리 작업을 수행하고 새 집계 계산을 다시 시작할 수 있도록해야합니다.

  • Accumulate

    는 :

... 쿼리 프로세서 집계 값을 축적하는이 방법을 사용한다. 집계중인 그룹의 각 값에 대해 한 번 호출됩니다. 쿼리 프로세서는 항상 집계 클래스의 지정된 인스턴스에서 Init 메서드를 호출 한 후에 만이 메서드를 호출합니다. 이 메소드의 구현은 건네지는 인수의 값의 누적을 반영하도록 (듯이) 인스턴스의 상태를 갱신 할 필요가 있습니다.

  • Merge이 :

이 방법은 현재 인스턴스와이 집계 클래스의 다른 인스턴스를 병합 할 수 있습니다. 쿼리 프로세서는이 메서드를 사용하여 집계의 여러 부분 계산을 병합합니다.

  • Terminate

    :

이 방법은 상기 집합 연산을 완료 한 집계 결과를 반환한다. ... MergeTerminate의 설명에서

, 우리는 서버가 병렬로 하나의 그룹 내에서 여러 부분 집계를 수행 할 수 있음을 추론 할 수있다. 이러한 병렬 누적이 각각 발생하면 클래스의 한 인스턴스에서 Terminate에 대한 최종 호출이 최종 집계 결과를 생성하기 전에 모든 결과가 Merge d가됩니다.

따라서 가능한 한 빠른 속도를 달성하는 한 가지 분명한 방법은 누적 단계를 병렬 처리하는 것입니다.

1

성능 차이는 단순히 SUM을 계산하기 때문에 모든 데이터를 동시에 메모리에 저장할 필요가 없다는 것입니다.

SUM을 데이터베이스에 직접 요청하는 쿼리를 실행하면 디스크의 각 레코드를 읽고 메모리의 단일 변수에 누적 합계를 기록한 다음 다음 레코드를 읽을 수 있습니다. 동시에 메모리에 기록하십시오. 더 중요한 것은 네트워크를 통해 레코드를 다른 서버로 보내 처리 할 필요가 없기 때문에 결과 SUM을 끝에 단일 숫자로 보내면됩니다.

또한 전체적으로 SUM이 전체의 다른 하위 집합의 SUM과 같기 때문에 SUM을 병렬 처리 할 수 ​​있습니다. 데이터가 파티셔닝되면 데이터베이스가 여러 세션을 실행하여 여러 세션을 실행하고 각각이 데이터의 일부를 SUM하면 제어 세션이 각 파티션의 결과를 SUM으로 간단하게 합칠 수 있습니다.

배열을 사용하여 Java 프로그램에서 합계를 계산할 때 먼저 데이터베이스에 필요한 모든 데이터를 요청하는 쿼리를 실행해야합니다. 모든 데이터를 데이터베이스에서 앱 서버로 전송해야하며, 모든 데이터를 저장하기 위해 메모리를 할당해야합니다. 그 후에야 프로그램이 메모리에서 Array를 반복하고 Sum을 계산합니다. 그런 다음 아마 배열을 메모리에서 할당 해제해야합니다.

데이터 양이 적 으면 성능 차이가 미미할 것입니다. 그러나 볼륨이 크면 차이가 매우 클 것으로 예상 될 수 있습니다.

0

흥미로운 질문입니다.

잘 쓰여진 rdbms는 phd 수학자와 데이터베이스 전문가의 수천 시간의 노동 시간을 완성합니다. MSSQL 또는 postgressql의 성능을 모방하려는 시도는 훌륭하지만 풍차에서 기울어 져 있습니다 (don quixote에 익숙하지 않은 경우 쓸데없는 읽기).

rdbms와의 일반적인 오해는 관계형이란 관련 테이블을 의미한다는 것입니다. 관련성은 실제로 수학적 관계를 나타냅니다. 기본적으로 - rdbms는 집합 이론에 중점을 둡니다. 훌륭한 rdbms가 있더라도 개발자는 고유 한 네이티브 집합을 사용하는 대신 행 단위로 계산하여 성능을 저하시킬 수 있습니다. 이는 실제로 경험하고있는 성능 차이를 비교하는 적절한 방법입니다.

db 대신 java에서이 계산을 수행하는 경우 데이터 구조 (최소 데이터 유형)와 루프 효율성을 최적화해야합니다. 당신은 여전히 ​​SQL 서버 나 포스트그레스와 경쟁 할 수 없을 것입니다. db에 항목을 저장하고 개선 된 성능이 정말로 필요하면 java에서 호출하는 것이 좋습니다.

2

자바 코드를 훨씬 느린 이유는 매우 간단 설명,있다 : 당신은 ArrayList에를 사용하는

, 따라서 나는 당신이 거기에 정수 - 객체를 가하고 있습니다, 가정가. 그것들은 일부 스택에서 C의 int보다 중요한 오버 헤드가 있습니다. 두 번째로 합산하면 각 부분 합계에 대해 다른 정수가 만들어 지므로 GarbageCollector가 모든 성능을 사용합니다.

다른 답변에 명시된 바와 같이

,

  1. DB 그냥 레지스터의 int를 추가하기 위해 직접 수학 프로세서 액세스를 사용합니다은 - 더 빨리 할 수 ​​없습니다.
  2. 좋은 DB는 반복하지 않고 합계, 최소 또는 최대와 같은 집계를 map + reduce합니다. 따라서 멀티 프로세서의 보너스를 얻고 거의 I/O 대기 시간을 무시합니다.

당신이 코드를 해결하려면 : 사용하는 int []

int[] parts; 
sum=0; 
for (int i:parts) { 
    sum+=i; 
} 

당신은 분할 (매핑) 배열 프로세서의 수를 따라하는 경우, 테스트 및 향후이이 parallize 할 수 있습니다 유용함 - 데이터 크기에 따라 다릅니다.

관련 문제