服务器优化原则:
1.内存里的数据要比磁盘上的数据访问起来快;
2.让数据尽可能长时间地留在内存里能减少磁盘读写活动的工作量;
3.让索引信息留在内存里要比让数据记录的内容留在内存里更重要。
针对以上几个原则,我们应该调整服务器:
增加服务器的缓存区容量,以便数据在内存在停留的时间长一点,以减少磁盘I/0。下面介绍几个重要的缓冲区:
===========================================================================================
1.数据表缓冲区(table_cache)
数据表缓冲区存放着与打开的数据表相的信息,它的大小可由服务器参数“table_cache”设置。Opened_tables参数 记录服务器进行过多少次
数据表打开操作,如果该值变化很大,就可能是数据表缓冲区已满,需把一些不常用的表移出缓冲区,以腾出空打开新的数据表。可用以下命令
查看Opened_tables的值: SHOW STATUS LIKE 'Opened_tables';
说明(针对某个表只记录一次.重复对一个表不记录.)
[root@localhost ~]# cat /etc/my.cnf
table_cache = 256
mysql> show status like 'Opened_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Opened_tables | 13 |
+---------------+-------+
1 row in set (0.00 sec)
显示打开表的活动
mysql> SHOW STATUS LIKE 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 5000 |
| Opened_tables | 195 |
+---------------+-------+
2 rows in set (0.00 sec)
说明
目前有 5,000 个表是打开的,有 195 个表需要打开,因为现在缓存中已经没有可用文件描述符了(由于统计信息在前面已经清除了,
因此可能会存在 5,000 个打开表中只有 195 个打开记录的情况)。如果 Opened_tables 随着重新运行 SHOW STATUS 命令快速增加,
就说明缓存命中率不够。如果 Open_tables 比 table_cache 设置小很多,就说明该值太大了(不过有空间可以增长总不是什么坏事)。
例如,使用 table_cache = 5000 可以调整表的缓存。
============================================================================================================
2.索引缓存(key_buffer)
在MyISAM和ISAM数据表中,索引被缓存在“key buffer”里,它的大小由服务器参数“key_buffer_size”来控制。系统默认的大小是8M,如果
内存充足的话可适当扩大该值,以使更多索引块缓存在该区里,以加快索引的速度。
InnoDB和BDB数据表也各有一个缓冲区,分别叫innodb_buffer_pool_size和bdb_cache_size。InnoDB还有 一个日志缓冲区叫innodb_log_buffer_size。
说明(myisam属于非事务安全型,innodb和bdb属于事务安全型)
[root@localhost ~]# cat /etc/my.cnf
#bdb_cache_size = 64M
key_buffer = 256M (内存的一半或1/4)
#innodb_buffer_pool_size = 256M
确定关键字效率
mysql> show status like '%key_read%';
+-------------------+-----------+
| Variable_name | Value |
+-------------------+-----------+
| Key_read_requests | 163554268 |
| Key_reads | 98247 |
+-------------------+-----------+
2 rows in set (0.00 sec)
Key_reads 代表命中磁盘的请求个数, Key_read_requests 是总数。命中磁盘的读请求数除以读请求总数就是不中比率 ——
在本例中每 1,000 个请求,大约有 0.6 个没有命中内存。如果每 1,000 个请求中命中磁盘的数目超过 1 个,就应该考虑增大关键字缓冲区了。
例如,key_buffer = 384M 会将缓冲区设置为 384MB
Key_reads与Key_read_requests之比越小越好
========================================================================================================================
3.查询缓冲区(query_cache_size)
自4.0.1开始,MySQL多了一个缓冲区,叫查询缓冲区,主要用来存放重复执行的查询文本和结果,当再次遇到相同的查询,服务器会 直接从缓冲区中返回结果。
该功能是内建的功能,如不想支持该功能,可在编译服务器时用configure脚本的--without-query-cache选项去掉该功能。
查询缓冲区由三个服务器参数控制,分别是:
1、query_cache_size
控制缓冲区的大小,如果该值为0,则禁用查询缓冲功能。设置方法是在选项文件中设置:
[mysqld]
set-variable = query_cache_size = 16M
这样就设置了一个16M的查询缓冲区
2、query_cache_limit
缓冲结果集的最大容量(以字节为单位),如果查询的结果集大于该值,则不缓冲该值。
3、query_cache_type
缓冲区的操作模式。
0表示不进行缓冲;
1表示除SELECT SQL_NO_CACHE开头的查询外,其余的都缓冲;
2表示只对以SELECT SQL_ON_CACHE开头的查询进行缓冲。
[root@localhost ~]# cat /etc/my.cnf
#query_cache_type=0
query_cache_size= 16M
query_cache_limit=2M
显示查询缓冲区的内容
mysql> show status like 'qcache%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 16768448 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 13 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+----------+
8 rows in set (0.01 sec)
mysql> flush query cache;
Query OK, 0 rows affected (0.00 sec)
mysql>
说明:
MySQL 查询缓存变量
变量名 说明
Qcache_free_blocks 缓存中相邻内存块的个数。数目大说明可能有碎片。FLUSH QUERY CACHE 会对缓存中的碎片进行整理,从而得到一个空闲块。
Qcache_free_memory 缓存中的空闲内存。
Qcache_hits 每次查询在缓存中命中时就增大。
Qcache_inserts 每次插入一个查询时就增大。命中次数除以插入次数就是不中比率;用 1 减去这个值就是命中率。在上面这个例子中,大约有 87% 的查询都在缓存中命中。
Qcache_lowmem_prunes 缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看;如果这个数字在不断增长,就表示可能碎片非常严重,或者内存 很少。
(上面的 free_blocks 和 free_memory 可以告诉您属于哪种情况)。
Qcache_not_cached 不适合进行缓存的查询的数量,通常是由于这些查询不是 SELECT 语句。
Qcache_queries_in_cache 当前缓存的查询(和响应)的数量。
Qcache_total_blocks 缓存中块的数量。
通常,间隔几秒显示这些变量就可以看出区别,这可以帮助确定缓存是否正在有效地使用。运行 FLUSH STATUS
可以重置一些计数器,如果服务器已经运行了一段时间,这会非常有帮助。使用非常大的查询缓存,期望可以缓存所有东西,这种想法非常诱人。
由于 mysqld 必须要对缓存进行维护,例如当内存变得很低时执行剪除,因此服务器可能会在试图管理缓存时而陷入困境。
作为一条规则,如果 FLUSH QUERY CACHE 占用了很长时间,那就说明缓存太大了。
============================================================================================
4.线程缓存(thread_cache)
root@localhost ~]# cat /etc/my.cnf
thread_cache = 40
显示线程使用统计信息
mysql> SHOW STATUS LIKE 'threads%';
+-------------------+--------+
| Variable_name | Value |
+-------------------+--------+
| Threads_cached | 27 |
| Threads_connected | 15 |
| Threads_created | 838610 |
| Threads_running | 3 |
+-------------------+--------+
4 rows in set (0.00 sec)
说明:
与表的缓存类似,对于线程来说也有一个缓存。 mysqld 在接收连接时会根据需要生成线程。在一个连接变化很快的繁忙服务器上,
对线程进行缓存便于以后使用可以加快最初的连接。此处重要的值是 Threads_created,每次 mysqld 需要创建一个新线程时,
这个值都会增加。如果这个数字在连续执行 SHOW STATUS 命令时快速增加,就应该尝试增大线程缓存。
例如,可以在 my.cnf 中使用 thread_cache = 40 来实现此目的。
=================================================================================================
5.sort_buffer_size(排序操作使用的缓冲区大小)
每个会话的设置
下面这些设置针对于每个会话。在设置这些数字时要十分谨慎,因为它们在乘以可能存在的连接数时候,这些选项表示大量的内存!
您可以通过代码修改会话中的这些数字,或者在 my.cnf 中为所有会话修改这些设置。
当 MySQL 必须要进行排序时,就会在从磁盘上读取数据时分配一个排序缓冲区来存放这些数据行。如果要排序的数据太大,
那么数据就必须保存到磁盘上的临时文件中,并再次进行排序。如果 sort_merge_passes 状态变量很大,这就指示了磁盘的活动情况。
给出了一些与排序相关的状态计数器信息。
清单 8. 显示排序统计信息
mysql> SHOW STATUS LIKE "sort%";
+-------------------+---------+
| Variable_name | Value |
+-------------------+---------+
| Sort_merge_passes | 1 |
| Sort_range | 79192 |
| Sort_rows | 2066532 |
| Sort_scan | 44006 |
+-------------------+---------+
4 rows in set (0.00 sec)
如果 sort_merge_passes 很大,就表示需要注意 sort_buffer_size。例如, sort_buffer_size = 4M 将排序缓冲区设置为 4MB。
说明:
sort_buffer_size = 6M
查询排序时所能使用的缓冲区大小。注意:该参数对应的分配内存是每连接独占!如果有100个连接,那么实际分配的总共排序缓冲区大小为100 × 6 = 600MB。
所以,对于内存在4GB左右的服务器推荐设置为6-8M
==============================================================================================================
6.read_buffer_size
当一个查询不断地扫描某一个表,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。如 果你认为连续扫描进行得太慢,
可以通过增加该变量值以及内存缓冲区大小提高其性能。
确定表扫描比率
1.内存里的数据要比磁盘上的数据访问起来快;
2.让数据尽可能长时间地留在内存里能减少磁盘读写活动的工作量;
3.让索引信息留在内存里要比让数据记录的内容留在内存里更重要。
针对以上几个原则,我们应该调整服务器:
增加服务器的缓存区容量,以便数据在内存在停留的时间长一点,以减少磁盘I/0。下面介绍几个重要的缓冲区:
===========================================================================================
1.数据表缓冲区(table_cache)
数据表缓冲区存放着与打开的数据表相的信息,它的大小可由服务器参数“table_cache”设置。Opened_tables参数 记录服务器进行过多少次
数据表打开操作,如果该值变化很大,就可能是数据表缓冲区已满,需把一些不常用的表移出缓冲区,以腾出空打开新的数据表。可用以下命令
查看Opened_tables的值: SHOW STATUS LIKE 'Opened_tables';
说明(针对某个表只记录一次.重复对一个表不记录.)
[root@localhost ~]# cat /etc/my.cnf
table_cache = 256
mysql> show status like 'Opened_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Opened_tables | 13 |
+---------------+-------+
1 row in set (0.00 sec)
显示打开表的活动
mysql> SHOW STATUS LIKE 'open%tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables | 5000
| Opened_tables | 195 |
+---------------+-------+
2 rows in set (0.00 sec)
说明
目前有 5,000 个表是打开的,有 195 个表需要打开,因为现在缓存中已经没有可用文件描述符了(由于统计信息在前面已经清除了,
因此可能会存在 5,000 个打开表中只有 195 个打开记录的情况)。如果 Opened_tables 随着重新运行 SHOW STATUS 命令快速增加,
就说明缓存命中率不够。如果 Open_tables 比 table_cache 设置小很多,就说明该值太大了(不过有空间可以增长总不是什么坏事)。
例如,使用 table_cache = 5000 可以调整表的缓存。
============================================================================================================
2.索引缓存(key_buffer)
在MyISAM和ISAM数据表中,索引被缓存在“key buffer”里,它的大小由服务器参数“key_buffer_size”来控制。系统默认的大小是8M,如果
内存充足的话可适当扩大该值,以使更多索引块缓存在该区里,以加快索引的速度。
InnoDB和BDB数据表也各有一个缓冲区,分别叫innodb_buffer_pool_size和bdb_cache_size。InnoDB还有 一个日志缓冲区叫innodb_log_buffer_size。
说明(myisam属于非事务安全型,innodb和bdb属于事务安全型)
[root@localhost ~]# cat /etc/my.cnf
#bdb_cache_size = 64M
key_buffer = 256M (内存的一半或1/4)
#innodb_buffer_pool_size = 256M
确定关键字效率
mysql> show status like '%key_read%';
+-------------------+-----------+
| Variable_name
+-------------------+-----------+
| Key_read_requests | 163554268 |
| Key_reads
+-------------------+-----------+
2 rows in set (0.00 sec)
Key_reads 代表命中磁盘的请求个数, Key_read_requests 是总数。命中磁盘的读请求数除以读请求总数就是不中比率 ——
在本例中每 1,000 个请求,大约有 0.6 个没有命中内存。如果每 1,000 个请求中命中磁盘的数目超过 1 个,就应该考虑增大关键字缓冲区了。
例如,key_buffer = 384M 会将缓冲区设置为 384MB
Key_reads与Key_read_requests之比越小越好
========================================================================================================================
3.查询缓冲区(query_cache_size)
自4.0.1开始,MySQL多了一个缓冲区,叫查询缓冲区,主要用来存放重复执行的查询文本和结果,当再次遇到相同的查询,服务器会 直接从缓冲区中返回结果。
该功能是内建的功能,如不想支持该功能,可在编译服务器时用configure脚本的--without-query-cache选项去掉该功能。
查询缓冲区由三个服务器参数控制,分别是:
1、query_cache_size
控制缓冲区的大小,如果该值为0,则禁用查询缓冲功能。设置方法是在选项文件中设置:
[mysqld]
set-variable = query_cache_size = 16M
这样就设置了一个16M的查询缓冲区
2、query_cache_limit
缓冲结果集的最大容量(以字节为单位),如果查询的结果集大于该值,则不缓冲该值。
3、query_cache_type
缓冲区的操作模式。
0表示不进行缓冲;
1表示除SELECT SQL_NO_CACHE开头的查询外,其余的都缓冲;
2表示只对以SELECT SQL_ON_CACHE开头的查询进行缓冲。
[root@localhost ~]# cat /etc/my.cnf
#query_cache_type=0
query_cache_size= 16M
query_cache_limit=2M
显示查询缓冲区的内容
mysql> show status like 'qcache%';
+-------------------------+----------+
| Variable_name
+-------------------------+----------+
| Qcache_free_blocks
| Qcache_free_memory
| Qcache_hits
| Qcache_inserts
| Qcache_lowmem_prunes | 0
| Qcache_not_cached
| Qcache_queries_in_cache | 0
| Qcache_total_blocks
+-------------------------+----------+
8 rows in set (0.01 sec)
mysql> flush query cache;
Query OK, 0 rows affected (0.00 sec)
mysql>
说明:
MySQL 查询缓存变量
变量名
Qcache_free_blocks
Qcache_free_memory
Qcache_hits
Qcache_inserts
Qcache_lowmem_prunes
Qcache_not_cached
Qcache_queries_in_cache
Qcache_total_blocks
通常,间隔几秒显示这些变量就可以看出区别,这可以帮助确定缓存是否正在有效地使用。运行 FLUSH STATUS
可以重置一些计数器,如果服务器已经运行了一段时间,这会非常有帮助。使用非常大的查询缓存,期望可以缓存所有东西,这种想法非常诱人。
由于 mysqld 必须要对缓存进行维护,例如当内存变得很低时执行剪除,因此服务器可能会在试图管理缓存时而陷入困境。
作为一条规则,如果 FLUSH QUERY CACHE 占用了很长时间,那就说明缓存太大了。
============================================================================================
4.线程缓存(thread_cache)
root@localhost ~]# cat /etc/my.cnf
thread_cache = 40
显示线程使用统计信息
mysql> SHOW STATUS LIKE 'threads%';
+-------------------+--------+
| Variable_name
+-------------------+--------+
| Threads_cached | 27
| Threads_connected | 15
| Threads_created | 838610 |
| Threads_running | 3
+-------------------+--------+
4 rows in set (0.00 sec)
说明:
与表的缓存类似,对于线程来说也有一个缓存。 mysqld 在接收连接时会根据需要生成线程。在一个连接变化很快的繁忙服务器上,
对线程进行缓存便于以后使用可以加快最初的连接。此处重要的值是 Threads_created,每次 mysqld 需要创建一个新线程时,
这个值都会增加。如果这个数字在连续执行 SHOW STATUS 命令时快速增加,就应该尝试增大线程缓存。
例如,可以在 my.cnf 中使用 thread_cache = 40 来实现此目的。
=================================================================================================
5.sort_buffer_size(排序操作使用的缓冲区大小)
每个会话的设置
下面这些设置针对于每个会话。在设置这些数字时要十分谨慎,因为它们在乘以可能存在的连接数时候,这些选项表示大量的内存!
您可以通过代码修改会话中的这些数字,或者在 my.cnf 中为所有会话修改这些设置。
当 MySQL 必须要进行排序时,就会在从磁盘上读取数据时分配一个排序缓冲区来存放这些数据行。如果要排序的数据太大,
那么数据就必须保存到磁盘上的临时文件中,并再次进行排序。如果 sort_merge_passes 状态变量很大,这就指示了磁盘的活动情况。
给出了一些与排序相关的状态计数器信息。
清单 8. 显示排序统计信息
mysql> SHOW STATUS LIKE "sort%";
+-------------------+---------+
| Variable_name
+-------------------+---------+
| Sort_merge_passes | 1
| Sort_range
| Sort_rows
| Sort_scan
+-------------------+---------+
4 rows in set (0.00 sec)
如果 sort_merge_passes 很大,就表示需要注意 sort_buffer_size。例如, sort_buffer_size = 4M 将排序缓冲区设置为 4MB。
说明:
sort_buffer_size = 6M
查询排序时所能使用的缓冲区大小。注意:该参数对应的分配内存是每连接独占!如果有100个连接,那么实际分配的总共排序缓冲区大小为100 × 6 = 600MB。
所以,对于内存在4GB左右的服务器推荐设置为6-8M
==============================================================================================================
6.read_buffer_size
当一个查询不断地扫描某一个表,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。如 果你认为连续扫描进行得太慢,
可以通过增加该变量值以及内存缓冲区大小提高其性能。
确定表扫描比率