LoginSignup
2
1

More than 5 years have passed since last update.

MySQLへ大量データをloadするためのCSVライブラリの検討及び実装(Java)

Posted at

なぜこの記事を?

MySQLへ大量データをload data infileするために、件数多いCSVファイルを作りたかった。そこで調査した。

前提

アノテーションを付加したJavaオブジェクトを1件1件処理できるCSVライブラリのなかから選定。

結果

Maven Repository: com.orangesignal » orangesignal-csv » 2.2.1
Maven Repository: com.github.mygreen » super-csv-annotation » 2.2
Maven Repository: com.univocity » univocity-parsers » 2.8.1

このなかでは、Super CSV Annotationはかなり遅かった(他の約3倍の遅さ)。
OrangeSignal CSVが一番速かった。

エスケープ処理が不要なのであれば、エスケープ処理を省いたものを自作したのが一番速かった。
↓エスケープ処理をしない自作のCSVライブラリ。
NonEscapedCsvWriter/src/com/github/momosetkn/csv at master · momosetkn/NonEscapedCsvWriter

検証方法

10万件あるCSVを作成、データ量削減のため囲み文字は無し。カンマ区切り、ヘッダー有りという条件で作成。

実行環境

  • Ubuntu18.04LTS
  • Core i7-4770K
  • RAM12GB
  • 5年ぐらい前から使っててちょっと傷んでそうなSSD(330 Series SSDSC2CT120A3K5)
  • IntelilJ IDEA上で実行

検証コード(Github参照)

NonEscapedCsvWriter/src/csv/test at master · momosetkn/NonEscapedCsvWriter

書き込みデータ

booleanField,localDateField,localDateTimeField,bigDecimalField,stringField,integerField,longField
true,2018-12-25,2018-12-25T09:30:10,100000.000001,1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456,2147483647,9223372036854775807
true,2018-12-25,2018-12-25T09:30:10,100000.000001,1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456,2147483647,9223372036854775807
(データは全部同じのが10万件続く…)

結果

CSVライブラリ 処理時間
OrangeSignal CSV 451.670,801ms
エスケープ処理しない自作CSVライブラリ 389.026,236ms
SuperCsvAnnotation 1,488.254,510ms
univocity-parsers 523.735,942ms

うーん…データ編集処理はディスクアクセスに比べたらそんなに重くない処理で、
どのライブラリも桁違いレベルには変わらないだろうと思ってたんですが、
SuperCsvAnnotationは他のCSVライブラリの3倍の時間かかってる…。
なんでか気になるなあ…。

自作したエスケープ処理しないCSVライブラリの工夫した点

↓コード
NonEscapedCsvWriter/NonEscapedCsvWriter.java at master · momosetkn/NonEscapedCsvWriter

StringBuilderを使って文字列結合するようにした。
↓参考資料
【String型 vs StringBuilder】文字列結合における処理速度の違い - Qiita
Java で 文字列を生成する場合にどう書くのが速い? - Qiita

StringBuilderのcapacityを最初に指定できるようにした。
想定しているデータ量に応じてライブラリ使用者が設定できる。

マルチスレッド環境を想定していないため、同期化してない…。

高速化とは関係無いけど、文字列への変換ロジックをラムダで簡単に書けるようにした。

自作したエスケープ処理しないCSVライブラリの使い方

というかサンプルコード

try(NonEscapedCsvWriter<ExampleBean> exampleBeanCsvWriter = new NonEscapedCsvWriter<>(ExampleBean.class,
                Files.newBufferedWriter(new File("/home/momose/Documents/test1_p.csv").toPath(), Charsets.UTF_8))
.charsCapacity(334)
.convert((input)-> {//文字列への変換ロジック
    if (input instanceof LocalDateTime) {
        return ((LocalDateTime) input).format(dateTimeFormatter);
    } else if (input instanceof Boolean) {
        return Boolean.TRUE.equals(input) ? "1" : "0";
    } else if (input == null) {
        return "null";
    }
    return input.toString();
})){
    exampleBeanCsvWriter.init();
    for (int i = 0; i < MAX_RECORD_COUNT; i++) {
        ExampleBean exampleBean = new ExampleBean();
        //データ編集処理…
        exampleBeanCsvWriter.write(exampleBean);
    }
};

あとはこのコマンドで取り込む。

LOAD DATA INFILE 'example.csv' INTO TABLE scheme.table FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 LINES;
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1