Velocidad al grabar multiples registros en Mysql

Post Reply
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Velocidad al grabar multiples registros en Mysql

Post 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
User avatar
cmsoft
Posts: 1293
Joined: Wed Nov 16, 2005 9:14 pm
Location: Mercedes - Bs As. Argentina

Re: Velocidad al grabar multiples registros en Mysql

Post 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
User avatar
Jimmy
Posts: 1733
Joined: Thu Sep 05, 2019 5:32 am
Location: Hamburg, Germany

Re: Velocidad al grabar multiples registros en Mysql

Post 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
 
greeting,
Jimmy
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: Velocidad al grabar multiples registros en Mysql

Post 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
admsoporte
Posts: 104
Joined: Sun Oct 09, 2005 3:09 pm
Location: Mexico

Re: Velocidad al grabar multiples registros en Mysql

Post 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
Saludos

Atentamente

Jose F Dominguez Serafin

email admsoporte@gmail.com
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: Velocidad al grabar multiples registros en Mysql

Post 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
Carlos Mora
Posts: 989
Joined: Thu Nov 24, 2005 3:01 pm
Location: Madrid, España

Re: Velocidad al grabar multiples registros en Mysql

Post 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
Saludos
Carlos Mora
http://harbouradvisor.blogspot.com/
StackOverflow http://stackoverflow.com/users/549761/carlos-mora
“If you think education is expensive, try ignorance"
nnicanor
Posts: 302
Joined: Fri Apr 23, 2010 4:30 am
Location: Colombia

Re: Velocidad al grabar multiples registros en Mysql

Post 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
Nicanor Martinez M.
Auditoria y Sistemas Ltda.
MicroExpress Ltda.
FW + FWH + XHARBOUR + HARBOUR + PELLES C + XDEVSTUDIO + XEDIT + BCC + VC_X86 + VCC_X64 + MINGW + R&R Reports + FastReport + Tdolphin + ADO + MYSQL + MARIADB + ORACLE
nnicanor@yahoo.com
paquitohm
Posts: 284
Joined: Fri Jan 14, 2022 8:37 am

Re: Velocidad al grabar multiples registros en Mysql

Post 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.
Post Reply