성능 최적화 기술 : 순서대로 병합

1. 문제 배경 및 적용 가능한 시나리오

이전 기사에서 우리는 관계형 데이터베이스가 테이블 간의 연관을 수행 할 때 HASH 분할 기술을 사용한다고 소개했습니다. 두 연관 테이블의 스케일 (레코드 수)이 각각 N과 M이라고 가정 할 때 HASH 분할 기술의 계산 복잡도 (관련 필드의 비교 수)는 대략 SUM (Ni * Mi)입니다. 여기서 Ni 및 Mi는 각각 HASH 값입니다 .i의 두 테이블에있는 레코드 수, N = SUM (Ni) 및 M = SUM (Mi)를 충족하는 경우이 확률은 전체 순회 N *의 복잡성보다 훨씬 작습니다. M (행운을 통해 K 배 작아짐), K는 HASH 값의 범위).

두 테이블이 연관 키를위한 순서라면 병합 알고리즘을 사용하여 연관을 처리 할 수 ​​있습니다. 이때 복잡성은 N + M입니다 .N과 M이 모두 클 때 (일반적으로 K보다 훨씬 큽니다), 이 숫자는 지금 당장 SUM (Ni * Mi)보다 훨씬 작을 것입니다. 따라서 순차적 병합 연관의 계산 속도는 HASH 세그먼트 연관보다 훨씬 빠릅니다.

실제 응용 프로그램에서 동일한 차원 테이블과 기본 및 하위 테이블은 항상 기본 키 또는 기본 키의 일부와 관련되어 있으므로 이러한 관련 테이블의 데이터를 기본 키에 따라 미리 정렬 한 다음 항상 병합 알고리즘을 사용하여 연관성을 달성 할 수 있으므로 효율성을 크게 향상시킬 수 있습니다. SPL은 이러한 알고리즘을 사용합니다.

esProc SPL을 사용하여 관계형 데이터베이스 Oracle과 비교하여 질서있는 병합 연결의 효율성을 테스트 해 보겠습니다.

 

2. 테스트 환경

1. 작은 데이터 전체 메모리 테스트

테스트 머신에는 2.6G로 클럭 된 2 개의 Intel2670 CPU, 총 16 코어, 128G 메모리 및 SSD 솔리드 스테이트 드라이브가 있습니다.

TPCH 표준에 의해 생성 된 50G 데이터를 사용하여 메인 테이블은 주문이고 하위 테이블은 orderdetail (라인 항목 테이블의 데이터 레코드를 줄여 생성됨)입니다. 두 테이블의 레코드는 각각 O_ORDERKEY 및 L_ORDERKEY의 오름차순으로 정렬됩니다.

Oracle과 SPL은 모두 단일 스레드 테스트를 사용합니다.

2. 빅 데이터 외부 저장 테스트

앞서 언급 한 테스트 머신, 16G 메모리 및 SSD 솔리드 스테이트 하드 드라이브에서 가상 머신을 사용합니다.

TPCH 표준에서 생성 된 200G 데이터를 사용하여 메인 테이블은 주문이고 하위 테이블은 라인 항목입니다. 두 테이블의 레코드는 각각 O_ORDERKEY 및 L_ORDERKEY의 오름차순으로 정렬됩니다.

상대적으로 많은 양의 데이터로 인해 Oracle과 SPL은 모두 8 스레드 병렬 테스트를 사용합니다.

세, 작은 데이터 전체 메모리 테스트

1. Oracle 테스트

(1 ) 상관 관계 검정 없음

테스트 된 SQL 문은 다음과 같습니다.

고르다

       l_year,

       합계 (볼륨)를 소득으로,

       sum (l_quantity) as 수량

...에서

       (

              고르다

                     추출 (l_shipdate에서 연도)을 l_year로,

                     (l_extendedprice * (1-l_discount)) 볼륨으로,

                     l_quantity

              ...에서

                     orderdetail

       )

그룹화

       l_year

모두 결합

고르다

       2019 년을 l_year로,

       (o_orderkey)를 소득으로 계산,

       수량으로 개수 (o_totalprice)

...에서

       명령;

 

(2 ) 관련 테스트

테스트 된 SQL 문은 다음과 같습니다.

고르다

       l_year,

       합계 (볼륨)를 소득으로,

       sum (l_quantity) as 수량

...에서

       (

              고르다

                     추출 (l_shipdate에서 연도)을 l_year로,

                     (l_extendedprice * (1-l_discount)) 볼륨으로,

                     l_quantity

              ...에서

                     명령,

                     orderdetail

              어디

                     o_orderkey = l_orderkey

                     및 l_quantity> 0

       )

그룹화

       l_year;

쿼리 조건 l_quantity> 0은 항상 true이며이 데이터 열을 읽을 수 있도록 필터링 데이터가 없습니다.

 

2. SPL 테스트

(1 ) 상관 관계 검정 없음

