外部システムからインタフェースされた大量データなどをDBのテーブルに一括ロードする場合、 BULK INSERT や、 SSIS を使用したバッチインサートを使用すると高速に処理できます。今回は細かい制御や条件、エラー処理用件があり手作業でデータインポートすることになった際、テーブルロックが効果があったため覚書として記載します。

ここで紹介する方法は当然サーバのスペックや環境によって変化します。

1. テーブルロックを使用した処理のテンプレート

テーブルロックを取得してデータを登録する処理のテンプレートを記載します。

DbConnection cn = new DbConnection();
cn.Open();
cn.BeginTransaction();
string sql = " SELECT TOP 1 *  FROM dbo.SampleTable WITH(TABLOCKX , HOLDLOCK); ";

using (DbCommand cmd = CreateTextCommand(string.Format(sql, Context.CustomDB)))
{
    cmd.ExecuteNonQuery();
}
// データのロード処理
// .....
cn.Commit()

2. テーブルロックの効果

テーブルロックを使用した場合に100万件データをロードしたときの計測時間(分) を記載します。

ケース ロックなし ロックあり
テーブルの列数2 40 10
テーブルの列数10 40 10
テーブルの列数100 40 28

3. テーブルロックではなく、多重スレッドで登録処理を行った場合のパフォーマンス

多重スレッドでデータを振り分けてクエリを発行すると(当然スレッドごとにコネクションは独立しています)、シングルスレッドの場合と比べ処理時間に大きな変化はありませんでした。

INSERTによりプライマリキーのロックなどで多重呼び出しの効果がないのかもしれません。

4. まとめ

今回の説明は以上です。テーブルロックしてからひたすらインポートする場合、カラム数(1レコードのデータ数)が小さいほど効果が大きくなります。逆に列数が百列列以上などもある場合は効果はあまりありません。