7 votes

mysql est lent avec InnoDB pendant l'insertion par rapport à MYISAM

Je viens d'installer MySQL 5.5 qui a le moteur InnoDB par défaut et j'ai réalisé que les requêtes INSERT sont vraiment lentes ! Après avoir désactivé general-log, ça s'est un peu amélioré mais c'est toujours aussi lent. J'ai analysé mysql pour trouver le problème mais aucune chance.

Voici un point de comparaison :

Test d'un tableau MYISAM (n) utilisant 500 lignes. - 5866 insertions par seconde. - 128866 lectures de lignes par seconde. - 56306 mises à jour par seconde.

Test d'une table INNODB (n) utilisant 500 lignes. - 9 insertions par seconde. - 28539 lectures de lignes par seconde. - 4358 mises à jour par seconde.

J'ai 9 requêtes d'insertion sur InnoDB contre 5866 avec MyISAM.

Voici mon my.ini (Windows 8 64bit) :

[mysql]

default-character-set=utf8
no-auto-rehash

[mysqld]
max_allowed_packet = 500M
table_open_cache = 512

# The TCP/IP Port the MySQL Server will listen on
port=3306

# Path to installation directory. All paths are usually resolved relative to this.
basedir="C:\Program Files\MySQL\MySQL Server 5.5\"

# Path to the database root
datadir="D:\MySQL Datafiles\data\"

# The default character set that will be used when a new schema or table is
# created and no character set is defined
character-set-server=utf8

# The default storage engine that will be used when create new tables when
# default-storage-engine=MYISAM

# Set the SQL mode to strict
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

# Enable Windows Authentication
# plugin-load=authentication_windows.dll

# General and Slow logging.
#log-output=FILE
#general-log=0
#general_log_file="POOYA.log"
#slow-query-log=0
#slow_query_log_file="POOYA-slow.log"
#long_query_time=10

#innodb_flush_log_at_trx_commit = 2

# Binary Logging.
# log-bin

# Error Logging.
log-error="POOYA.err"

max_connections=100

query_cache_size=32M

table_cache=512

tmp_table_size=64M

thread_cache_size=8

myisam_max_sort_file_size=100G

myisam_sort_buffer_size=64M

key_buffer_size=256M

# Size of the buffer used for doing full table scans of MyISAM tables.
# Allocated per thread, if a full scan is needed.
read_buffer_size=1M
read_rnd_buffer_size=4M

# This buffer is allocated when MySQL needs to rebuild the index in
# REPAIR, OPTIMZE, ALTER table statements as well as in LOAD DATA INFILE
# into an empty table. It is allocated per thread so be careful with
# large settings.
sort_buffer_size=1M

#*** INNODB Specific options ***
# innodb_data_home_dir=0.0

# Use this option if you have a MySQL server with InnoDB support enabled
# but you do not plan to use it. This will save memory and disk space
# and speed up some things.
# skip-innodb

# Additional memory pool that is used by InnoDB to store metadata
# information.  If InnoDB requires more memory for this purpose it will
# start to allocate it from the OS.  As this is fast enough on most
# recent operating systems, you normally do not need to change this
# value. SHOW INNODB STATUS will display the current amount used.
innodb_additional_mem_pool_size=64M

# If set to 1, InnoDB will flush (fsync) the transaction logs to the
# disk at each commit, which offers full ACID behavior. If you are
# willing to compromise this safety, and you are running small
# transactions, you may set this to 0 or 2 to reduce disk I/O to the
# logs. Value 0 means that the log is only written to the log file and
# the log file flushed to disk approximately once per second. Value 2
# means the log is written to the log file at each commit, but the log
# file is only flushed to disk approximately once per second.
innodb_flush_log_at_trx_commit=1

# The size of the buffer InnoDB uses for buffering log data. As soon as
# it is full, InnoDB will have to flush it to disk. As it is flushed
# once per second anyway, it does not make sense to have it very large
# (even with long transactions).
innodb_log_buffer_size=8M

# InnoDB, unlike MyISAM, uses a buffer pool to cache both indexes and
# row data. The bigger you set this the less disk I/O is needed to
# access data in tables. On a dedicated database server you may set this
# parameter up to 80% of the machine physical memory size. Do not set it
# too large, though, because competition of the physical memory may
# cause paging in the operating system.  Note that on 32bit systems you
# might be limited to 2-3.5G of user level memory per process, so do not
# set it too high.
innodb_buffer_pool_size=512M

# Size of each log file in a log group. You should set the combined size
# of log files to about 25%-100% of your buffer pool size to avoid
# unneeded buffer pool flush activity on log file overwrite. However,
# note that a larger logfile size will increase the time needed for the
# recovery process.
innodb_log_file_size=49M

# Number of threads allowed inside the InnoDB kernel. The optimal value
# depends highly on the application, hardware as well as the OS
# scheduler properties. A too high value may lead to thread thrashing.
innodb_thread_concurrency=17
[mysqldump]
quick
max_allowed_packet = 16M

[myisamchk]
key_buffer_size = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

J'ai modifié ce fichier pour obtenir de hautes performances, et je n'ai jamais eu de problème avec mysql 5.1.

9voto

Najzero Points 2110

Comme demandé, la journalisation au niveau du commit cause souvent beaucoup de stress sur le disque et par conséquent réduit le débit de données sur les instances mysql avec inno pour une grande partie.

Configurer votre mysql.ini à innodb_flush_log_at_trx_commit = 0 (ou 2) permet souvent de résoudre ce problème.

Veuillez noter que les règles ACID aimeraient que cette valeur soit à 1...

1voto

Mark Howard Points 56

Vous pouvez également le définir directement sur la ligne de commande MySQL en utilisant la commande suivante :

SET GLOBAL innodb_flush_log_at_trx_commit = 0;

1voto

Ajoutez-vous les rangs un par un ?

Si vous ajoutez plusieurs lignes par transaction, cela aide beaucoup .

# 1:
INSERT INTO my_table VALUES (1, "A");
INSERT INTO my_table VALUES (2, "B");

# 2:
INSERT INTO my_table VALUES (1, "A"),(2, "B");

# 3:
BEGIN;
INSERT INTO my_table VALUES (1, "A");
INSERT INTO my_table VALUES (2, "B");
COMMIT;

En InnoDB, les numéros 2 et 3 seront beaucoup plus rapides que le numéro 1.

2 aide aussi avec MyISAM, mais pas autant. En chiffres bruts, j'ai vu cela accélérer MyISAM de 2x, et InnoDB de 100x.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X