Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Inserção em lote com tabela que possui muitas colunas usando Anorm


Eu vou com a opção B. Não estou muito familiarizado com BatchSql desde a última vez que verifiquei, ele apenas executa uma carga de consultas em sequência, o que é muito lento. Eu recomendo agregar tudo em uma única consulta. É um pouco mais tedioso, mas muito mais rápido executar uma única consulta com mil inserções do que mil inserções únicas.

Por conveniência, digamos que você tenha Seq do
case class Test(val1: Int, val2: Option[Long], val3: Option[String])

Então você pode construir sua consulta assim:
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()

Observações:

Você terá que verificar se os values não está vazio antes de continuar, pois geraria uma instrução SQL inválida se estivesse.

Dependendo de quantas linhas e colunas você está inserindo, eventualmente os analisadores de token que criaram a instrução preparada ficarão mais lentos devido à grande quantidade de tokens a serem analisados ​​(e ao tamanho da string). Eu notei isso depois de algumas centenas de linhas com várias colunas. Isso pode ser um pouco mitigado. Graças ao Scala ser uma linguagem fortemente tipada, Int e Long não representam ameaça para injeção de SQL. Você pode preparar suas instruções SQL usando interpolação/concatenação de strings apenas para essas colunas e vincular as colunas não seguras com NamedParameter normalmente. Isso reduziria o número de tokens que precisam ser analisados.