MySQL Slow Writes

8

Les insertions dans le tableau suivant prennent jusqu'à 70 secondes pour terminer:

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Il y a environ 100 000 lignes dans le tableau, et cela prend 7 Mo sur le disque.

Y a-t-il des paramètres dans MySQL qui peuvent améliorer les performances d'écriture?

Mon my.cnfdossier est le suivant:

log-slow-queries="/var/log/mysql/slow-query.log"
long_query_time=1 
log-queries-not-using-indexes

innodb_buffer_pool_size=4G
innodb_log_buffer_size=4M
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=8
innodb_flush_method=O_DIRECT

query_cache_size = 6G
key_buffer_size = 284M
query_cache_limit = 1024M
thread_cache_size = 128
table_cache = 12800

sort_buffer_size=2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M

read_buffer_size=128K

open_files_limit               = 1000
table_definition_cache         = 1024
table_open_cache               = 6000

max_heap_table_size=512M
tmp_table_size=4096M

max_connections=1000

thread_concurrency = 24

Voici la configuration matérielle:

  • Dell R710
  • RAID10
  • RAM 48G

Compte tenu de ce matériel, je ne m'attendrais pas à ce que le problème soit un goulot d'étranglement matériel.

Ronn0
la source
Pouvez-vous fournir des données objectives? Journaux, votre méthodologie de test / benchmarking et vos résultats, ce genre de chose?
womble
Quel type de journaux aimeriez-vous voir? La seule chose que je vois pourquoi cela prend autant de temps est en detop . Je testerais des choses comme changer la table en une table myisam, des limites de mémoire plus élevées, des threads plus élevés.
Ronn0
Le meilleur réglage pour améliorer mysql ... est de passer au postgres lol
Antony Gibbs
thread_concurrency = 24 n'a aucun effet ... vous pouvez vider cette ligne
Antony Gibbs

Réponses:

16

OBSERVATION # 1

La toute première chose qui attire mon attention est la structure de la table

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Veuillez noter que l' categoriesIdindex et la CLÉ PRIMAIRE commencent par la même colonne. Il s'agit d'un index redondant. Étant donné que cette table est InnoDB, l' categoriesIdindex est redondant pour une autre raison: tous les index secondaires contiennent des clés dans gen_clust_index (alias Clustered Index; voir à quoi sert gen_clust_index dans mysql? )

Si vous supprimez l' categoriesIdindex avec

ALTER TABLE productsCategories DROP INDEX categoriesId;

cela améliorera considérablement les INSERT, car vous n'aurez pas à effectuer de maintenance d'index secondaire et en cluster supplémentaire.

OBSERVATION # 2

Si vous effectuez des opérations d'insertion en bloc, vous avez besoin d'un grand tampon d'insertion en bloc .

Veuillez consulter mes précédents articles à ce sujet:

OBSERVATION # 3

La taille de votre fichier journal est bien trop petite !!! Il doit représenter 25% du pool de tampons InnoDB, qui dans votre cas doit être 1G. Voir mon article sur la façon de redimensionner les fichiers journaux InnoDB .

OBSERVATION # 4

Veuillez ne pas définir innodb_thread_concurrency !!! J'ai appris de première main à Percona Live NYC pour laisser ce paramètre tranquille . Il est désactivé par défaut dans MySQL 5.5, MySQL 5.1 InnoDB Plugin et Percona Server 5.1+.

OBSERVATION # 5

Vous devez utiliser innodb_file_per_table. Si cette option est désactivée, je fais de la maintenance des fichiers sur ibdata1 un cauchemar. Veuillez lire mon article sur la façon de nettoyer InnoDB pour l'implémenter .

OBSERVATION # 6

Si vous utilisez MySQL 5.5 ou Percona Server, vous devez définir certaines options pour que InnoDB utilise plusieurs processeurs / plusieurs cœurs. Veuillez consulter mon article sur ces paramètres .

OBSERVATION # 7

Vous avez innodb_log_buffer_size=4M. La valeur par défaut est 8M. Cela provoquera deux fois plus de vidage dans les journaux de rétablissement. Cela neutralisera également votre innodb_flush_log_at_trx_commit=2réglage. Veuillez le régler sur 32M. Consultez également la documentation MySQL sur innodb_log_buffer_size .

À la lumière de ces observations, veuillez ajouter ou remplacer les paramètres suivants:

[mysqld]
innodb_thread_concurrency = 0
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_io_capacity = 5000
innodb_file_per_table
innodb_log_file_size=1G
innodb_log_buffer_size=1G
bulk_insert_buffer_size = 256M
RolandoMySQLDBA
la source
Ouah merci! J'ai imprimé tous les points et je travaille dessus maintenant et je les enregistre dans le cerveau pour aider d'autres personnes à l'avenir. Merci beaucoup!
Ronn0
2
query_cache_sizeest énorme aussi. Chaque insert nécessitera jusqu'à 6 Go de cache pour être vidé.
Aaron Brown
@AaronBrown Je suis d'accord. J'ai lu dans le livre High Performance MySQL qu'InnoDB fait des choses fastidieuses avec l'ID de transaction sur la table InnoDB dans le cache de requête, ce qui rend inutile, sans parler de la lenteur, l'utilisation d'un cache de requête. En fait, MySQL 4.1 a le cache de requête désactivé pour InnoDB.
RolandoMySQLDBA
Je pense que le cache de requête est complètement séparé du moteur de stockage. Il sérialise essentiellement toutes les opérations d'écriture en forçant tout à passer et à analyser le cache de requêtes pour les requêtes à invalider. Je n'ai jamais trouvé de cas d'utilisation pour cela et cela a toujours causé des problèmes.
Aaron Brown
une dernière chose à ajouter: query_cache_size = 6G <- c'est totalement et complètement absurde. Le cache de requêtes est souvent mieux désactivé et ne doit certainement pas être supérieur à 32M ou 64M. La surcharge de maintenance d'un cache de requêtes 6G nuit certainement aux performances.
Gavin Towey
0

Vous devez vérifier innodb_log_file_size, le paramètre par défaut est 5M, ce qui est assez faible pour les configurations à écriture intensive. Pensez à le régler sur 100M. Vous devrez supprimer les anciens ib_logfile*fichiers afin de démarrer la base de données avec de nouveaux paramètres. Veuillez ne pas supprimer les fichiers journaux pendant que le serveur DB est en cours d'exécution, vous devrez d'abord l'arrêter. Vous devriez probablement sauvegarder les anciens fichiers journaux en premier, et pas seulement les supprimer.

Alex
la source