다음과 같이 SPL 스크립트를 작성하십시오.

bef4400cbc05de35bf684369d9db10ed.gif
1 > orders = file ( "/ home / ctx / orders.ctx"). create (). memory ()
2 > orderdetail = file ( "/ home / ctx / orderdetail.ctx"). create (). memory ()
= now ()
4 = orderdetail.cursor (L_ORDERKEY, L_EXTENDEDPRICE, L_DISCOUNT, L_SHIPDATE, L_QUANTITY) .groups (year (L_SHIPDATE) : l_year; sum (L_EXTENDEDPRICE * (1-L_DISCOUNT)) : revenue, sum (L_QUANTITY) : quantity)
5 = orders.groups (; count (O_ORDERKEY), count (O_TOTALPRICE))
6 = interval @ s (A3, now ())

 

(2 ) 관련 테스트

다음과 같이 SPL 스크립트를 작성하십시오.

bef4400cbc05de35bf684369d9db10ed.gif
1 > orders = file ( "/ home / ctx / orders.ctx"). create (). memory ()
2 > orderdetail = file ( "/ home / ctx / orderdetail.ctx"). create (). memory ()
= now ()
4 = orders.cursor (O_ORDERKEY, O_TOTALPRICE; O_TOTALPRICE> 0)
5 = orderdetail.cursor (L_ORDERKEY, L_EXTENDEDPRICE, L_DISCOUNT, L_SHIPDATE, L_QUANTITY)
6 = joinx (A5 : detail, L_ORDERKEY; A4 : 주문, O_ORDERKEY)
7

= A6.groups (year (detail.L_SHIPDATE) : l_year;

sum (detail.L_EXTENDEDPRICE * (1-detail.L_DISCOUNT)) : 수익, sum (detail.L_QUANTITY) : quantity)

8 = interval @ s (A3, now ())

A6의 joinx는 정렬 된 병합 연결 기능으로, 관련 필드를 오름차순으로 정렬해야합니다.

 

3. 테스트 결과 및 분석

테스트 결과 목록은 다음과 같습니다 (단위 : 초) :

범주 무관 관련 감속 배수 협회 시간
신탁 16 67 4.2 51
SPL 14 32 2.3 18

각 테스트 결과가 여러 번 실행되고 데이터가 완전히 캐시되면 가장 빠른 결과를 가져옵니다.

SQL의 두 문장을 분석합니다. 관련없는 테스트에서 orders 테이블의 O_ORDERKEY 및 O_TOTALPRICE 열을 읽고 레코드 수를 세고 orderdetail 테이블에서 L_ORDERKEY, L_EXTENDEDPRICE, L_DISCOUNT, L_SHIPDATE 및 L_QUANTITY의 5 개 열을 읽습니다. 판매 가격과 L_QUANTITY 합계를 더합니다. 상관 테스트에서 주문 및 주문 세부 정보 테이블의 읽기 볼륨은 동일하며 관련 판매 가격이 합산되고 L_QUANTITY가 합산됩니다. 두 경우의 읽기 및 계산량은 기본적으로 동일하며 추가 작업은 두 테이블 간의 연결이므로 두 테이블 간의 실행 시간 차이는 연결 작업 시간입니다. SPL도 마찬가지입니다.

동일한 하드웨어 장비 및 데이터 규모에서 SPL 연관은 18 초, Oracle 연관은 전자의 거의 3 배인 51 초가 소요되며 SPL은 Java로 작성된 프로그램이며 Oracle은 C ++로 구현되어 질서 성 병합 상관 관계를 완전히 검증합니다. 상관 관계의 효율성을 크게 향상시킬 수 있습니다. 상관 관계가있는 SPL의 속도는 상관 관계가 없을 때보 다 2.3 배 느리고 Oracle은 4.2 배 더 느려 순서화 된 병합 계산 속도가 일반 계산 속도와 같고 HASH 상관 관계가 일반 계산보다 훨씬 느립니다.

 

4. 빅 데이터 외부 저장 테스트

JOIN 할 두 테이블이 너무 커서 메모리에 맞지 않는 경우 관계형 데이터베이스는 여전히 HASH 분할 기술을 사용합니다. 관련 필드의 HASH 값에 따라 데이터는 여러 세그먼트로 나뉘며, 각 세그먼트는 메모리에로드 될 수있을만큼 작으며 메모리의 HASH 세그먼트 알고리즘을 구현합니다. 그러나 이로 인해 외부 메모리 전환 문제가 발생할 수 있습니다. 데이터를 세그먼트로 기록한 다음 읽어야합니다. 추가 데이터를 쓰고 다른 하나를 읽습니다. 외부 메모리 읽기는 본질적으로 빠르지 않고 쓰기 속도가 느립니다. , 따라서 성능이 훨씬 나빠질 것입니다.

