MySQL单机调优
数据库独立一台服务器
MySQL体系结构
单机调优:
纵向升级:硬件内存,硬盘设备等升级
编译安装的参数
skip-name-resolv 跳过主机名解析
公共参数的调优
存储引擎的选择:
MyISAM
Innodb
Heap
针对不同的存储引擎进行优化
一、公共参数的调优
缓存方面的优化:
查看mysqld到底支持什么样的参数启动
1、show variables .....
2、查看官档
3、mysqld --verbose --help
sort_buffer_size参数
order by , group by
mysql> show variables like 'sort%';
+------------------+---------+
| Variable_name | Value |
+------------------+---------+
| sort_buffer_size | 2097144 | <---适当调整大一点,2~8m一般就足够了
+------------------+---------+
join_buffer_size参数
mysql> show variables like 'join%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| join_buffer_size | 131072 | <---适当调整大一点,2~8m一般就足够了
+------------------+--------+
read_rnd_buffer_size参数
以上的buffer都是每个连接线程独立分配。
连接线程调优:
mysql> show variables like 'thread%';
+-------------------+---------------------------+
| Variable_name | Value |
+-------------------+---------------------------+
| thread_cache_size | 0 |
| thread_handling | one-thread-per-connection |
| thread_stack | 196608 |
+-------------------+---------------------------+
thread_cache_size 每个线程独立分配
mysql> set global thread_cache_size=6;
建议值
thread_stack 512KB
查看状态
mysql> show status like 'thread%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 0 | 当前有多少空闲线程被缓存
| Threads_connected | 1 | 当前有多少个线程被连接着
| Threads_created | 1 | 从mysql启动以来,创建了多少个线程
| Threads_running | 1 | 当前多少连接线程是正在执行SQL
+-------------------+-------+
mysql支持的最大并发连接数
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 | 《---一般不会超过500 ~ 800,还要参考系统的性能。
+-----------------+-------+
如何判断连接线程池是否设定得正确?
mysql> show status like 'connections';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Connections | 5 | 《--mysql启动以来,一共被连接多少次。
+---------------+-------+
通过计算连接线程池的命中率来判断thread_cache_size的正确性。
thread_cache_hit = (Connections - Threads_created)/Connections * 100 %
如果保持在90以上,说明设置非常好。
table_open_cache
mysql> show variables like 'table_%_cache';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| table_definition_cache | 256 | 表定义缓存
| table_open_cache | 64 |
+------------------------+-------+
[mysqld]
table_open_cache=256
table_definition_cache=516
mysql> show status like 'open_table%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| Open_table_definitions | 14 | 参数应该要比这里出现的值要一点
| Open_tables | 8 |
+------------------------+-------+
其他网络参数调优
如果是本机连接,那么建议用socket
如果是远程连接,局域网比远程连接要快速很多。
如果不是非常机密的数据,尽可能不要使用SSL,性能会降低50%以上。
日志方面的优化:
二进制日志,错误日志,查询日志,慢查询日志
错误日志是必须打开。
查询日志强烈建议关闭。查询日志会记录客户端一切的操作,会产生大量的IO。
二进制日志文件,在一般比较重要的场合都建议打开。记录了所有对数据库的数据产生变更的SQL语句的执行情况。
它有什么作用:
基于时间点恢复
误操作的恢复
把数据库恢复到最新状态
MySQL复制:双机热备。
慢查询日志,专门记录执行超过指定时间的SQL语句。
二进制日志文件
mysql> show variables like '%binlog%';
+-----------------------------------------+------------+
| Variable_name | Value |
+-----------------------------------------+------------+
| binlog_cache_size | 32768 |
| binlog_direct_non_transactional_updates | OFF |
| binlog_format | STATEMENT |
| max_binlog_cache_size | 4294963200 |
| max_binlog_size | 1073741824 |
| sync_binlog | 0 |
+-----------------------------------------+------------+
binlog_cache_size 每个线程都是独立的,用于缓存二进制日志记录,当时机成熟的时候才把缓存中记录同步到二进制日志文件中。建议:如果大多数的更新操作都是比较复杂的,一次性更改的数据比较多,执行的操作比较多,那么应该适当增大该数值。
max_binlog_cache_size 所有线程的binlog_cache_size加起来不能超过这个值。
max_binlog_size 单个二进制日志文件的尺寸。
sync_binlog 非常重要,直接影响性能。关于到数据的完整性。
sync_binlog = 0 ,MySQL仅仅把cache中日志记录同步到日志文件中,MySQL不保证记录真的同步到磁盘,因为存在文件系统缓存,存在系统缓存,存在磁盘缓存。
sync_binlog = 1 ,每完成一次事务,MySQL就会把日志记录同步到日志文件中,而且还会进行flush操作(刷盘操作),保证数据不会留在文件系统缓存,而是真正的写入到磁盘文件上。
sync_binlog = N ,每完成N次事务 ...
0和1之间的性能最大可以相差5倍。一般来说,Master服务器都会设定1。
log-bin 静态参数,只能修改配置文件,然后重启mysql才能生效。
mysql> show status like '%binlog%';
慢查询日志
启动
[mysqld]
slow-query-log
slow_query_log_file=/data/mysqld-slow.log
log-slow-admin-statements
log-short-format
long_query_time=2
log-queries-not-using-indexes
mysql> show variables like '%long%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 | 一般的应用场合,超过2秒都可以认为是慢查询。
+-----------------+-----------+
分析工具
# mysqldumpslow -s at -t 10 /tmp/data/mysql-query-slow.log
二、针对不同存储引擎进行优化
常用的:
Memory(Heap)
不太重要的数据,但访问频繁的数据。就算丢了无所谓的数据。
MyISAM
数据文件和索引文家是分开的
小规模的数据环境 2000万条记录以下。
简单的查询。
适合读多写少的应用。
很容易出现表损坏,经常需要对表进行优化,修复。容易导致数据丢失。
小规模环境,MyISAM比Innodb性能要好。
不支持事务。
Innodb
数据和索引是放在一起。
对海量数据支持支持比较好。 400G以下。
对复杂查询支持比较好。
适合高并发环境。
支持事务。
能够对数据进行自动简单恢复。
针对MyISAM表进行优化
查询缓存优化
索引优化 <---影响性能重点
查询缓存
根据查询缓存的特点,表记录经常被修改的,这些表的所有查询都不应该放到缓存中,例如论坛的帖子表。经常被重复访问,但修改不平凡的表,可以放到查询缓存。
mysql> show variables like '%query_cache%';
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| have_query_cache | YES | 是否支持查询缓存的功能。
| query_cache_limit | 1048576 | 单个查询最多能够使用多少内存。
| query_cache_min_res_unit | 4096 | 单查询结果最低使用4K的内存
| query_cache_size | 0 | 使用多少的内存作为查询缓存
| query_cache_type | ON | 代表启用查询缓存的功能。
| query_cache_wlock_invalidate | OFF |
+------------------------------+---------+
query_cache_size 8M
修改查询缓存的大小
mysql> set global query_cache_size=8*1024*1024;
[mysqld]
query_cache_size=8M
=========================================================
导入access.log日志到数据库
处理之前的记录
1297557818.709 1830 192.168.1.3 TCP_MISS/200 324 GET http://www.hxuming.com/ip.php - DIRECT/205.209.136.218 text/html
处理之后的记录:
2011-02-13 08:43:38 192.168.1.3 http://www.hxuming.com/ip.php
# man awk
# awk '{print strftime( "%Y-%m-%d %H:%M:%S" , $1)"\t"$3"\t"$7}' access.log.1 > done.log
建立一个数据库log,建立一个表squid,设计表结构,然后导入数据
mysql> create database log default charset utf8;
mysql> use log;
mysql> create table squid (
-> id int unsigned not null primary key auto_increment,
-> acc_date timestamp,
-> ip varchar(15),
-> url varchar(256) );
mysql> load data local infile '/share/06/done.log' into table squid
-> fields terminated by '\t' ( acc_date,ip,url );
==========================================================
启用query_cache
mysql> select count(id) from squid where ip='192.168.1.3';
+-----------+
| count(id) |
+-----------+
| 26 |
+-----------+
1 row in set (4.54 sec)
mysql> select count(id) from squid where ip='192.168.1.3';
+-----------+
| count(id) |
+-----------+
| 26 |
+-----------+
1 row in set (0.00 sec)
mysql> selecT count(id) from squid where ip='192.168.1.3';
+-----------+
| count(id) |
+-----------+
| 26 |
+-----------+
1 row in set (4.44 sec)
mysql> selecT count(id) from squid where ip='192.168.1.3';
+-----------+
| count(id) |
+-----------+
| 26 |
+-----------+
1 row in set (0.00 sec)
mysql> insert into squid values (NULL,now(),'10.1.1.22','http://www.upl.com');
mysql> selecT count(id) from squid where ip='192.168.1.3';
+-----------+
| count(id) |
+-----------+
| 26 |
+-----------+
1 row in set (4.20 sec)
如何控制使用query_cache
SQL_CACHE,SQL_NO_CACHE
不会查缓存,也不会把结果放到缓存当中。
mysql> select SQL_NO_CACHE count(id) from squid where ip='192.168.1.3';
查看状态数据:
mysql> show status like '%Qcache%';
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Qcache_free_blocks | 1 | 数字越大,碎片越多。
| Qcache_free_memory | 8378312 | 剩余多少内存空闲
| Qcache_hits | 10 | query_cache命中的次数
| Qcache_inserts | 23 | 没有命中,需要把查询结果放到query_cache
| Qcache_lowmem_prunes | 0 | 有多少个查询因为内存不足,而需要清掉旧数据
| Qcache_not_cached | 4 | 由于各种原因不能缓存的查询次数。
| Qcache_queries_in_cache | 1 | 有多少个查询语句的结果被保存
| Qcache_total_blocks | 4 | 用了多少个block
+-------------------------+---------+
通过计算query_cache命中率来衡量设定是否正确。
命中率 = Qcache_hits / (Qcache_hits + Qcache_inserts) * 100 %
一般95%以上才算是设定正确。