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

Left join muy lento

Estas en el tema de Left join muy lento en el foro de Mysql en Foros del Web. Buenas compañeros, Tengo un problema con una consulta que se me relentiza muchisimo. Probando con poner y quitar el LEFT JOIN he visto que este ...
  #1 (permalink)  
Antiguo 20/10/2014, 09:25
 
Fecha de Ingreso: octubre-2014
Mensajes: 5
Antigüedad: 10 años, 1 mes
Puntos: 0
Left join muy lento

Buenas compañeros,

Tengo un problema con una consulta que se me relentiza muchisimo. Probando con poner y quitar el LEFT JOIN he visto que este es el motivo de la extrema lentitud. Actualmente las dos tablas que comparten esta consulta tienen 62.000 filas una y 54.000 filas la otra.

He estado investigando y una posible solución es la utilización de indices, creeis que esta es la mejor opción o sería mejor plantear la consulta de otra manera.

Dejo el código aquí y mil gracias

Código MySQL:
Ver original
  1. can.cand_intnacionalidad Nacionalidad
  2. ,DATE_FORMAT(can.cand_datenacimiento,'%d/%m/%Y') as fechaNacimiento
  3. ,can.cand_intprovincia as idProvincia
  4. ,can.cand_strpoblacion as Poblacion
  5. ,can.cand_strfoto as urlFotografia
  6. ,can.cand_intautonomo as boolAutonomo
  7. ,can.cand_strfoto as urlFotografia
  8. ,cuen.nombre
  9. ,cuen.apellido
  10. FROM tbcandidatos can
  11. LEFT JOIN catcuentas cuen on can.ccta_stremail=cuen.ccta_stremail
  #2 (permalink)  
Antiguo 20/10/2014, 09:35
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Left join muy lento

Si los campos tbcandidatos.ccta_stremail y catcuentas.ccta_stremail no representan una relación PK<--FK, entonces te conviene indexarlos en ambas tablas.
__________________
¿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 20/10/2014, 09:46
 
Fecha de Ingreso: octubre-2014
Mensajes: 5
Antigüedad: 10 años, 1 mes
Puntos: 0
Respuesta: Left join muy lento

Hola gnzsoloyo,

Muchas gracias por la rapidez.

Cuando te refieres a que no representan una relacion PK<-- FK te refieres a las claves foraneas no? Sería eso una solución distina a los indices? Puedo generar esta relación entre las tablas ?

Gracias y disculpa la ignorancia ya que este tema lo tengo muy verde
  #4 (permalink)  
Antiguo 20/10/2014, 09:51
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Left join muy lento

Las claves foráneas no son estrictamente una solución "distinta". El tema pasa por el lado de que cuando existe una relacion de PK/FK MySQL crea un índice que administra esa relación, por lo que indexar esos campos es redundante. No generará diferencias de comportamiento, y como mucho bajará la performance de los INSERT a las dos tablas.
Ahora bien, si las tablas no son InnoDB, sino MyISAM, entonces no existirán los indices de FOREIGN KEY y te convendrá crear un indice para ese campo en cada tabla.
De todos modos, recuerda que un LEFT JOIN siempre realiza un FULL TABLE SCAN sobre la primera tabla, por lo que si la primera tiene demasiados registros es mejor que se encuentre optimizada.
__________________
¿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 23/10/2014, 03:45
 
Fecha de Ingreso: octubre-2014
Mensajes: 5
Antigüedad: 10 años, 1 mes
Puntos: 0
Respuesta: Left join muy lento

Muchas gracias gnzsoloyo,

Las dos tablas son InnoDB, por lo que he intentado crear una tabla foranea. El problema que me encuentro es que el sistema no me deja por un problema de integridad referencial. Supongo que alguna fila de la clave foranea no existe en la clave principal.

Por este motivo he intentado detectar estas filas para eliminarlas (Leiendo una propuesta tuya que le hacías a otro compañero: http://www.forosdelweb.com/f86/como-comprobar-que-campo-tabla-exista-otra-tabla-785427/) pero el sistema se me queda colgado entiendo que por ser una consulta muy muy lenta. Existe otra manera de comprobar las filas que no coinciden?

Mil gracias
  #6 (permalink)  
Antiguo 23/10/2014, 04:08
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Left join muy lento

Dos formas básicas:
Código MySQL:
Ver original
  1. SELECT can.ccta_stremail
  2. FROM tbcandidatos can
  3. LEFT JOIN catcuentas cuen on can.ccta_stremail=cuen.ccta_stremail
  4. WHERE cuen.ccta_stremail IS NULL
eso te devolverá el campo ccta_stremail de aquellos registros de la primera que no tengan su correspondiente en la segunda.
o bien
Código MySQL:
Ver original
  1. SELECT can.ccta_stremail
  2. FROM tbcandidatos can
  3. WHERE cuen.ccta_stremail NOT IN (SELECT cuen.ccta_stremail FROM catcuentas cuen )

Respecto a las FK recuerda que para crear una:
1) El campo de la taba referida debe ser PRIMARY KEY o al menos UNIQUE en su tabla.
2) Ambos campos deben ser del mismo tipo, rango, collation y charset, si son de caracteres, o tipo y rango, si son numéricos, fecha, hora o datetime.
3) Si tienen datos, deben ser consistentes con las restricciones de FK (no debe haber valores en la segunda que no existan en la PK de la primera).
__________________
¿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 23/10/2014, 04:40
 
Fecha de Ingreso: octubre-2014
Mensajes: 5
Antigüedad: 10 años, 1 mes
Puntos: 0
Respuesta: Left join muy lento

