7
votes

Inserts MySQL lents

J'utilise et travaille sur des logiciels qui utilise MySQL comme moteur backend (il peut utiliser d'autres personnes telles que PostgreSQL ou Oracle ou SQLite, mais c'est la principale application que nous utilisons). Le logiciel a été conçu de manière à ce que les données binaires que nous souhaitons accéder soient conservées comme blobs dans des colonnes individuelles (chaque table dispose d'une colonne blob , d'autres colonnes ont des entiers / flotteurs Pour caractériser la colonne blob et une colonne de chaîne avec la blob sm5 hachage). Les tables ont typiquement 2, 3 ou 4 index, dont l'une est toujours la colonne MD5, qui est faite unique . Certaines tables ont déjà des millions d'entrées et elles sont entrées dans la taille du multi-gigaoctet. Nous gardons des bases de données séparées par an MySQL dans le même serveur (jusqu'à présent). Le matériel est assez raisonnable (je pense) pour des applications générales (un serveur de formulaire Dell PowerEdge 2U).

MySQL Sélectionnez Les requêtes sont relativement rapides. Il y a peu de plaintes là-bas, car ils sont (la plupart du temps) en mode batch. Cependant, Insérer Les requêtes prennent beaucoup de temps, ce qui augmente avec la taille de la table (nombre de lignes). Certes, c'est parce que la colonne MD5 est de type unique et donc chaque insert doit déterminer si chaque nouvelle ligne a une chaîne MD5 correspondante, déjà insérée. Et ce n'est pas trop étrange (je pense) si la performance s'aggrave s'il y a d'autres index (pas uniques). Mais je ne peux toujours pas mettre mon esprit à reposer que ce choix d'architecture logicielle (je soupçonne qu'il conserve blobs dans la ligne de table au lieu du disque a un impact négatif significatif) n'est pas le meilleur choix. Les insertions ne sont pas critiques, mais c'est un sentiment ennuyeux d'avoir.

Quelqu'un a-t-il de l'expérience dans des situations similaires? Avec mysql, ou même autre (de préférence) rdbmes? Toutes les idées que vous souhaitez fournir, peut-être des chiffres de performance?

BTW, la langue de travail est C ++ (qui enveloppe C appelle à l'API de MySQL).


0 commentaires

5 Réponses :


1
votes

Utilisez-vous Myisam?
Afaik Myisam a une très bonne lecture-performance, mais de mauvaises performances d'écriture.

InnoDB devrait être équilibré à la vitesse.


1 commentaires

Oui, j'ai oublié ce détail. Le serveur que nous utilisons utilise Myisam.



5
votes

voir Vitesse des instructions d'insertion . Avez-vous des collisions fréquentes MD5? Je crois que ceux-ci ne devraient pas arriver trop souvent, alors peut-être que vous pouvez utiliser quelque chose comme Insérer ... sur dupliquer pour gérer les collisions. Si vous avez des périodes d'insertion spécifiques, vous pouvez Désactiver les clés pour le moment de l'insertion et les restaurer plus tard. Une autre option consiste à utiliser Réplication , à l'aide d'une machine maître pour le Inserts et esclave pour les SELECTS.


2 commentaires

Merci pour les suggestions, je vais regarder dans eux.


À partir du lien ci-dessus: "Si vous insérez de nombreuses lignes du même client en même temps, utilisez des instructions d'insertion avec plusieurs listes de valeurs pour insérer plusieurs lignes à la fois. Ceci est considérablement plus rapide (plusieurs fois plus vite dans certains cas) que d'utiliser Déclarations d'insertion à une rangée séparées. " Cela a pris mon processus d'insertion de 6K enregistrements de 2,5 min à 5 secondes.



10
votes

Cela pourrait être un temps pour le cloisonnement horizontal et le déplacement de champ de blob en mouvement dans une table séparée. Dans ce Article dans 'Note latérale rapide sur la partition verticale' L'auteur supprime un champ de varchar de plus gros à partir d'une table et augmente la vitesse d'une requête sur l'ordre de grandeur.

La raison est une traversée physique des données sur un disque devient significativement plus rapide s'il y a moins d'espace pour couvrir, donc les plus gros champs. ailleurs augmente les performances.

Aussi (et vous le faites probablement déjà), il est avantageux de réduire la taille de votre colonne d'index à son Minumum absolu (char (32) dans l'encodage ASCII pour MD5), car la taille de La clé est directement proportionnelle à la vitesse de son utilisation.

Si vous effectuez plusieurs inserts à la fois avec des tables INNODB, vous pouvez augmenter de manière significative la vitesse des insertions en les emballant dans la transaction et en faisant des inserts Mupliples dans une seule requête: xxx


4 commentaires

Le choix de la transaction de début semble la solution la plus simple actuelle. Cependant, j'ai quelques questions, car je ne le connais pas (je vais garder la RTFM dans l'intervalle). 1) Depuis que l'API de MySQL est en C, cela pourrait arriver que nous gâchons et essayons d'insérer des valeurs qui pointent sur NULL. Cela provoquera presque certainement que l'application client meure avec Segfault. La transaction sera-t-elle "sale" dans ce cas? Tout besoin de nettoyer? Comment? 2) Nous utilisons Myisam. La commutation à Innodb peut maintenant être douloureuse et / ou dangereuse. Connaissez-vous la performance de la transaction sur myisam? Merci d'avance pour vos commentaires.


