정렬-병합
Sort-merge joinsort-merge join(머지 조인이라고도 함)은 조인 알고리즘으로 관계형 데이터베이스 관리 시스템의 구현에 사용됩니다.
Join 알고리즘의 기본적인 문제는 Join Atribute의 개별 값에 대해 해당 값을 표시하는 각 관계에서 튜플 세트를 찾는 것입니다.sort-merge 알고리즘의 주요 아이디어는 먼저 결합 속성을 기준으로 관계를 정렬하여 인터리브된 선형 스캔이 이러한 세트를 동시에 발견하도록 하는 것입니다.
실제로 정렬-머지 결합을 실행할 때 가장 비용이 많이 드는 부분은 알고리즘에 대한 양쪽 입력이 정렬된 순서로 제시되도록 배치하는 것입니다.이는 명시적 정렬 작업(대개 외부 정렬)을 통해 수행되거나 조인 관계 중 하나 또는 둘 다에 있는 기존 순서를 활용하여 수행될 수 있습니다.결합에 대한 입력이 트리 기반 인덱스, 다른 병합 결합 또는 적절한 키로 정렬된 출력을 생성하는 다른 계획 연산자의 인덱스 스캔에 의해 생성될 수 있기 때문에 대상 순서라고 불리는 후자의 조건이 발생할 수 있습니다.대상 순서는 우연일 필요는 없습니다.옵티마이저는 1개 또는 여러 다운스트림노드가 이용할 수 있는 흥미로운 순서를 산출하는 경우 이 가능성을 찾아 특정 이전 작업에 적합하지 않은 계획을 선택할 수 있습니다.
를 들어, 페이지 와 의 R\displaystyle Sdisplaystyle R R\displaystyle S\displaystyle의 2가지 가 있다고 합시다.따라서 최악의 경우 정렬-머지 결합은 Or + { O I/O로 됩니다.R R과 S S의 순서가 없는 최악의 경우 시간 비용에는 Or + s + log ( r )+ s log ( P) { O{의 추가 정렬 시간이 포함됩니다. 즉 O r log ( r)+ log ( O}+와 . (직선형 항이 선형 항보다 크므로 빅 O 표기법 – 공통 함수 순서 참조).
유사 코드
단순하게 하기 위해 알고리즘은 단일 Atribute 상에서 2개의 관계가 내부 결합되어 있는 경우에 설명됩니다.다른 결합 유형, 더 많은 관계 및 더 많은 키로 일반화하는 것은 간단합니다.
함수 sortMerge(관계 왼쪽, 관계 오른쪽, 속성 a) var relation 출력 var list left_relation list left_sort(왼쪽, a) // var attribute left_key, right_key var set_set_right, right_right_s/ 이러한 집합은 조인 술어가 충족되지 않는 한 경우에만 폐기됩니다.advanced(left_key, left_key, a) advanced(right_key, a) advanced(right_key, a) left_key = right_key // join 술어가 충족되면 left_key 및 right_key 출력에 데카르트 곱을 추가합니다(_key, left_key, right_key, ref).t_key, a) advanced(right_key, right_key, right_key, a) else(left_key advanced(left_key, left_key, left_key, a) else(right_key > right_key advanced, right_key, a) 출력 반환
// 정렬된 [1]까지 정렬된 항목에서 하위 집합으로 튜플을 제거합니다. 값이 함수 변경(삭제, 정렬된 입력, 키 출력) 키 := 정렬된 항목 [1].하위 집합 := 비어 있습니다.비어 있지 않을 때 설정(정렬됨) 및 정렬됨[1].a = 키 삽입 정렬됨[1] 하위 집합으로 제거[1]
C#의 심플한 실장
이 실장에서는 Join Atribute가 고유하다고 가정하고 있습니다.즉, 키의 특정 값에 대해 여러 개의 튜플을 출력할 필요가 없습니다.
일반의 학급 결합 { // 왼쪽과 오른쪽이 이미 정렬되어 있다고 가정합니다. 일반의 정적인 관계. 머지(관계. 왼쪽, 관계. 맞다) { 관계. 산출량 = 신규 관계.(); 하는 동안에 (!왼쪽.IsPastEnd() & & !맞다.IsPastEnd()) { 한다면 (왼쪽.열쇠 == 맞다.열쇠) { 산출량.더하다(왼쪽.열쇠); 왼쪽.발전(); 맞다.발전(); } 또 다른 한다면 (왼쪽.열쇠 < > 맞다.열쇠) 왼쪽.발전(); 또 다른 // if (왼쪽).키 > 오른쪽.키) 맞다.발전(); } 돌아가다 산출량; } } 일반의 학급 관계. { 사적인 목록.< >인트> 목록.; 일반의 컨스턴트 인트 엔드포스 = -1; 일반의 인트 위치 = 0; 일반의 인트 위치 { 얻다 { 돌아가다 위치; } } 일반의 인트 열쇠 { 얻다 { 돌아가다 목록.[위치]; } } 일반의 부울 발전() { 한다면 (위치 == 목록..세어보세요 - 1 위치 == 엔드포스) { 위치 = 엔드포스; 돌아가다 거짓의; } 위치++; 돌아가다 진실의; } 일반의 무효 더하다(인트 열쇠) { 목록..더하다(열쇠); } 일반의 부울 IsPastEnd() { 돌아가다 위치 == 엔드포스; } 일반의 무효 인쇄() { 앞지르다 (인트 열쇠 에 목록.) 콘솔.기입선(열쇠); } 일반의 관계.(목록.< >인트> 목록.) { 이것..목록. = 목록.; } 일반의 관계.() { 이것..목록. = 신규 목록.< >인트> ( ) ; } }