순 서적 병합 연결에는이 문제가 없습니다. 두 테이블의 데이터는 한 번만 순회하면됩니다. CPU 계산량이 감소 할뿐만 아니라 외부 메모리 IO의 양도 크게 감소합니다. 또한 병합 알고리즘을 실행하는 데 필요한 메모리는 매우 적습니다. 메모리의 각 테이블에 대해 몇 개의 캐시 레코드가 유지되는 한 다른 동시 작업의 메모리 요구 사항에는 거의 영향을주지 않습니다.

 

1. Oracle 테스트

(1 ) 상관 관계 검정 없음

테스트 된 SQL 문은 작은 데이터 테스트와 동일합니다. orderdetail 테이블을 lineitem 테이블로 변경하고 8 개의 스레드를 병렬로 사용하려면 첫 번째 선택 후에 "/ * + parallel (8) * /"를 추가하면됩니다.

(2 ) 관련 테스트

테스트 된 SQL 문은 작은 데이터 테스트와 동일합니다. orderdetail 테이블을 lineitem 테이블로 변경하고 8 개의 스레드를 병렬로 사용하려면 첫 번째 선택 후에 "/ * + parallel (8) * /"를 추가하면됩니다.

 

2. SPL 테스트

(1 ) 상관 관계 검정 없음

다음과 같이 SPL 스크립트를 작성하십시오.

bef4400cbc05de35bf684369d9db10ed.gif
1 = now ()
2 = file ( "/ home / ctx / lineitem.ctx"). create (). cursor @ m (L_ORDERKEY, L_EXTENDEDPRICE, L_DISCOUNT, L_SHIPDATE, L_QUANTITY ;; 8)
= A2.groups (year (L_SHIPDATE) : l_year; sum (L_EXTENDEDPRICE * (1-L_DISCOUNT)) : revenue, sum (L_QUANTITY) : quantity)
4 = file ( "/ home / ctx / orders.ctx"). create (). cursor @ m (O_ORDERKEY, O_TOTALPRICE ;; 8)
5 = A4.total (count (O_ORDERKEY), count (O_TOTALPRICE))
6 = interval @ s (A1, now ())

데이터의 양이 많으며 A2와 A4는 모두 8 채널 병렬 커서 판독 값을 사용합니다.

 

(2 ) 관련 테스트

다음과 같이 SPL 스크립트를 작성하십시오.

bef4400cbc05de35bf684369d9db10ed.gif
1 = now ()
2 = file ( "/ home / ctx / orders.ctx"). create (). cursor @ m (O_ORDERKEY, O_TOTALPRICE; O_TOTALPRICE> 0; 8)
= file ( "/ home / ctx / lineitem.ctx"). create (). cursor (L_ORDERKEY, L_EXTENDEDPRICE, L_DISCOUNT, L_SHIPDATE, L_QUANTITY ;; A2)
4 = joinx (A3 : detail, L_ORDERKEY; A2 : 주문, O_ORDERKEY)
5 = A4.groups (year (detail.L_SHIPDATE) : l_year; sum (detail.L_EXTENDEDPRICE * (1-detail.L_DISCOUNT)) : revenue, sum (detail.L_QUANTITY) : quantity)
6 = interval @ s (A1, now ())

A2는 A3에서 커서를 생성 할 때 매개 변수로 사용됩니다. 즉, 기본 테이블 순서의 기본 키와 동시에 세그먼트에서 읽습니다.

A4의 joinx는 정렬 된 병합 연결 기능으로, 관련 필드를 오름차순으로 정렬해야합니다.

 

3. 테스트 결과 및 분석

테스트 결과 목록은 다음과 같습니다 (단위 : 초) :

범주 무관 관련 감속 배수 협회 시간
신탁 265 863 3.3 598
SPL 70 101 1.4 31

계산 분석 및 상관 시간 계산은 소규모 데이터 테스트와 동일합니다.

동일한 하드웨어 장비 및 데이터 규모에서 SPL 연결은 31 초가 걸리고 Oracle 연결은 598 초 (전자의 19 배)가 걸리므로 순서에 따른 병합 연결이 연결 효율성을 크게 향상시킬 수 있음을 추가로 확인합니다. 소규모 데이터 테스트와 비교하여 배수가 크게 증가하여 데이터 양이 많을수록 HASH 연결에 비해 질서있는 병합 연결의 성능 향상 이점이 더 분명함을 나타냅니다.

상관 관계가없는 것보다 느린 상관 관계 배수도 작은 데이터 테스트에서와 동일한 결론을 도출 할 수 있지만 작은 데이터 테스트에서보다 데이터를 읽는 데 더 많은 시간이 있습니다 (작은 데이터가있는 경우 데이터는 모두 메모리에 캐시됩니다. small), so no 상관 관계 검정의 시간축이 커졌고 소형 데이터 검정에 비해 감속 배수가 감소한 것으로 보입니다.


추천

출처blog.51cto.com/12749034/2602017