Recientemente cambié mis tablas de proyecto a InnoDB (pensando que las relaciones serían algo bueno tener). Estoy usando un script PHP para indexar alrededor de 500 productos a la vez.InnoDB se inserta muy lento y ralentizando
Palabras/asociación ids tabla que almacena:
CREATE TABLE `windex` (
`word` varchar(64) NOT NULL,
`wid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`count` int(11) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`wid`),
UNIQUE KEY `word` (`word`)
) ENGINE=InnoDB AUTO_INCREMENT=324551 DEFAULT CHARSET=latin1
Otra tabla almacena los ID de producto/palabra asociaciones Identificación:
CREATE TABLE `indx_0` (
`wid` int(7) unsigned NOT NULL,
`pid` int(7) unsigned NOT NULL,
UNIQUE KEY `wid` (`wid`,`pid`),
KEY `pid` (`pid`),
CONSTRAINT `indx_0_ibfk_1` FOREIGN KEY (`wid`) REFERENCES `windex` (`wid`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `indx_0_ibfk_2` FOREIGN KEY (`pid`) REFERENCES `product` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
El script se ensayó usando MyISAM y que indexa productos relativamente rápido (mucho , mucho más rápido que InnoDB). La primera vez que ejecuté InnoDB fue ridículamente lento, pero después de anidar más valores juntos terminé acelerando mucho (pero no lo suficiente).
Supongo que innodb sería mucho más rápido para este tipo de cosas debido a bloqueos rowlevel, pero ese no es el caso.
construyo una consulta que se ve algo como:
SELECT
title,keywords,upc,...
FROM product
WHERE indexed = 0
LIMIT 500
puedo crear un bucle y llenar una matriz con todas las palabras que necesitan ser añadido a Windex y todos los pares de palabra/Identificación del producto id que necesitan para ser agregado a indx_0.
Debido a que innodb sigue aumentando mis valores de autoincremento cada vez que hago un "REEMPLAZAR" o "INSERTAR IGNORAR" que falla debido a valores duplicados, necesito asegurarme de que los valores que agrego no existan. Para hacer que por primera vez seleccionar todos los valores que existen, utilizando una consulta como por ejemplo:
SELECT wid,word
FROM windex
WHERE
word = "someword1" or word = "someword2" or word = "someword3" ... ...
Entonces puedo filtrar mi batalla contra los resultados que existen por lo que todas las nuevas palabras que agrego son 100% nuevo.
Esto toma alrededor del 20% del tiempo total de ejecución. El otro 80% se usa para agregar los valores de par en indx_0, para lo cual hay muchos más valores.
Aquí hay un ejemplo de lo que obtengo.
0.4806 segundos para seleccionar productos. (0,4807 sec en total).
0.0319 segundos para reunir 500 elementos. (0.5126 sec en total).
5.2396 segundos para seleccionar los valores de windex para la comparación. (5,7836 segundos en total).
1.8986 segundos para actualizar la cuenta. (7.6822 segundos en total).
0.0641 segundos para agregar 832 registros de windex. (7.7464 segundos en total).
17.2725 segundos para agregar el índice de 3435 pares pid/wid. (25.7752 segundos en total).
La operación tomó 26.07 segundos para indexar 500 productos.
Los 3435 pares están siendo ejecutados todos en una sola consulta, tales como:
INSERT INTO indx_0(pid,wid)
VALUES (1,4),(3,9),(9,2)... ... ...
¿Por qué es InnoDB mucho más lento que MyISAM en mi caso?
¿La idea del índice de palabras es crear algún tipo de funcionalidad de búsqueda? Si ese es el caso, hayas hecho eso, echa un vistazo a un motor de búsqueda real como solr o mysql fulltext search por ejemplo. No puede superar tales tareas específicas. –