Mysql
 sql >> Base de données >  >> RDS >> Mysql

Insertion par lots avec un tableau comportant de nombreuses colonnes à l'aide d'Anorm

Je vais choisir l'option B. Je ne suis pas très familier avec BatchSql depuis la dernière fois que j'ai vérifié, il exécute simplement une charge de bateaux de requêtes en séquence, ce qui est terriblement lent. Je recommanderais de tout agréger en une seule requête. C'est un peu plus fastidieux, mais beaucoup plus rapide d'exécuter une seule requête avec mille insertions que mille insertions simples.

Pour plus de commodité, disons que vous avez Seq de

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

Ensuite, vous pouvez créer votre requête comme ceci :

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()

Remarques :

Vous devrez vérifier que values est non vide avant de continuer, car cela générerait une instruction SQL invalide si c'était le cas.

Selon le nombre de lignes et de colonnes que vous insérez, les analyseurs de jetons qui ont créé l'instruction préparée ralentiront éventuellement en raison de la quantité de jetons à analyser (et de la taille de la chaîne). J'ai remarqué cela après quelques centaines de lignes avec plusieurs colonnes. Cela peut être quelque peu atténué. Grâce au fait que Scala est un langage fortement typé, Int et Long ne présentent aucune menace pour l'injection SQL. Vous pouvez préparer vos instructions SQL en utilisant l'interpolation/concaténation de chaînes uniquement pour ces colonnes et lier les colonnes non sécurisées avec NamedParameter normalement. Cela réduirait le nombre de jetons à analyser.