Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

[SOLUCIONADO] Insert ignore para optimizar?

Estas en el tema de Insert ignore para optimizar? en el foro de Mysql en Foros del Web. Amigos de FDW, Ante todo un saludo. Estoy tratando de optimizar un script que funcionaba bien, pero que de pronto comenzó a colapsar cuando la ...
  #1 (permalink)  
Antiguo 12/10/2013, 10:43
Avatar de luisvasquez  
Fecha de Ingreso: diciembre-2003
Ubicación: Venezuela
Mensajes: 879
Antigüedad: 20 años, 4 meses
Puntos: 6
Pregunta Insert ignore para optimizar?

Amigos de FDW,

Ante todo un saludo.

Estoy tratando de optimizar un script que funcionaba bien, pero que de pronto comenzó a colapsar cuando la tabla pasó los 100 mil registros.

Basicamente lo que hace es preguntar si existe un registro en la tabla y sino, pues lo inserta, pero la cosa se ha puesto lenta porque hace un ciclo para pregunta.

Un poco del código
Código MySQL:
Ver original
  1. SELECT COUNT(*) FROM followers
  2. WHERE twitterid = :id and usuario_master =  '$cuenta'
  3.  
  4. INSERT INTO followers SET twitterid = :id, usuario_master = "'.$cuenta.'", update_dt = NOW()

Cita:
Editado: Código de programación no permitido en Foros de BBDD. Leer las normas del foro, por fvor.
Como pueden ver, hay un ciclo foreach (para un arreglo de 100 mil entradas) y en cada ciclo pregunta si el valor está o no, para insertarlo.

Pensé en usar INSERT IGNORE para evitar el SELECT COUNT(*), más o menos asi:

Código MySQL:
Ver original
  1. INSERT IGNORE INTO followers
  2. SET twitterid = :id, usuario_master = "'.$cuenta.'", update_dt = NOW()

Cita:
Editado: Código de programación no permitido en Foros de BBDD. Leer las normas del foro, por fvor.
sin embargo, debo ejecutar una función después de un insert efectivo (la función mensaje_directo) y en este caso dicha función se ejecutaría AUNQUE LA CLAVE ESTÉ DUPLICADA y eso sería desastroso.

Debo poder ejecutar el INSERT IGNORE y luego poder evaluar ¿Se inserto el registro? para poder decidir si ejecutar la función o no.

Espero haberme explicado y agradeciendo de antemano sus comentarios.

Luis Vásquez

Última edición por gnzsoloyo; 12/10/2013 a las 12:51 Razón: Código de programación no permitido en Foros de BBDD. Leer las normas del foro, por fvor.
  #2 (permalink)  
Antiguo 12/10/2013, 11:03
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Insert ignore para optimizar?

Creo que estás entremezclando las cosas: O lo resuelves por programación, o lo haces con un mejor uso de lógica de SQL y Bases de Datos.
Hacer las cosas iterativamente es muy de programadores, pero no es necesariamente correcto usarla en SQL. Las iteraciones no son necesarias si se usan correctas validaciones en la base de datos.

Explica mejor estas cosas:
1) ¿Por qué recorres esa iteración, qué datos se supone que tienes al inicio para hacerla y qué es lo que intentas hacer al realizarla.
2) realmente necesitas insertar, o estás intentando actualizar algo también?
3) ¿Por qué una sintaxis alternativa de INSERT? Se puede prestar a confusiones, por más que sea válida.

Nota: El código de programación no está permitido en Foros de BBDD. Leer las normas del foro, por favor.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 12/10/2013, 11:28
Avatar de luisvasquez  
Fecha de Ingreso: diciembre-2003
Ubicación: Venezuela
Mensajes: 879
Antigüedad: 20 años, 4 meses
Puntos: 6
Respuesta: Insert ignore para optimizar?

Cita:
Iniciado por gnzsoloyo Ver Mensaje
Creo que estás entremezclando las cosas: O lo resuelves por programación, o lo haces con un mejor uso de lógica de SQL y Bases de Datos.
Hacer las cosas iterativamente es muy de programadores, pero no es necesariamente correcto usarla en SQL. Las iteraciones no son necesarias si se usan correctas validaciones en la base de datos.

Explica mejor estas cosas:
1) ¿Por qué recorres esa iteración, qué datos se supone que tienes al inicio para hacerla y qué es lo que intentas hacer al realizarla.
2) realmente necesitas insertar, o estás intentando actualizar algo también?
3) ¿Por qué una sintaxis alternativa de INSERT? Se puede prestar a confusiones, por más que sea válida.

Nota: El código de programación no está permitido en Foros de BBDD. Leer las normas del foro, por favor.
Agradezco tu pronta respuesta y pido disculpas por postear código en esta sección del foro.

