48

Go の database/sql パッケージで sql ステートメントをバッチ処理するにはどうすればよいですか?

Javaでは、次のようにします:

// Create a prepared statement
String sql = "INSERT INTO my_table VALUES(?)";
PreparedStatement pstmt = connection.prepareStatement(sql);

// Insert 10 rows of data
for (int i=0; i<10; i++) {
    pstmt.setString(1, ""+i);
    pstmt.addBatch();
}

// Execute the batch
int [] updateCounts = pstmt.executeBatch();

Goで同じことをどのように達成できますか?

4

12 に答える 12

85

db.Exec関数はvariadicであるため、1 つのオプション (実際には 1 つのネットワーク ラウンドトリップのみを行う) は、自分でステートメントを作成し、引数を分解して渡すことです。

サンプルコード:

func BulkInsert(unsavedRows []*ExampleRowStruct) error {
    valueStrings := make([]string, 0, len(unsavedRows))
    valueArgs := make([]interface{}, 0, len(unsavedRows) * 3)
    for _, post := range unsavedRows {
        valueStrings = append(valueStrings, "(?, ?, ?)")
        valueArgs = append(valueArgs, post.Column1)
        valueArgs = append(valueArgs, post.Column2)
        valueArgs = append(valueArgs, post.Column3)
    }
    stmt := fmt.Sprintf("INSERT INTO my_sample_table (column1, column2, column3) VALUES %s", 
                        strings.Join(valueStrings, ","))
    _, err := db.Exec(stmt, valueArgs...)
    return err
}

私が実行した簡単なテストでは、このソリューションは、他の回答で提示された開始、準備、コミットよりも 10,000 行の挿入で約 4 倍高速ですが、実際の改善は個々のセットアップ、ネットワーク遅延などに大きく依存します。

于 2014-08-07T21:03:36.963 に答える
17

PostgreSQL を使用している場合、pqは一括インポートをサポートします。

于 2015-04-16T15:04:42.350 に答える
16

プレースホルダーをサポートしていない PostgreSQL にAndrew のソリューション?を適用すると、次のように動作します。

func BulkInsert(unsavedRows []*ExampleRowStruct) error {
    valueStrings := make([]string, 0, len(unsavedRows))
    valueArgs := make([]interface{}, 0, len(unsavedRows) * 3)
    i := 0
    for _, post := range unsavedRows {
        valueStrings = append(valueStrings, fmt.Sprintf("($%d, $%d, $%d)", i*3+1, i*3+2, i*3+3))
        valueArgs = append(valueArgs, post.Column1)
        valueArgs = append(valueArgs, post.Column2)
        valueArgs = append(valueArgs, post.Column3)
        i++
    }
    stmt := fmt.Sprintf("INSERT INTO my_sample_table (column1, column2, column3) VALUES %s", strings.Join(valueStrings, ","))
    _, err := db.Exec(stmt, valueArgs...)
    return err
}
于 2018-01-03T02:25:38.960 に答える
1

database/sql で利用可能なインターフェースを介してバッチ処理を行うことはできません。ただし、特定のデータベース ドライバが個別にサポートしている場合があります。たとえば、https://github.com/ziutek/mymysqlは MySQL でのバッチ処理をサポートしているようです。

于 2012-09-19T12:13:19.863 に答える
0

チェーン構文で見るもう1つの良いライブラリはgo-pg

https://github.com/go-pg/pg/wiki/Writing-Queries#insert

1 つのクエリで複数の書籍を挿入する:

err := db.Model(book1, book2).Insert()
于 2019-07-24T10:27:27.320 に答える