2014-04-14 8 views
8

Talend를 사용하여 SQL Server 데이터베이스에 데이터를로드합니다.talend 및 sql 서버로 데이터를 빠르게로드하는 방법

내 작업의 가장 약한 점은 데이터 처리가 아니라 내 데이터베이스의 유효로드가 17 줄/초보다 빠르다는 것입니다.

재미있는 점은 같은 시간에 5 개의 작업을 시작할 수 있으며 17rows/초로 모두로드된다는 것입니다.

이 속도가 어떻게 느려지는지 설명하고 속도를 어떻게 향상시킬 수 있습니까?

감사

새로운 정보 :

내 데스크톱 및 서버 사이의 전송 속도는 1MByte가에 관한은

내 작업은 매 10 000

내가 SQL 서버를 사용 범 2008 R2

D 나는 내 작업에 사용하는 스키마는 다음과 같이이다 :이 성능 문제가 양식을 어디서 왔는지 내가 찾은

enter image description here

+2

Talend에 "대량로드", "대량 삽입"또는 "대량 복사"기능이 있습니까? – RBarryYoung

+0

그리고 하드웨어를 확인하십시오. 단일 스레드 SQL 문에 대해서조차도 불쌍합니다. 어쩌면 서버가 휴대 전화 나 노트북과 같을 수도 있습니다. 앱과 서버 사이의 대기 시간은 얼마입니까? – TomTom

+0

느려짐은 talend와 DB 사이의 네트워크 속도, talend에서 쓰는 작업 방식, talend에 SQL Server의 대량로드 구성 요소가있는 것과 같은 요인으로 인해 발생할 수 있지만 일반적인 SQL Server 구성 요소의 경우 성능은 매우 좋지 않습니다 . 나는 당신이 실행중인 SQL과 같은 세부 사항을 언급 할 것을 제안한다. 어떤 종류의 처리가 talend 측면에서 수행되고 있는가, 어떤 talend 구성 요소를 사용하고 있는가 등을 말하면된다. – garpitmzn

답변

0

.

나는 INSERT OR UPDATE을 사용하고, 간단한 INSERT으로 바꾸면 4000 행/초까지 올라갑니다.

허용되는 속도로 보입니까?

어쨌든, 내 INSERT OR UPDATE이 필요하므로 붙어 있습니다.

+1

나는 Talend에 익숙하지 않지만 두 개의 별도 INSERT/단계/작업을 업데이트 하시겠습니까? 하나는 전체적으로 삽입 작업을 수행하는 작업이고 다른 하나는 업데이트를 수행하는 작업입니다 (업데이트를 미리 확인한 레코드의 경우) –

+0

"중복 키 또는 고유 인덱스에 대한 삽입 또는 업데이트"는 어떻게 사용합니까? 이것은 MySQL 명령 INSERT ... ON DUPLICATE KEY INSERT를 실행합니다. 불행히도이 작업을 한 번에 두 개 이상의 행에서 작동하도록하는 방법을 찾지 못했지만 적어도 읽지 않아도되므로 "삽입 또는 업데이트"보다 훨씬 빠르게 실행해야합니다. – fool4jesus

13

데이터베이스 INSERT OR UPDATE 데이터베이스는 모든 커밋을 한꺼번에 일괄 처리 할 수 ​​없기 때문에 엄청나게 비용이 많이 들며 한 줄씩 처리해야합니다 (ACID 트랜잭션은 삽입을 시도한 다음 모두 실패한 경우 ACID 트랜잭션을 사용합니다). 이 커밋의 다른 레코드도 실패합니다).

대용량 대량 작업의 경우 커밋을 데이터베이스에 전달한 다음 데이터베이스에 2 개의 트랜잭션을 보내기 전에 레코드를 삽입하거나 업데이트할지 여부를 항상 미리 결정하는 것이 가장 좋습니다.

이 기능이 필요한 일반적인 작업은 INSERT OR UPDATEd 인 데이터를 조합 한 다음 데이터베이스 테이블에 기존 기본 키를 쿼리합니다. 기본 키가 이미 존재하면 UPDATE으로 보낼 수 있습니다. 그렇지 않으면 INSERT입니다. 이 논리는 tMap 구성 요소에서 쉽게 수행 할 수 있습니다.이 작업에서

Insert or Update Job Example

우리는 몇 가지 기존 데이터를 포함하는 우리가 데이터베이스 테이블에 INSERT OR UPDATE하고자 일부 데이터를 가지고 :

Initially loaded data

을 그리고 우리는 다음과 같은 데이터를 추가 할 그것에 :

Insert or Update data

작업은 새로운 데이터를 tHashOutput 구성 요소에 던져서 작동하여 동일한 작업에서 여러 번 사용할 수 있습니다 (단순히 메모리에 저장하거나 큰 인스턴스에서는 디스크에 캐시 할 수 있음).

이 데이터를이어서 tHashInput 구성 요소에서 읽고 tMap으로 직접 읽습니다. 또 다른 tHashInput 구성 요소는 테이블에 대해 매개 변수화 쿼리를 실행하기 위해 사용됩니다 : 당신은 유용한 this guide to Talend and parameterised queries을 찾을 수

Parameterised Query Parameter Config

. 여기에서 반환 된 레코드 (따라서 데이터베이스 내부의 레코드 만)가 tMap에 대한 조회로 사용됩니다.

tMap configuration

이러한 출력은 단지 UPDATEtMySQLOutput 성분을 분리하는 흐름 :