MHISAM n'est pas transactionnel, cela signifie que vous pouvez ignorer en toute sécurité tout ce que j'ai écrit sur les transactions, mais l'instruction insertion avec plusieurs centaines ou des milliers d'insertions dans une requête accélérera également les choses à Myisam.


D'ACCORD. Savez-vous si l'insertion dans la syntaxe impose une limite à la longueur de la chaîne de requête? I.o.w., MySQL accepte-t-il un insert dans une chaîne de requête avec une longueur de (par exemple) des centaines de millions de caractères? Ça me sent des ennuis pour moi.


La limite est déterminée par max_allowed_packet dans le fichier de configuration. Je garde le mien 16m. J'ajoute généralement environ 10000 enregistrements dans une déclaration d'insertion



1
votes

Vos données correspondent-elles à la RAM? Sinon, obtenez plus de RAM jusqu'à ce que cela devienne peu économique (16g est généralement sur le point de la plupart des gens).

Ensuite, vos index correspondent-ils dans le tampon de la clé Myisam?

Si vous exécutez un système d'exploitation 32 bits, ne le faites pas. Une fois que vous êtes sur un système d'exploitation 64 bits, réglez le tampon de la clé environ 1/3 de la RAM. La RAM est utilisée par le cache du système d'exploitation pour mettre en cache des fichiers de données (qui ne fait que pour les insertions, mais est bénéfique pour sélectionner).

Avoir des tables multi-gigaoctets dans Myisam peut être une douleur car en cas d'arrêt impural, des opérations de réparation très longues sont nécessaires, mais

Ne changez pas les moteurs MySQL sans validation significative de votre application, cela changera le comportement de plusieurs manières (pas seulement des performances). Cela affectera l'utilisation de l'espace disque.


0 commentaires

1
votes

J'ai demandé à une Question aujourd'hui comme bien.

L'une des réponses fournies consiste à considérer l'insérer retardé de sorte qu'il passe dans la file d'attente d'insertion et est traitée lorsque le dB n'est pas aussi occupé.


3 commentaires

Basé sur une réponse dans ce fil, j'ai examiné la documentation retardée d'insertion de MySQL. Ils prétendent que les soins doivent être utilisés lors de l'option pour l'insertion retardée, car il peut détériorer les performances globales dans des insertions à une seule cliente par rapport aux insertions "normales".


OK - Je ne voyais pas que moi-même, bien que je cherche également à pouvoir accélérer le script qui effectue les insertions plutôt qu'à la performance de l'insert lui-même


Il convient de noter que l'insérer des œuvres retardées avec Myasam, mais pas innodb