|
|
|
|
|
 |
|
|
|
| mysql优化基础 |
|
|
作者:未知 文章来源:网络 点击数: 更新时间:2008-11-7  |
一.MySQL 日志介绍 =========================================================================================== 各种日志文件激活时需要的参数表, 与日志有关的启动选项 由该选项激活的日志 log[=file_name] 常规日志文件.................................连接/断开连接事件和查询信息 log-update[=file_name] 变更日志文件..........................创建/变更表结构或修改了表内容的查询命令文本 log-bin[=file_name] 二进制变更日志文件........................如上面,这是二进制表示 log-bin-index[=file_name] 二进制变更日志索引文件..............二进制变量日志文件的清单 log-slow-queries[=file_name] 慢查询日志文件...................耗时很长的查询命令的文本 log-long-format 这个选项用来设置慢查询日志和变更日志的格式 HOSTNAME.err 错误日志 "启动/关机" 事件和异常情况 HOSTNAME.pid 进程ID文件 MySQL服务器进程的ID =============================================================================================
1.慢查询日志文件 (耗时很长的查询命令的文本记录到此日志里)
long_query_time 是指执行超过多久的sql会被log下来,这里是2秒。 log-slow-queries 设置把日志写在那里,可以为空,系统会给一个缺省的文件 log-queries-not-using-indexes 就是纪录没使用索引的sql
在my.cnf下加入如下内容 log-slow-queries=/usr/local/mysql/data/slowquery.log long_query_time=2 log-queries-not-using-indexes
mysql> load data local infile "aa" into table wang_tb; mysql> select count(*) from wang_tb; +----------+ | count(*) | +----------+ | 294129 | +----------+ 1 row in set (0.00 sec) mysql> select * from wang_tb
[root@localhost data]# tail -f slowquery.log # Time: 070304 11:45:16 # User@Host: root[root] @ localhost [] # Query_time: 9 Lock_time: 0 Rows_sent: 294129 Rows_examined: 294129 use wang_db; select * from zhang_tb; # Time: 070304 11:45:44 # User@Host: root[root] @ localhost [] # Query_time: 7 Lock_time: 1 Rows_sent: 294129 Rows_examined: 294129 select * from wang_tb; # Time: 070304 11:46:25 # User@Host: root[root] @ localhost [] # Query_time: 23 Lock_time: 0 Rows_sent: 294129 Rows_examined: 294129 select * from wang_tb; # Time: 070304 11:47:24 # User@Host: root[root] @ localhost [] # Query_time: 9 Lock_time: 0 Rows_sent: 294129 Rows_examined: 294129 select * from wang_tb; ============================================================================================
2.常规日志文件 (连接/断开连接事件和查询信息记录到此日志里)
在my.cnf下加入如下内容 log=/usr/local/mysql/data/normal.log
[root@localhost data]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 to server version: 4.1.10a-max-log
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> use wang_db; Database changed mysql> select count(*) from wang_tb -> ; +----------+ | count(*) | +----------+ | 294129 | +----------+ 1 row in set (0.16 sec)
mysql> \q Bye [root@localhost data]# [root@localhost data]# [root@localhost data]# cat normal.log /usr/local/mysql/bin/mysqld, Version: 4.1.10a-max-log. started with: Tcp port: 3306 Unix socket: /tmp/mysql.sock Time Id Command Argument 070304 10:42:05 1 Connect root@localhost on 070304 10:42:11 1 Query SELECT DATABASE() 1 Init DB wang_db 070304 10:42:12 1 Quit 070304 10:45:53 2 Connect root@localhost on 070304 10:45:57 2 Query SELECT DATABASE() 2 Init DB wang_db 070304 10:46:15 2 Query select count(*) from wang_tb 070304 10:46:17 2 Quit [root@localhost data]#
========================================================================================
3.变更日志文件 (创建/变更表结构或修改了表内容的查询命令文本记录到此日志里)
在my.cnf下加入 log-update=/usr/local/mysql/data/change.log
[root@localhost data]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 to server version: 4.1.10a-max-log
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> use wang_db; Database changed mysql> load data local infile "aa" into table zhang_tb; Query OK, 8913 rows affected (0.20 sec) Records: 8913 Deleted: 0 Skipped: 0 Warnings: 0
mysql> \q Bye [root@localhost data]# cat change.log # /usr/local/mysql/bin/mysqld, Version: 4.1.10a-max-log at 070304 10:48:26 # Time: 070304 10:49:33 # User@Host: root[root] @ localhost [] use wang_db; load data local infile "aa" into table zhang_tb;
============================================================================================= [root@localhost ~]# mysqladmin variables 可以用该命令查看日志功能是否开启.
二.MySQL 优化
服务器优化原则:
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变量控制这一缓冲区的大小。如果你认为连续扫描进行得太慢, 可以通过增加该变量值以及内存缓冲区大小提高其性能。 确定表扫描比率 mysql> SHOW STATUS LIKE "com_select"; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | Com_select | 318243 | +---------------+--------+ 1 row in set (0.00 sec)
mysql> SHOW STATUS LIKE "handler_read_rnd_next"; +-----------------------+-----------+ | Variable_name | Value | +-----------------------+-----------+ | Handler_read_rnd_next | 165959471 | +-----------------------+-----------+ 1 row in set (0.00 sec)
Handler_read_rnd_next / Com_select 得出了表扫描比率 —— 在本例中是 521:1。如果该值超过 4000,就应该查看 read_buffer_size, 例如 read_buffer_size = 4M。如果这个数字超过了 8M,就应该与开发人员讨论一下对这些查询进行调优了!
说明: 读查询操作所能使用的缓冲区大小。和sort_buffer_size一样,该参数对应的分配内存也是每连接独享
==============================================================================================================
7.join_buffer_size = 8M 联合查询操作所能使用的缓冲区大小,和sort_buffer_size一样,该参数对应的分配内存也是每连接独享! ========================================================================================================
8.thread_concurrency = 8 该参数取值为服务器逻辑CPU数量×2,在本例中,服务器有2颗物理CPU,而每颗物理CPU又支持H.T超线程,所以实际取值为4 × 2 = 8 =============================================================================================================
9.确定临时表的使用(max_heap_table_size)
临时表可以在更高级的查询中使用,其中数据在进一步进行处理(例如 GROUP BY 字句)之前,都必须先保存到临时表中; 理想情况下,在内存中创建临时表。但是如果临时表变得太大,就需要写入磁盘中。清单 7 给出了与临时表创建有关的统计信息。
[root@localhost ~]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4 to server version: 4.1.10a-max-log
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> SHOW STATUS LIKE 'created_tmp%'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | Created_tmp_disk_tables | 0 | | Created_tmp_files | 3 | | Created_tmp_tables | 0 | +-------------------------+-------+ 3 rows in set (0.00 sec) mysql>
每次使用临时表都会增大 Created_tmp_tables;基于磁盘的表也会增大 Created_tmp_disk_tables。对于这个比率,并没有什么严格的规则, 因为这依赖于所涉及的查询。长时间观察 Created_tmp_disk_tables 会显示所创建的磁盘表的比率,您可以确定设置的效率。 tmp_table_size 和 max_heap_table_size 都可以控制临时表的最大大小,因此请确保在 my.cnf 中对这两个值都进行了设置。
===================================================================================================================
10.back_log
指定MySQL可能的连接数量。当MySQL主线程在很短的时间内接收到非常多的连接请求,该参数生效,主线程花费很短的时间检查连接并且启动一个新线程。 back_log参数的值指出在MySQL暂时停止响应新请求之前的短时间内多少个请求可以被存在堆栈中。如果系统在一个短时间内有很多连接,则需要增大该参数的值, 该参数值指定到来的TCP/IP连接的侦听队列的大小。不同的*作系统在这个队列大小上有它自 己的限制。 试图设定back_log高于你的*作系统的限制将是无效的。默认值为50。对于Linux系统推荐设置为小于512的整数 ================================================================================================================
11.skip-networking 开启该选项可以彻底关闭MySQL的TCP/IP连接方式,如果WEB服务器是以远程连接的方式访问MySQL数据库服务器则不要开启该选项!否则将无法正常连接! ====================================================================================================================
12.skip-name-resolve 禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间。但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式, 否则MySQL将无法正常处理连接请求! ============================================================================================
三.MySQL 资源设置 max_connections=500 wait_timeout=10 max_connect_errors = 100
连接最大个数是在第一行中进行管理的。与 Apache 中的 MaxClients 类似,其想法是确保只建立服务允许数目的连接。要确定服务器上目前建立过的最大连接数,请执行 SHOW STATUS LIKE 'max_used_connections'。
第 2 行告诉 mysqld 终止所有空闲时间超过 10 秒的连接。在 LAMP 应用程序中,连接数据库的时间通常就是 Web 服务器处理请求所花费的时间。有时候,如果负载过重, 连接会挂起,并且会占用连接表空间。如果有多个交互用户或使用了到数据库的持久连接,那么将这个值设低一点并不可取!
最后一行是一个安全的方法。如果一个主机在连接到服务器时有问题,并重试很多次后放弃,那么这个主机就会被锁定,直到 FLUSH HOSTS 之后才能运行。默认情况下, 10 次失败就足以导致锁定了。将这个值修改为 100 会给服务器足够的时间来从问题中恢复。如果重试 100 次都无法建立连接,那么使用再高的值也不会有太多帮助, 可能它根本就无法连接。
====================================================================================================
四.MySQL 服务器参数
服务器参数分为全局级和会话级两个级别。全局级参数将影响整个服务器,会话级参数则只影响某给定客户连接上的工作。 如果某个变量同时存在于两个级别,则服务器在客户建立连接时用全局变量的值去初始化相应的会话级参数,一旦客户连接建立起来后, 对全局参数所作的修改不会影响到相应的会话级参数当前值。设置全局参数和会话级参数的语句:
全局级: mysql> SET GLOBAL variable = value; mysql> SET @@GLOBAL.variable = value;
会话级: mysql> SET SESSION variable = value; mysql> SET @@SESSION.variable = value;
默认不带级别限定符的SET语句修改的参数属会话级,如: mysql> SET variable = value; mysql> SET @@variable = value;
可用一条SET语句设置多个参数,参数间用逗号分隔,如: SET SESSION variable = value1,value2,value3;
SESSION和LOCAL是同义语,可用LOCAL代替SESSION,如:@@LOCAL
显示参数的语句如下 SHOW GLOBAL VARIABLES; SHOW GLOBAL VARIABLES LIKE 'TEST'; SHOW SESSION VARIABLES; SHOW SESSION VARIABLES LIKE 'TEST'; 如不带限定符,则返回会话级参数,如会话级参数不存在则返回全局级参数。
也可用命令行方式显示服务器参数变量(全局),如: % mysqladmin variables
例如: [root@localhost mysql]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 to server version: 4.1.10a-max-log
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> set session wait_timeout=2880; Query OK, 0 rows affected (0.00 sec)
mysql> set global wait_timeout=2880; Query OK, 0 rows affected (0.00 sec)
mysql> set @@session.wait_timeout=288; Query OK, 0 rows affected (0.00 sec)
mysql> set @@local.wait_timeout=28800; Query OK, 0 rows affected (0.00 sec)
说明: 具备SUPER权限才能设置全局参数,新设置值的效力将持续到该参数被再次修改或服务器退出。设置会话级参数不用特殊的权限, 新设置值的效力将持续到该值被再次修改或连接断开。 ===========================================================================================
五.MySQL 常用命令 show index from tb1 show [full] processlist show status show table status show variables =================================================================================================
|
| 文章录入:root 责任编辑:root |
|
上一篇文章: MySQL服务器安装完之后如何调节性能
下一篇文章: 没有了 |
| 【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 |
|
|
|
| |
|
| |
|
|