Mysql
 sql >> Database >  >> RDS >> Mysql

Inserisci batch con tabella che ha molte colonne usando Anorm

Andrò con l'opzione B. Non ho molta familiarità con BatchSql dall'ultima volta che ho controllato, esegue solo un carico di query in sequenza, il che è terribilmente lento. Consiglierei di aggregare tutto in una singola query. È un po' più noioso, ma molto più veloce eseguire una singola query con mille inserimenti rispetto a mille singoli inserimenti.

Per comodità, supponiamo che tu abbia Seq di

case class Test(val1: Int, val2: Option[Long], val3: Option[String])

Quindi potresti creare la tua query in questo modo:

val values: Seq[Test] = Seq(....)

/* Index your sequence for later, to map to inserts and parameters alike */
val indexedValues = values.zipWithIndex

/* Create the portion of the insert statement with placeholders, each with a unique index */
val rows = indexValues.map{ case (value, i) =>
    s"({val1_${i}}, {val2_${i}}, {val3_${i}})"
}.mkString(",")

/* Create the NamedParameters for each `value` in the sequence, each with their unique index in the token, and flatten them together */
val parameters = indexedValues.flatMap{ case(value, i) =>
    Seq(
        NamedParameter(s"val1_${i}" -> value.val1),
        NamedParameter(s"val2_${i}" -> value.val2),
        NamedParameter(s"val3_${i}" -> value.val3)
    ) 
}

/* Execute the insert statement, applying the aggregated parameters */
SQL("INSERT INTO table1 (col1, col2, col3) VALUES " + rows)
    .on(parameters: _ *)
    .executeInsert()

Note:

Dovrai controllare quei values non è vuoto prima di procedere, in quanto genererebbe un'istruzione SQL non valida se lo fosse.

A seconda di quante righe e colonne stai inserendo, alla fine i parser di token che hanno creato l'istruzione preparata rallenteranno dall'enorme quantità di token da analizzare (e dalla dimensione della stringa). L'ho notato dopo alcune centinaia di righe con diverse colonne. Questo può essere in qualche modo mitigato. Grazie al fatto che Scala è un linguaggio fortemente tipizzato, Int e Long non rappresentano una minaccia per l'iniezione di SQL. Puoi preparare le tue istruzioni SQL usando l'interpolazione/concatenazione di stringhe solo per quelle colonne e associare le colonne non sicure con NamedParameter normalmente. Ciò ridurrebbe il numero di token che devono essere analizzati.