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%以上才算是设定正确。