372 lines
12 KiB
Markdown
372 lines
12 KiB
Markdown
---
|
||
categories: databases
|
||
title: Howto MySQL : optimisation avancée.
|
||
...
|
||
|
||
Pour le guide d'installation et d'usage courant, consultez [/HowtoMySQL]().
|
||
|
||
## mysqltuner
|
||
|
||
Après quelque temps d'utilisation, il est intéressant de regarder les résultats du script `mysqltuner.pl` téléchargeable via <http://mysqltuner.pl/>
|
||
|
||
~~~
|
||
# perl mysqltuner.pl
|
||
|
||
>> MySQLTuner 1.0.1 - Major Hayden <major@mhtx.net>
|
||
>> Bug reports, feature requests, and downloads at http://mysqltuner.com/
|
||
>> Run with '--help' for additional options and output filtering
|
||
|
||
-------- General Statistics --------------------------------------------------
|
||
[--] Skipped version check for MySQLTuner script
|
||
[OK] Currently running supported MySQL version 5.0.51a-24+lenny3
|
||
[OK] Operating on 64-bit architecture
|
||
|
||
-------- Storage Engine Statistics -------------------------------------------
|
||
[--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
|
||
|
||
|
||
[--] Data in MyISAM tables: 556M (Tables: 3831)
|
||
[--] Data in InnoDB tables: 34M (Tables: 968)
|
||
[--] Data in MEMORY tables: 3K (Tables: 9)
|
||
[!!] Total fragmented tables: 335
|
||
|
||
-------- Performance Metrics -------------------------------------------------
|
||
[--] Up for: 20h 59m 23s (2M q [29.301 qps], 31K conn, TX: 5B, RX: 300M)
|
||
[--] Reads / Writes: 23% / 77%
|
||
[--] Total buffers: 58.0M global + 2.6M per thread (100 max threads)
|
||
[OK] Maximum possible memory usage: 320.5M (10% of installed RAM)
|
||
[OK] Slow queries: 0% (1/2M)
|
||
[OK] Highest usage of available connections: 11% (11/100)
|
||
[OK] Key buffer size / total MyISAM indexes: 16.0M/216.0M
|
||
[OK] Key buffer hit rate: 97.0% (31M cached / 942K reads)
|
||
[OK] Query cache efficiency: 77.2% (921K cached / 1M selects)
|
||
[!!] Query cache prunes per day: 78490
|
||
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 59K sorts)
|
||
[!!] Joins performed without indexes: 29333
|
||
[OK] Temporary tables created on disk: 25% (22K on disk / 88K total)
|
||
[OK] Thread cache hit rate: 99% (26 created / 31K connections)
|
||
[!!] Table cache hit rate: 0% (64 open / 82K opened)
|
||
[OK] Open file limit used: 12% (126/1K)
|
||
[OK] Table locks acquired immediately: 99% (1M immediate / 1M locks)
|
||
[!!] InnoDB data size / buffer pool: 34.4M/8.0M
|
||
|
||
-------- Recommendations -----------------------------------------------------
|
||
General recommendations:
|
||
Run OPTIMIZE TABLE to defragment tables for better performance
|
||
MySQL started within last 24 hours - recommendations may be inaccurate
|
||
Enable the slow query log to troubleshoot bad queries
|
||
Adjust your join queries to always utilize indexes
|
||
Increase table_cache gradually to avoid file descriptor limits
|
||
Variables to adjust:
|
||
query_cache_size (> 16M)
|
||
join_buffer_size (> 128.0K, or always use indexes with joins)
|
||
table_cache (> 64)
|
||
innodb_buffer_pool_size (>= 34M)
|
||
~~~
|
||
|
||
## tunning-prime
|
||
|
||
Il y a aussi [tunning-prime](https://launchpad.net/mysql-tuning-primer/trunk) qui est plus verbeux, il complète bien *mysqltuner*.
|
||
|
||
~~~
|
||
-- MYSQL PERFORMANCE TUNING PRIMER --
|
||
- By: Matthew Montgomery -
|
||
|
||
MySQL Version 5.1.49-3-log x86_64
|
||
|
||
Uptime = 102 days 22 hrs 6 min 25 sec
|
||
Avg. qps = 196
|
||
Total Questions = 1747455439
|
||
Threads Connected = 29
|
||
|
||
Server has been running for over 48hrs.
|
||
It should be safe to follow these recommendations
|
||
|
||
To find out more information on how each of these
|
||
runtime variables effects performance visit:
|
||
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html
|
||
Visit http://www.mysql.com/products/enterprise/advisors.html
|
||
for info about MySQL's Enterprise Monitoring and Advisory Service
|
||
|
||
SLOW QUERIES
|
||
The slow query log is enabled.
|
||
Current long_query_time = 2.000000 sec.
|
||
You have 533228 out of 1747455460 that take longer than 2.000000 sec. to complete
|
||
Your long_query_time seems to be fine
|
||
|
||
BINARY UPDATE LOG
|
||
The binary update log is NOT enabled.
|
||
You will not be able to do point in time recovery
|
||
See http://dev.mysql.com/doc/refman/5.1/en/point-in-time-recovery.html
|
||
|
||
WORKER THREADS
|
||
Current thread_cache_size = 32
|
||
Current threads_cached = 12
|
||
Current threads_per_sec = 0
|
||
Historic threads_per_sec = 0
|
||
Your thread_cache_size is fine
|
||
|
||
MAX CONNECTIONS
|
||
Current max_connections = 250
|
||
Current threads_connected = 28
|
||
Historic max_used_connections = 250
|
||
The number of used connections is 100% of the configured maximum.
|
||
You should raise max_connections
|
||
|
||
INNODB STATUS
|
||
Current InnoDB index space = 34 M
|
||
Current InnoDB data space = 77 M
|
||
Current InnoDB buffer pool free = 98 %
|
||
Current innodb_buffer_pool_size = 6.00 G
|
||
Depending on how much space your innodb indexes take up it may be safe
|
||
to increase this value to up to 2 / 3 of total system memory
|
||
|
||
MEMORY USAGE
|
||
Max Memory Ever Allocated : 7.67 G
|
||
Configured Max Per-thread Buffers : 671 M
|
||
Configured Max Global Buffers : 7.01 G
|
||
Configured Max Memory Limit : 7.67 G
|
||
Physical Memory : 23.58 G
|
||
Max memory limit seem to be within acceptable norms
|
||
|
||
KEY BUFFER
|
||
Current MyISAM index space = 4.13 G
|
||
Current key_buffer_size = 512 M
|
||
Key cache miss rate is 1 : 4965
|
||
Key buffer free ratio = 8 %
|
||
You could increase key_buffer_size
|
||
It is safe to raise this up to 1/4 of total system memory;
|
||
assuming this is a dedicated database server.
|
||
|
||
QUERY CACHE
|
||
Query cache is enabled
|
||
Current query_cache_size = 512 M
|
||
Current query_cache_used = 52 M
|
||
Current query_cache_limit = 8 M
|
||
Current Query cache Memory fill ratio = 10.34 %
|
||
Current query_cache_min_res_unit = 4 K
|
||
Your query_cache_size seems to be too high.
|
||
Perhaps you can use these resources elsewhere
|
||
MySQL won't cache query results that are larger than query_cache_limit in size
|
||
|
||
SORT OPERATIONS
|
||
Current sort_buffer_size = 2 M
|
||
Current read_rnd_buffer_size = 256 K
|
||
Sort buffer seems to be fine
|
||
|
||
JOINS
|
||
Current join_buffer_size = 132.00 K
|
||
You have had 9527 queries where a join could not use an index properly
|
||
You should enable "log-queries-not-using-indexes"
|
||
Then look for non indexed joins in the slow query log.
|
||
If you are unable to optimize your queries you may want to increase your
|
||
join_buffer_size to accommodate larger joins in one pass.
|
||
|
||
Note! This script will still suggest raising the join_buffer_size when
|
||
ANY joins not using indexes are found.
|
||
|
||
OPEN FILES LIMIT
|
||
Current open_files_limit = 5260 files
|
||
The open_files_limit should typically be set to at least 2x-3x
|
||
that of table_cache if you have heavy MyISAM usage.
|
||
You currently have open more than 75% of your open_files_limit
|
||
You should set a higher value for open_files_limit in my.cnf
|
||
|
||
TABLE CACHE
|
||
Current table_open_cache = 2500 tables
|
||
Current table_definition_cache = 256 tables
|
||
You have a total of 5084 tables
|
||
You have 2500 open tables.
|
||
Current table_cache hit rate is 0%
|
||
, while 100% of your table cache is in use
|
||
You should probably increase your table_cache
|
||
You should probably increase your table_definition_cache value.
|
||
|
||
TEMP TABLES
|
||
Current max_heap_table_size = 64 M
|
||
Current tmp_table_size = 256 M
|
||
Of 8549110 temp tables, 35% were created on disk
|
||
Effective in-memory tmp_table_size is limited to max_heap_table_size.
|
||
Perhaps you should increase your tmp_table_size and/or max_heap_table_size
|
||
to reduce the number of disk-based temporary tables
|
||
Note! BLOB and TEXT columns are not allow in memory tables.
|
||
If you are using these columns raising these values might not impact your
|
||
ratio of on disk temp tables.
|
||
|
||
TABLE SCANS
|
||
Current read_buffer_size = 128 K
|
||
Current table scan ratio = 50592 : 1
|
||
You have a high ratio of sequential access requests to SELECTs
|
||
You may benefit from raising read_buffer_size and/or improving your use of indexes.
|
||
|
||
TABLE LOCKING
|
||
Current Lock Wait ratio = 1 : 115
|
||
You may benefit from selective use of InnoDB.
|
||
If you have long running SELECT's against MyISAM tables and perform
|
||
frequent updates consider setting 'low_priority_updates=1'
|
||
If you have a high concurrency of inserts on Dynamic row-length tables
|
||
consider setting 'concurrent_insert=2'.
|
||
~~~
|
||
|
||
## Support des _large pages_
|
||
|
||
Le support des _large pages_ permet d'avoir une gestion différente de la mémoire, notamment
|
||
utile pour les requêtes avec des besoins en mémoire important. Ceci n'est utile dans la plupart
|
||
des cas a priori.
|
||
|
||
Pour l'activer, il faudra vérifier que le kernel supporte les _large pages_ :
|
||
|
||
~~~
|
||
# cat /proc/meminfo | grep -i huge
|
||
HugePages_Total: 0
|
||
HugePages_Free: 0
|
||
HugePages_Rsvd: 0
|
||
HugePages_Surp: 0
|
||
Hugepagesize: 2048 kB
|
||
~~~
|
||
|
||
Si cela ne renvoie rien c'est que le support des _large pages_ est désactivé.
|
||
(options `CONFIG_HUGETLBFS` et `CONFIG_HUGETLB_PAGE` du noyau).
|
||
|
||
Pour l'activer, on fera les opérations suivantes :
|
||
|
||
~~~
|
||
# Set the number of pages to be used.
|
||
# Each page is normally 2MB, so a value of 20 = 40MB.
|
||
# This command actually allocates memory, so this much
|
||
# memory must be available.
|
||
|
||
# echo 20 > /proc/sys/vm/nr_hugepages
|
||
|
||
# Set the group number that is permitted to access this
|
||
# memory (110 in this case). The mysql user must be a
|
||
# member of this group.
|
||
|
||
# echo 110 > /proc/sys/vm/hugetlb_shm_group
|
||
|
||
# Increase the amount of shmem permitted per segment
|
||
# (900M in this case).
|
||
|
||
# echo 943718400 > /proc/sys/kernel/shmmax
|
||
~~~
|
||
|
||
Ajouter dans le `/etc/security/limits.conf` :
|
||
|
||
~~~
|
||
ulimit -l unlimited
|
||
~~~
|
||
|
||
Enfin dans la configuration MySQL :
|
||
|
||
~~~{.ini}
|
||
[mysqld]
|
||
large-pages
|
||
~~~
|
||
|
||
Mais encore une fois, cela n'est pas nécessaire dans la plupart des cas.
|
||
|
||
### À propos de shmmax
|
||
|
||
> Since shm (shared memory) in Unix/Linux is only used to share memory between independent processes and mysql server is a single process (multi-threaded), I am convinced that shmmax value has no consequence on mysql. (OTOH Oracle has a multiprocess architecture and uses shared memory).
|
||
|
||
Il semblerait que contrairement à PostgreSQL, il ne soit pas nécessaire d'augmenter le `kernel.shmmax` dans la plupart des cas [Source](http://lists.mysql.com/mysql/135019).
|
||
|
||
## Benchmark avec sql-bench
|
||
|
||
Récupérer les fichiers de sql-bench avec bazar :
|
||
|
||
~~~
|
||
$ bzr branch lp:sql-bench
|
||
~~~
|
||
|
||
Installer quelques outils nécessaires pour le benchmark :
|
||
|
||
~~~
|
||
# apt install libclass-dbi-perl libdbd-mysql-perl mysql-client-5.1
|
||
~~~
|
||
|
||
Créer une base de données de test :
|
||
|
||
~~~
|
||
# mysqladmin create test
|
||
# mysql
|
||
mysql> GRANT ALL PRIVILEGES ON test.* TO 'test'@localhost IDENTIFIED BY 'test';
|
||
~~~
|
||
|
||
Résultat du benchmark :
|
||
|
||
~~~
|
||
# cd ~/mysql-5.5.12/sql-bench/sql-bench/
|
||
# perl run-all-tests --user='test' --password='test'
|
||
Benchmark DBD suite: 2.15
|
||
Date of test: 2011-05-19 14:01:18
|
||
Running tests on: Linux 2.6.32-5-amd64 x86_64
|
||
Arguments:
|
||
Comments:
|
||
Limits from:
|
||
Server version: MySQL 5.1.49 3
|
||
Optimization: None
|
||
Hardware:
|
||
|
||
Operation seconds usr sys cpu tests
|
||
alter-table: Total time: 16 wallclock secs ( 0.08 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.08 CPU)
|
||
ATIS: Total time: 4 wallclock secs ( 2.34 usr 0.77 sys + 0.00 cusr 0.00 csys = 3.11 CPU)
|
||
big-tables: Total time: 5 wallclock secs ( 0.92 usr 2.47 sys + 0.00 cusr 0.00 csys = 3.39 CPU)
|
||
connect: Total time: 18 wallclock secs ( 4.85 usr 2.88 sys + 0.00 cusr 0.00 csys = 7.73 CPU)
|
||
create: Total time: 53 wallclock secs ( 3.86 usr 1.75 sys + 0.00 cusr 0.00 csys = 5.61 CPU)
|
||
insert: Total time: 618 wallclock secs (221.17 usr 14.05 sys + 0.00 cusr 0.00 csys = 235.22 CPU)
|
||
select: Total time: 49 wallclock secs (11.28 usr 8.95 sys + 0.00 cusr 0.00 csys = 20.23 CPU)
|
||
transactions: Test skipped because the database doesn't support transactions
|
||
wisconsin: Total time: 5 wallclock secs ( 1.93 usr 0.47 sys + 0.00 cusr 0.00 csys = 2.40 CPU)
|
||
TOTALS 788.00 244.02 30.97 274.99 2913950
|
||
~~~
|
||
|
||
## Cache
|
||
|
||
La première fois que vous faites un SELECT, son résultat sera conservé dans le _Query Cache_ de MySQL.
|
||
Si ce cache n'a pas été invalidé, la même requête retournera directement son résultat à partir de cache,
|
||
soit un résultat quasi-instantané.
|
||
|
||
On peut avoir des stats sur ce _Query Cache_ :
|
||
|
||
~~~
|
||
mysql> SHOW STATUS LIKE 'Qcache%';
|
||
+-------------------------+-----------+
|
||
| Variable_name | Value |
|
||
+-------------------------+-----------+
|
||
| Qcache_free_blocks | 28 |
|
||
| Qcache_free_memory | 242412400 |
|
||
| Qcache_hits | 226483735 |
|
||
| Qcache_inserts | 22334124 |
|
||
| Qcache_lowmem_prunes | 5337097 |
|
||
| Qcache_not_cached | 3323695 |
|
||
| Qcache_queries_in_cache | 4229 |
|
||
| Qcache_total_blocks | 8919 |
|
||
+-------------------------+-----------+
|
||
8 rows in set (0.00 sec)
|
||
~~~
|
||
|
||
On peut vider ce cache ainsi :
|
||
|
||
~~~
|
||
mysql> RESET QUERY CACHE;
|
||
Query OK, 0 rows affected (0.00 sec)
|
||
~~~
|
||
|
||
## tmpdir
|
||
|
||
Il peut être intéressant de changer le chemin du tmpdir pour le mettre sur un disque plus rapide ou plus gros par exemple.
|
||
|
||
~~~
|
||
# mkdir /ssd/mysqltmp
|
||
# chown mysql: /ssd/mysqltmp
|
||
# chmod 700 /ssd/mysqltmp
|
||
~~~
|
||
|
||
Puis dans la configuration MySQL :
|
||
|
||
~~~{.ini}
|
||
[mysqld]
|
||
tmpdir = /ssd/mysqltmp
|
||
~~~
|