Page 1 of 1

Velocidad al grabar multiples registros en Mysql

Posted: Tue Aug 06, 2024 11:17 am
by paquitohm
Hola,

Todos los dias subo la tabla de ventas a un servidor mysql
El problema es que ya demora mucho.
La voy subiendo registro a registro con la siguiente estrategia y queria saber a ver a vds. que se les ocurre para mejorar la velocidad.
Desde ya gracias

Code: Select all | Expand

cSetKey:= ConstruyeSet(aCamKey, cAlias)     
cSet   := ConstruyeSet(aCam   , cAlias)


cSql:= "INSERT INTO "+ cTablaSede+ Space(1)+;
               "SET "+ cSetKey+ If(Empty(cSetKey), "", ",")+ Space(1)+;
                cSet+ Space(1)+;
               "ON DUPLICATE KEY UPDATE "+ cSet

IF !oServer:Execute(cSql)
   MERROR_("(1) Fallo en ejecucion sql", cSql)
ENDIF
RETURN NIL

Re: Velocidad al grabar multiples registros en Mysql

Posted: Tue Aug 06, 2024 12:16 pm
by cmsoft
Hola Paquito:
Si haces el insert o update registro por registro, eso implica que hagas tantas ejecuciones insert como registros tengas.
Podrías hace una sola query para actualizar todos los registros de una sola vez.
De esta forma podrías hacerlo a mano asi

Code: Select all | Expand

dbf->(DBGOTOP())
cSql := "INSERT INTO ventas "+;
        " (factura,importe,iva,cliente) VALUES "
DO WHILE !dbf->(Eof())
    cSql := cSql + "("+ClipValue2SQL(dbf->factura) + "," + ;
                       ClipValue2SQL(dbf->importe) + "," + ;
                       ClipValue2SQL(dbf->iva) + "," + ;
                       ClipValue2SQL(dbf->cliente) + "), "
    dbf->(DbSkip())
ENDDO
cSql := LEFT(cSql,LEN(cSql)-2)  // Le borro la ultima coma y espacio
cSql := cSql + "ON DUPLICATE KEY UPDATE "+;
                     "importe = VALUES(importe), "+;
                     "iva = VALUES(iva) "
TRY
  oServer:BeginTransaction()
  oServer:Execute(cSql)
  oServer:CommitTransaction()
CATCH cError
  MsgStop("Error al Importar"+CHR(10)+cError:description,"Error")
  oServer:RollBack()
END TRY    
 
La clase TDolphin tiene un metodo para hacerlo de forma automática

Code: Select all | Expand

oServer:InsertFromDbf( cTable, cAlias, nLimit, aStruct, bOnInsert, cDuplicateKey, bOnRow )
Seguramente la clase nativa tiene algo similar
https://forums.fivetechsupport.com/view ... =3&t=32657
Espero te sirva de base para tu caso

Re: Velocidad al grabar multiples registros en Mysql

Posted: Tue Aug 06, 2024 12:40 pm
by Jimmy
hi,

you speedup a lot when send multiple INSERT Commands in "one line", depend on Cache Configuration of SQL-Server

Code: Select all | Expand

LOCAL nBatchSize := 1500                                              // MTU
...
   // for every Record
   //
   cPreText := "INSERT INTO " + xtab + " VALUES("
...
   DO WHILE .NOT. EOF()
      nCount ++
      lUseBlob := .F.
      cIns += cPreText
---
      cIns := STRTRAN( cIns, CHR( 0 ), " " )    // if any CHR(0)

      nBatch += LEN( cIns )
      IF nBatch >= (nBatchSize*8)              // send when reach half size of Server Cache
         nBatch := 0

         oPG:exec( cIns )                       // now send Query
---
      ELSE
         // EOL
         cIns += ";" + CRLF                     // Add to "one LIne"
      ENDIF
 

Re: Velocidad al grabar multiples registros en Mysql

Posted: Wed Aug 07, 2024 3:01 pm
by paquitohm
César, Jimmy,

Lo voy a intentar según el esquema de César atendiendo al límite de bufferización que propone Jimmy

Gracias a ambos

Re: Velocidad al grabar multiples registros en Mysql

Posted: Wed Aug 07, 2024 6:56 pm
by admsoporte
Buenas tardes desde Puebla Mexico, yo tuve esa problematica y la resolvi utilizando el metodo SetAutoCommit( lOnOff) del objecto Connection (oCon)
primero antes de iniciar los insert lo pongo desactivado
oCon:SetAutoCommit(.f.)
y al terminar todas las inserciones lo regreso a activado
oCon:SetAutoCommit(.t.)
En el ejemplo oCon es el nombre de tu objeto connection.
Saludos

Re: Velocidad al grabar multiples registros en Mysql

Posted: Wed Aug 07, 2024 7:41 pm
by paquitohm
Gracias admSoporte por la respuesta.

Lamentablemente no puedo hacerlo porque uso TDolphin y parece ser, si no estoy equivocado, que no tiene esa posibilidad

BTW. ¿ No haría falta un oConn:Commit() ?

Salu2

Re: Velocidad al grabar multiples registros en Mysql

Posted: Wed Aug 21, 2024 9:27 am
by Carlos Mora
Hola Paquito!

Si quieres velocidad, olvídate de las transacciones. Solo se justifica si la concurrencia es mucha y realmente hay procesos que actualicen simultáneamente la misma tabla.
Haz la prueba: Intala el MySqlWorkbech, tiene un apartado en administración que mide las queries y fíjate lo que pesa un start transaction y un commit.

Un saludo,

Carlos

Re: Velocidad al grabar multiples registros en Mysql

Posted: Wed Aug 21, 2024 2:25 pm
by nnicanor
Hola,

Puedes armar la senctencia insert como script y usar Execute de tdolphin y te funciona de maravillas, si lo haces registro a registro se realiza un bloqueo a nivel de tabla por cada insert.

Slds,


Nicanor

Re: Velocidad al grabar multiples registros en Mysql

Posted: Wed Aug 21, 2024 3:50 pm
by paquitohm
Carlos Mora wrote:Hola Paquito!

Si quieres velocidad, olvídate de las transacciones. Solo se justifica si la concurrencia es mucha y realmente hay procesos que actualicen simultáneamente la misma tabla.
Haz la prueba: Intala el MySqlWorkbech, tiene un apartado en administración que mide las queries y fíjate lo que pesa un start transaction y un commit.

Un saludo,

Carlos
Hola Carlos,

Qué sorpresa tan agradable verte por aquí. Tu estupendas soluciones aun son consultables en el foro y cuanto nos ayudan a muchos !!
Gracias por tu interés. Digo lo que he hecho más abajo

nnicanor wrote:Hola,

Puedes armar la senctencia insert como script y usar Execute de tdolphin y te funciona de maravillas, si lo haces registro a registro se realiza un bloqueo a nivel de tabla por cada insert.

Slds,Nicanor
Hola nnicanor,

Gracias por tu interes. Debajo pongo la solución que he usado:

La solución que he usado ha sido usar el comando "LOAD DATA LOCAL INFILE" que me ha acelerado mucho las subidas de informacion.
Lo probé poniendo transacciones grandes, luego pequeñas, luego más pequeñas y nada, no mejoraba.
En cambio con LOAD DATA LOCAL INFILE, despues de habilitar permisos en el servidor para que permita ese comando, ya si arreó como una moto

Gracias a TODOS los que habeis tomado interés en el hilo.