web-dev-qa-db-ja.com

talendとSQLサーバーでデータをより速くロードする方法

Talendを使用してデータをSQLServerデータベースにロードします。

私の仕事の最も弱い点はデータ処理ではなく、データベースの実効負荷であり、17行/秒より速くないようです。

面白い点は、5つのジョブを同時に起動でき、それらはすべて17行/秒で読み込まれることです。

この遅さを説明できるものと、速度を改善するにはどうすればよいですか?

ありがとう

新しい情報:

デスクトップとサーバー間の転送速度は約1Mバイトです

私の仕事は10000ごとにコミットします

SQL Server 2008R2を使用しています

そして、私の仕事に使用するスキーマは次のようなものです。

enter image description here

8
Krowar

データベースINSERT OR UPDATEメソッドは、データベースがすべてのコミットを一度にバッチ処理できず、行ごとに実行する必要があるため、非常にコストがかかります(ACIDトランザクションは、挿入を試みて失敗した場合、すべてのコミットを強制的に実行するためです。このコミットの他のレコードも失敗します)。

代わりに、大規模な一括操作の場合、データベースにコミットを渡してから2つのトランザクションをデータベースに送信する前に、レコードを挿入するか更新するかを事前に決定することが常に最善です。

この機能を必要とする一般的なジョブは、INSERT OR UPDATEdとなるデータをアセンブルしてから、データベーステーブルに既存の主キーを照会します。主キーがすでに存在する場合は、これをUPDATEとして送信できます。それ以外の場合は、INSERTです。このためのロジックは、tMapコンポーネントで簡単に実行できます。

Insert or Update Job Example

このジョブでは、既存のデータを含むデータベーステーブルにINSERT OR UPDATEしたいデータがいくつかあります。

Initially loaded data

そして、それに次のデータを追加したいと思います。

Insert or Update data

このジョブは、新しいデータをtHashOutputコンポーネントにスローすることで機能するため、同じジョブで複数回使用できます(単にメモリに配置するか、大規模なインスタンスではディスクにキャッシュできます)。

これに続いて、1ロットのデータがtHashInputコンポーネントから読み取られ、直接tMapに読み込まれます。別のtHashInputコンポーネントを使用して、テーブルに対してパラメーター化されたクエリを実行します。

Parameterised QueryParameter Config

Talendおよびパラメーター化されたクエリに関するこのガイド が役立つ場合があります。ここから、返されたレコード(つまり、データベース内のレコードのみ)がtMapへのルックアップとして使用されます。

次に、これはINNER JOINとして構成され、挿入するINNER JOINからの拒否を含むUPDATEDである必要があるレコードを検索します。

tMap configuration

これらの出力は、必要に応じてtMySQLOutputコンポーネントをUPDATEまたはINSERTに分離するために流れます。そして最後に、メインサブジョブが完了すると、変更をcommitします。

15
ydaetskcoR

@ydaetskcoRの答えは、理論的な観点(Insertが必要な行をそれらからUpdateに分割する)で完璧であり、小さなデータセット(数千行)に役立つ実用的なETLソリューションを提供すると思います。

すべてのデータがTalendマシンとDBサーバーの間を行き来するため、ETLでは、行を更新する必要があるかどうかを判断できるようにルックアップを実行するのはコストがかかります。

ETLからELTに渡す必要のあるレコードが数十万または数百万に達した場合、@ Balazs Gunicsから提案されているように、データを一時(ステージング)テーブルにロードし、SQLを使用して操作します。

この場合、データをロードした後(INSERT = fastのみ、BULK LOADコンポーネントを使用するとさらに高速)、一時テーブルと宛先テーブルの間にLEFT OUTER JOINを発行して、すでに存在する行(更新が必要)と他の行を分割します。 。

このクエリは、挿入する必要のある行を提供します。

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

これは、更新する必要のある行です。

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

これはETLよりも桁違いに高速ですが、データを操作するにはSQLを使用する必要がありますが、ETLではJavaを使用できます。すべてのデータがTalendサーバーに取り込まれるため、多くの場合、ローカルマシンでデータを前処理してJava(データをクリーンアップおよび検証するため))、joinを使用してデータをロードするDBで起動する最初のステップが一般的です。正しい方法で。

これがELTJOBのスクリーンショットです。 INSERT or UPDATE ELT job

How to distinguish between rows to insert or update

4
RobMcZag

行を挿入するステージングテーブルを実行する必要があります。

このステージングテーブルに基づいて、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;

これにより、すべての新規/変更された行が移動します。

0
Balazs Gunics

DB2サーバーへのデータのロードでも同じ問題が発生していました。私もコミットを10000に設定しましたが、(同じコンポーネントオプション画面で)バッチするオプションを選択すると、パフォーマンスが劇的に向上しました。コミットとバッチを20000に移動すると、ジョブは5時間から2分未満になりました。

0
dwberry

このパフォーマンスの問題がどこから発生するのかを見つけました。

INSERT OR UPDATEを実行しますが、単純なINSERTに置き換えると、速度は最大4000行/秒になります。

許容できるペースのように見えますか?

とにかく、私はINSERT OR UPDATEが必要なので、行き詰まっていると思います。

0
Krowar

同じ問題が発生し、ターゲットテーブルにインデックスを定義することで解決しました。

通常、ターゲットテーブルには、主キーであるためインデックスが付けられたidフィールドがあります。したがって、それとのあらゆる種類の結合は問題なく機能します。ただし、フラットファイルからの更新は一部のデータフィールドによって行われるため、各更新ステートメントは全表スキャンを実行する必要があります。

上記は、INSERTで高速に動作し、INSERT OR UPDATEで低速になる理由も説明しています。

0
jutky

いくつかの簡単なことをお勧めします:

  1. 可能/合理的な場合は、ETLからELTに変更します。
  2. CDCプロセスを設定し、変更のみを処理します。データベースとニーズに応じて、これは(a)データベース上で直接、(b)自動化されたTalend機能(サブスクリプションが必要)を介して、(c)SQL(完全外部結合)およびカスタムJava MD5ハッシュを生成する関数、または(d)SQL(完全外部結合)およびtAddCRCRowコンポーネントを介して手動で。
  3. 可能な場合は、複数のテーブルを同時にロードします。
  4. 可能な場合は、テーブルに一括読み込みを使用してください。
  5. 場合によっては、クリアとロードがアプローチとして受け入れられ、更新をチェックするよりも高速です。
0
David Cohn

挿入は更新よりも桁違いに速いというメモに基づくと(4000対17 /秒)-DBインデックスを確認する必要があるようです。更新パラメータに一致するインデックスを追加すると、更新が大幅に高速化される可能性があります。もちろん、このインデックスは挿入を少し遅くする可能性があります。

更新クエリのクエリ実行プランを調べて、インデックスを使用しているかどうかを確認することもできます。 クエリ実行プランを取得するにはどうすればよいですか?

0
user1452132