El arreglo que estoy recorriendo viene de un llamado al API de Twitter, por lo que no es una estructura elegida por mi. Viene así y así debo procesalra. Contiene los id de los seguidores de una cuenta twitter en particular ($cuenta).

Sólo necesito insertar los registros nuevos, que no han sido insertados antes, es decir, los nuevos seguidores de la cuenta desde la última ejecución del script.

De allí el select count() para preguntar ¿ya está en la tabla? e insertar si no está.

El asunto es que está tardando mucho tiempo en ejecutar y no se me ocurre nada para optimizar. Me parece que el select count() repetido 100 mil veces es lo que está causando el problema.

Los campos Id y usuario_master forman el primary_key y además están indexados por separado.

Agradezco tu tiempo y paciencia.
Saludos
  #4 (permalink)  
Antiguo 12/10/2013, 12:54
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Insert ignore para optimizar?

Esta parte es la que me causa dudas:
Cita:
El asunto es que está tardando mucho tiempo en ejecutar y no se me ocurre nada para optimizar. Me parece que el select count() repetido 100 mil veces es lo que está causando el problema.
¿Por qué razón se termina contando N veces (100.000)? Si esos dos valores son PK, entonces sólo debe ser necesario contar una única vez, una sola ejecución, y siendo PK, sería rapidísima.
¿De donde salen los otros 99.999 registros que verificas? ¿En qué se diferencian?

Respecto a usar INSERT IGNORE, si el registro ya existe, simplemente no lo inserta, sin warnings. Pero si no existe, lo inserta, y en ese caso la función NUM_ROWS() debe devolverte un numero positivo (1), ya que se modificó algo. En cambio, si no lo insertó, NUM_ROWS() devolverá cero (0).
Nota: NUM_ROWS() es una función de MySQL, no de PHP, pero PHP tiene su propia forma de obtener la misma información, luego de ejecutar la consulta en MySQL.
Eso lo tienes que ver en el Foro de PHP.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 12/10/2013, 13:30
Avatar de luisvasquez  
Fecha de Ingreso: diciembre-2003
Ubicación: Venezuela
Mensajes: 879
Antigüedad: 20 años, 4 meses
Puntos: 6
Respuesta: Insert ignore para optimizar?

Cita:
Iniciado por gnzsoloyo Ver Mensaje
Esta parte es la que me causa dudas:

¿Por qué razón se termina contando N veces (100.000)? Si esos dos valores son PK, entonces sólo debe ser necesario contar una única vez, una sola ejecución, y siendo PK, sería rapidísima.
¿De donde salen los otros 99.999 registros que verificas? ¿En qué se diferencian?

Respecto a usar INSERT IGNORE, si el registro ya existe, simplemente no lo inserta, sin warnings. Pero si no existe, lo inserta, y en ese caso la función NUM_ROWS() debe devolverte un numero positivo (1), ya que se modificó algo. En cambio, si no lo insertó, NUM_ROWS() devolverá cero (0).
Nota: NUM_ROWS() es una función de MySQL, no de PHP, pero PHP tiene su propia forma de obtener la misma información, luego de ejecutar la consulta en MySQL.
Eso lo tienes que ver en el Foro de PHP.
Gracias de nuevo amigo!.

Te comento, el arreglo tiene más de 100 mil registros por lo que, recorrerlo para verificar cada entrada implica 100 mil select count(*) where reg = 'elemento actual del arreglo'.

Debo verificar cada elemento del arreglo que viene de twitter para ver si ya lo cargué en la base de datos o no. Hago el insert SI Y SOLO SI no lo he cargado.

Por eso pensé ¿y si elimino ese select count e inserto sin preguntar?

Para eso tengo 2 opciones: Hacerlo con insert y manejar el error para evitar ejecutar la función o hacerlo con insert ignore
  #6 (permalink)  
Antiguo 12/10/2013, 14:01
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Insert ignore para optimizar?

Usa el IGNORE, pero luego verifica si el resultado fue una inserción. Sencillamente eso.
Si lo haces desde programación, ya te dije que el lenguaje te devolverá si la acción generó un registro. Si lo haces desde SQL, son dos queries: una para insertar y otra para verificar si inseró algo.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #7 (permalink)  
Antiguo 13/10/2013, 00:27
Avatar de luisvasquez  
Fecha de Ingreso: diciembre-2003
Ubicación: Venezuela
Mensajes: 879
Antigüedad: 20 años, 4 meses
Puntos: 6
Respuesta: Insert ignore para optimizar?

1000 gracias, la verdad es que ha mejorado bastante.

Etiquetas: insert
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:24.