InnoDB insère très lent et le ralentissement de
J'ai récemment changé mon projet de tables InnoDB (penser les relations seraient une bonne chose à avoir). J'utilise un script PHP pour l'index de près de 500 produits à la fois.
Une table de stockage de mot/id de l'association:
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
Une autre table stocke l'id du produit/mot id associations:
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
Le script a été testé à l'aide de MyISAM et index des produits relativement rapide (beaucoup, beaucoup plus rapide que InnoDB). La première fois que l'exécution en InnoDB il était ridiculement lent mais après l'imbrication des valeurs plus ensemble, j'ai fini par l'accélérer par beaucoup (mais pas assez).
Je suppose que innodb serait beaucoup plus rapide pour ce genre de chose, car de rowlevel serrures mais ce n'est pas le cas.
Je construire une requête qui ressemble à quelque chose comme:
SELECT
title,keywords,upc,...
FROM product
WHERE indexed = 0
LIMIT 500
J'ai créer une boucle et remplir un tableau avec tous les mots qui doivent être ajoutés à windex et tous le mot id/id de produit paires qui doivent être ajoutés à indx_0.
Parce que innodb ne cesse de monter mon auto-incrémentation des valeurs à chaque fois que je fais un "REMPLACER par" ou "INSÉRER IGNORER" qui échoue à cause de doublons, j'ai besoin de s'assurer que les valeurs-je ajouter n'existent pas déjà. Pour le faire j'ai d'abord sélectionner toutes les valeurs qui existent à l'aide d'une requête comme tel:
SELECT wid,word
FROM windex
WHERE
word = "someword1" or word = "someword2" or word = "someword3" ... ...
Puis je filtre mon tableau par rapport aux résultats qui existent, pour tous les nouveaux mots que j'ai ajouter sont 100% nouveau.
Cela prend environ 20% du temps d'exécution global. Les autres 80% va dans ajout de la paire de valeurs dans indx_0, pour lequel il y a beaucoup plus de valeurs.
Voici un exemple de ce que je reçois.
0.4806 secondes pour sélectionner les produits. (0.4807 sec total).
0.0319 secondes pour rassembler les 500 articles. (0.5126 sec total).
5.2396 secondes pour sélectionner windex valeurs à des fins de comparaison. (5.7836 sec total).
1.8986 secondes pour le nombre de mises à jour. (7.6822 sec total).
0.0641 secondes pour ajouter 832 windex enregistrements. (7.7464 sec total).
17.2725 secondes pour ajouter de l'indice de 3435 pid/wid paires. (25.7752 sec total).
L'opération a pris 26.07 secondes à l'indice 500 de produits.
La 3435 paires sont toutes exécutées en une seule requête telle que:
INSERT INTO indx_0(pid,wid)
VALUES (1,4),(3,9),(9,2)... ... ...
Pourquoi est-InnoDB beaucoup plus lent que MyISAM dans mon cas?
OriginalL'auteur nick | 2012-02-02
Vous devez vous connecter pour publier un commentaire.
InnoDB fournit plus complexe clés de la structure que MyIsam (
FOREIGN KEYS
) et la régénération de clés est vraiment lent en InnoDB. Vous devez joindre tous les update/insert dans l'une des transactions (ceux-ci sont en fait assez rapide en InnoDB, une fois que j'ai eu environ 300 000 requêtes de type insert sur la table InnoDb avec 2 index et il a fallu environ 30 minutes, une fois que j'ai fermé toutes les 10 000 insère dansBEGIN TRANSACTION
etCOMMIT
il a fallu moins de 2 minutes).Je recommande d'utiliser:
Ce sera la cause de InnoDB pour actualiser les index juste une fois n'est pas quelques centaines de fois.
Laissez-moi savoir si cela a fonctionné
J'ai eu un problème dans un curseur qui ce fixe (à partir de 90 secondes à 0,9!) Lentement, je suis en train d'apprendre ce qui est exigé de InnoDB
Concernant les "j'ai fermé toutes les 10 000 insère dans
BEGIN TRANSACTION
etCOMMIT
il a fallu moins de 2 minutes", Pourquoi avez-vous divisé en 10k lots? Pourquoi ne pas joindre tous états au sein d'une seule opération?récupération plus facile, et en général j'évite vraiment de grosses transactions, donc je n'aurais pas de problèmes à l'intérieur des verrous de table...
Maintenant, je ne suis pas sûr que je vous comprends par là, sûrement que la transaction est le l'exécution d'une seule lorsque nous faisons le lot insère droit...... Aussi, qu'entendez-vous par "récupération plus facile"?
OriginalL'auteur Vyktor
J'ai eu un problème similaire et il semble InnoDB a par défaut innodb_flush_log_at_trx_commit permis qui supprime chaque insérer/mettre à jour une requête sur votre disque dur le fichier de log. La vitesse d'écriture de votre disque dur est un goulot d'étranglement pour ce processus.
Essayez donc de modifier votre fichier de configuration de mysql
Redémarrez le service de mysql.
J'ai vécu sur le x100 speedup sur les plaquettes.
fonctionne comme un charme
OriginalL'auteur Mini Fridge