Hola gnzsoloyo,

El primer código ya lo había intentado y en el segundo me pasa exactamente igual. En phpmyadmin me aparece después de un tiempo el error #1317 - Query execution was interrupted .

Entiendo que la busqueda es muy pesadada y por eso. Existe alguna otra manera menos "pesada" o la opción de hacerlo en tramos para que me lo permita realizar?

Muchas gracias por tu ayuda
  #8 (permalink)  
Antiguo 23/10/2014, 05:42
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: Left join muy lento

Bueno, vamoa a analizar el problema mas en detalle. VEamos la composicion de las tablas. Postea el resultado de estas dos queries (son para ver la estructura real de las tablas):
Código MySQL:
Ver original
  1. SHOW CREATE TABLE tbcandidatos;
  2. SHOW CREATE TABLE catcuentas;
Luego esto:
Código MySQL:
Ver original
  1. SELECT COUNT(ccta_stremail) TotalNoNulos, SUM(IF(ccta_stremail IS NULL OR TRIM(ccta_stremail ) = '', 1, 0)) TotalNulos
  2. FROM tbcandidatos
Código MySQL:
Ver original
  1. SELECT COUNT(ccta_stremail) TotalNoNulos, SUM(IF(ccta_stremail IS NULL OR TRIM(ccta_stremail ) = '', 1, 0)) TotalNulos
  2. FROM catcuentas;
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #9 (permalink)  
Antiguo 23/10/2014, 06:02
 
Fecha de Ingreso: octubre-2014
Mensajes: 5
Antigüedad: 10 años, 1 mes
Puntos: 0
Respuesta: Left join muy lento

SHOW CREATE TABLE tbcandidatos

Código MySQL:
Ver original
  1. CREATE TABLE `tbcandidatos` (
  2.  `ccta_stremail` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  3.  `sin_estudios` int(1) NOT NULL,
  4.  `sin_experiencia` int(1) NOT NULL,
  5.  `cand_datenacimiento` date NOT NULL,
  6.  `cand_intgenero` tinyint(4) NOT NULL,
  7.  `cand_strtelefono` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  8.  `cand_intpais` tinyint(4) NOT NULL,
  9.  `cand_intprovincia` tinyint(4) NOT NULL,
  10.  `cand_strpoblacion` varchar(150) COLLATE latin1_spanish_ci NOT NULL,
  11.  `cand_intnacionalidad` tinyint(4) NOT NULL,
  12.  `cand_intautonomo` tinyint(4) NOT NULL,
  13.  `cand_intconductor` varchar(200) COLLATE latin1_spanish_ci NOT NULL,
  14.  `cand_strfoto` varchar(150) COLLATE latin1_spanish_ci NOT NULL,
  15.  `cand_inactivo` tinyint(4) NOT NULL,
  16.  `cand_strpuestoideal` varchar(200) COLLATE latin1_spanish_ci NOT NULL,
  17.  `cand_intcategoria` tinyint(4) NOT NULL,
  18.  `cand_strsubcategorias` varchar(300) COLLATE latin1_spanish_ci NOT NULL,
  19.  `cand_strprovincias` varchar(300) COLLATE latin1_spanish_ci NOT NULL,
  20.  `cand_intviajar` tinyint(4) NOT NULL,
  21.  `cand_intmudanza` tinyint(4) NOT NULL,
  22.  `cand_intofertas` tinyint(4) NOT NULL,
  23.  `cand_intperfil` tinyint(4) NOT NULL,
  24.  `fech_last_login` date NOT NULL,
  25.  `fech_last_postu` date NOT NULL,
  26.  `fecha_last_pdf` date NOT NULL,
  27.  `fecha_las_linkedin` date NOT NULL,
  28.  `almacen` int(1) NOT NULL,
  29.  `integridadRelacional` int(1) NOT NULL,
  30.  PRIMARY KEY (`ccta_stremail`)
  31. ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci

SHOW CREATE TABLE catcuentas
Código MySQL:
Ver original
  1. CREATE TABLE `catcuentas` (
  2.  `id_cuenta` int(255) NOT NULL AUTO_INCREMENT,
  3.  `ccta_stremail` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  4.  `ccta_strnombre` varchar(200) COLLATE latin1_spanish_ci NOT NULL,
  5.  `ccta_strapellidos` varchar(250) COLLATE latin1_spanish_ci NOT NULL,
  6.  `ccta_strtelefono` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  7.  `ccta_strpassword` varchar(20) COLLATE latin1_spanish_ci NOT NULL,
  8.  `ccta_md5strpassword` varchar(555) COLLATE latin1_spanish_ci NOT NULL,
  9.  `ccta_inttipo` tinyint(4) NOT NULL COMMENT '1. Empresa - 2.Candidato',
  10.  `ccta_intactivo` tinyint(4) NOT NULL,
  11.  `codigo` varchar(20) COLLATE latin1_spanish_ci NOT NULL,
  12.  `fecha_alta` date NOT NULL,
  13.  `cookie` varchar(100) COLLATE latin1_spanish_ci NOT NULL,
  14.  PRIMARY KEY (`id_cuenta`,`ccta_stremail`)
  15. ) ENGINE=InnoDB AUTO_INCREMENT=68664 DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci

SELECT COUNT tbcandidatos

TotalNoNulos TotalNulos
54911 1

SELECT COUNT catcuentas

TotalNoNulos TotalNulos
67772 1


Un saludo,

Etiquetas: join, left, optimización
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 10:39.