다음 삽입 할 INNER JOIN에서 불량품 UPDATED을해야하는 레코드를 발견하기 INNER JOIN로 구성된 또는 필요에 따라 INSERT. 마지막으로 주 하위 작업이 완료되면 commit 변경됩니다.

+0

고마워, 나는 그것을 조사하고 나의 해결책 (그리고 시간 결과)을 가지고 돌아올 것이다 – Krowar

+0

나는 그것이 어떻게 행해질지를 보여줄 수있는 빠른 일자리를 만들고있다. 도움이 될 수 있도록 스크린 샷을 업로드하려고합니다. – ydaetskcoR

+0

이 직업은 좋아 보이지만 스테이징 테이블을 사용하면 생각했던 것과 똑같이 할 수 있습니다. 내 대답을 확인해. –

0

인서트는 업데이트보다 빠르게 처리됩니다 (4000 대 17 초). DB 인덱스를 살펴 봐야 할 것처럼 보입니다. 업데이트 매개 변수와 일치하는 인덱스를 추가하면 업데이트 속도가 크게 빨라질 수 있습니다. 물론이 인덱스는 삽입 속도를 느리게 할 수 있습니다.

업데이트 쿼리의 쿼리 실행 계획을보고 인덱스를 사용 중인지 확인할 수도 있습니다. How do I obtain a Query Execution Plan?

+1

UPSERTS를 대량으로 설치할 수없는 실제 문제. 따라서 한 번에 1 행을 삽입/업데이트해야합니다. –

+1

참. 그러나 17/초의 업데이트 성능 자체는 복잡성을 증가시키지 않으면 서 올바른 색인으로 쉽게 증가시킬 수 있습니다. – user1452132

0

행을 삽입하는 준비 테이블을 작성해야합니다.

이 준비 테이블을 기반으로 t * SQLrow를 사용하여 DELETE 쿼리를 수행합니다.

DELETE FROM target_table 
WHERE target_table.id IN (SELECT id FROM staging_table); 

그래서 업데이트하려는 행이 더 이상 존재하지 않습니다.

INSERT INTO target_table 
SELECT * FROM staging_table; 

이렇게하면 모든 새 행/수정 된 행이 이동합니다.

+2

좋은 생각이지만이 방법으로 ACID 트랜잭션을 잃게됩니다. 행을 삭제 한 후 어떤 이유로 든 업무가 실패하면 어떻게됩니까? 이 작업을하기 위해서는 삽입 작업을하기 전에 반드시 삭제 작업을 커밋해야 작업 실패를 롤백 할 수 없습니다. 이것에 대해 신경 쓰지 않는다면 그것은 더 간단합니다. 나는 이것을 더 잘하는 방법이라고 생각합니다. 그러나 나는 항상 이런 식으로 ACID 트랜잭션을 원할 것입니다. – ydaetskcoR

+0

oracle을 사용하면 merge를 사용할 수 있습니다. http://psoug.org/reference/merge.html –

3

@ydaetskcoR의 대답은 디오 메트릭 관점 (삽입을 필요로하는 행을 업데이트해야 함)으로 완벽하고 작은 데이터 집합 (수천 행)에 유용한 작업 ETL 솔루션을 제공한다고 생각합니다.

Talend 시스템과 DB 서버간에 모든 데이터가 이동하기 때문에 행을 업데이트해야하는지 결정할 수있는 조회를 수행하는 데 비용이 많이 듭니다.

ETL에서 ELT로 전달해야하는 레코드가 수십만 개 또는 수백만 개에 이르면 @Balazs Gunics에서 제안한대로 임시 (준비) 테이블에 데이터를로드 한 다음 SQL을 사용하여 그것을 조작하십시오.

이 경우 데이터를로드 한 후 (대량로드 구성 요소를 사용하는 경우 INSERT = 빠름, 더 빨라짐) 임시 테이블과 대상 테이블간에 LEFT OUTER JOIN을 실행하여 이미있는 행을 나눕니다) 및 기타. 이 빠른 ETL 이상의 크기 순서가 될 것

SELECT staging.* FROM staging 
LEFT OUTER JOIN destination ON (destination.PK = staging.PK) 
WHERE destination.PK IS NOT NULL 

: 업데이트 할 필요가

SELECT staging.* FROM staging 
LEFT OUTER JOIN destination ON (destination.PK = staging.PK) 
WHERE destination.PK IS NULL 

이 다른 하나의 행을 :

이 쿼리는 당신에게 당신이 삽입해야 행을 줄 것이다 하지만 SQL을 사용하여 데이터를 조작해야합니다. ETL에서는 Java를 모두 사용할 수 있기 때문에 Talend 서버로 데이터를 가져옵니다. 따라서 로컬 시스템에서 Java의 데이터를 사전 처리하는 첫 번째 단계가 자주 있습니다. (그것을 청소하고 유효성을 검사하기 위해) 그리고 나서 그것을로드하기 위해 join을 사용하는 DB에서 실행 시켜라. 옳은 길.

다음은 ELT JOB 스크린 샷입니다. INSERT or UPDATE ELT job

How to distinguish between rows to insert or update

0

나는 DB2 서버에 동일한 문제가 로딩 데이터를 가지고 있었다 . 나도 커밋을 10000으로 설정했지만 동일한 구성 요소 옵션 화면에서 일괄 처리 옵션을 선택하면 성능이 크게 향상되었습니다. 커밋과 일괄 처리를 20000으로 옮기면 작업이 5 시간에서 2 분으로 단축되었습니다.