web-dev-qa-db-fra.com

Comment améliorer l'insert dans RDS de AWS?

J'ai un mysql db.t2.small à AWS, le serveur n'est pas dans mon pays, mais j'obtiens 70ms. Maintenant, j'ai besoin d'insérer plus de 7 000 enregistrements dans une table, mais cela prend beaucoup, plus de 6 minutes. J'ai essayé de nombreuses configurations:

[.____] - Query_Cache_size = 16777216 [.____] - Query_cache_type = 1 [.____] - Net_write_timeout = 300 [ -innodb_flush_log_at_trx_commit = 2 (aussi j'ai essayé de la définir à 0). 

J'ai essayé d'envoyer les demandes 1 de 1 et utilisez également en gros, mais le résultat est le même, près de 20 inserts par seconde.

Qu'est-ce que je rate?

Mon Java code groupé:

try {
        conn = bd.getConectionAWS();
        PreparedStatement stmt = null;
        if (conn.getAutoCommit()) {
            conn.setAutoCommit(false);
        }
        try {
            String query = "INSERT INTO CONTRATO(Codigo,Nombre,IdEstado,DesEstado,FechaInicio,IndActivo,Activo,Descripcion,Cliente,Responsable) VALUES(?,?,?,?,?,?,?,?,?,?) \n"
                    + " ON DUPLICATE KEY \n"
                    + " UPDATE Nombre=?, IdEstado=?, idEstado=? ,DesEstado=? ,FechaInicio=?, IndActivo=?,Descripcion=?,Cliente=?,Responsable=?";
            stmt = conn.prepareStatement(query);
            for (Contrato contrato : listaDatos) {
                stmt.setString(1, contrato.getCodigo());
                stmt.setString(2, contrato.getNombre());
                stmt.setInt(3, contrato.getIdEstado());
                stmt.setString(4, contrato.getDesEstado());
                stmt.setTimestamp(5, contrato.getFechaInicio());
                stmt.setString(6, contrato.getIndActivo());
                stmt.setString(7, contrato.getActivo());
                stmt.setString(8, contrato.getDescripcion());
                stmt.setString(9, contrato.getCliente());
                stmt.setString(10, contrato.getResponsable());   
                stmt.setString(11, contrato.getNombre());
                stmt.setInt(12, contrato.getIdEstado());
                stmt.setString(13, contrato.getDesEstado());
                stmt.setTimestamp(14, contrato.getFechaInicio());
                stmt.setString(15, contrato.getIndActivo());
                stmt.setString(16, contrato.getActivo());
                stmt.setString(17, contrato.getDescripcion());
                stmt.setString(18, contrato.getCliente());
                stmt.setString(19, contrato.getResponsable());
                //          stmt.executeUpdate();
                stmt.addBatch();
            }
            stmt.executeBatch();
            conn.commit();
        }

J'ai pris quelques choses à partir de - https://www.mkyong.com/jdbc/jdbc-preparationStatement-example-batch-update/

Mon "1 par 1" est le même, il suffit de remplacer addBatch pour executeUpdate();.

Une requête SELECT 1; Prend 0,059Sec.

3
Jebus

Il y a deux façons d'atteindre efficacement (lire: rapidement) charger 7000 lignes.

  • LOAD DATA INFILE - Une fois que vous avez construit un fichier CSV de 7 000 lignes.

  • "Lot" INSERT - comme INSERT INTO t (a,b) VALUES (1,2),(5,6),(9,2), ...; - Soyez prudent du nombre de lignes. 100 à 1000 est une bonne gamme de ce qu'il faut faire à la fois.

max_allowed_packet=536870912 - Non, pas dans A minuscule 2 Go VM; changer à 16m. Autres paramètres probables de vérifier:

key_buffer_size = 10M
innodb_buffer_pool_size = 200M

Je suppose que vos tables sont innodub ??

1
Rick James

Si vous courez dans RDS (pas votre propre instance EC2 construite), vous pouvez obtenir de grandes performances à partir de l'outil AWS Data Pipeline - Charces directement à partir de S3. Il est conçu pour le chargement propre et rapide.

0
Chris Johnson