通过慢日志查询可以知道哪些SQL语句执行效率低下
通过explain我们可以得知SQL语句的具体执行情况,索引使用等,还可以结合show命令查看执行状态。
通过profiling命令得到更准确的SQL执行消耗系统资源的信息。
1、开户慢日志:
A)、log-slow-queries参数为慢查询日志存放的位置
B)、long_query_time=2中的2表示查询超过两秒才记录
C)、使用mysqldumpslow工具(MySQL客户端安装自带)来对慢查询日志进行分类汇总。
mysqldumpslow对日志文件进行了分类汇总,显示汇总后摘要结果
-s, 是表示按照何种方式排序,
c、t、l、r分别是按照记录次数、时间、查询时间、返回的记录数来排序,
ac、at、al、ar,表示相应的倒叙;
-t, 是top n的意思,即为返回前面多少条的数据;
-g, 后边可以写一个正则匹配模式,大小写不敏感的;
mysql> set global slow_query_log = ON;
mysql> show variables like ‘slow%’;
2、explain分析查询
3、profiling分析查询
profiling默认是关闭的。可以通过以下语句查看
mysql> select @@profiling;
mysql> set profiling = 1;
mysql> show profiles \G;
mysql> show profile for query 1;
4、索引及查询优化
大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)使用B树中存储。
空间列类型的索引使用R-树,
MEMORY表支持hash索引。
A、MySQL可以为多个列创建索引。一个索引可以包括15个列。对于某些列类型,可以索引列的左前缀,列的顺序非常重要。
B、越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快
C、简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;以及用整型数据类型存储IP地址。
D、尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值
5、关于索引和写SQL语句时应当注意的一些琐碎建议和注意点
A、当结果集只有一行数据时使用LIMIT 1
B、避免SELECT *,始终指定你需要的列
C、使用连接(JOIN)来代替子查询(Sub-Queries)
D、使用ENUM、CHAR 而不是VARCHAR,使用合理的字段属性长度
E、尽可能的使用NOT NULL
F、固定长度的表会更快
G、拆分大的DELETE 或INSERT 语句
H、查询的列越小越快
6、Where条件
A、在多个条件的时候,把会提取尽量少数据量的条件放在前面,减少后一个where条件的查询时间。
有些where条件会导致索引无效:
A、where子句的查询条件里有!=,MySQL将无法使用索引。
B、where子句使用了Mysql函数的时候,索引将无效,比如:select * from tb where left(name, 4) = ‘xxx’
C、使用LIKE进行搜索匹配的时候,这样索引是有效的:select * from tbl1 where name like ‘xxx%’,而like ‘%xxx%’ 时索引无效
7、配置优化
A、连接请求的变量
max_connections
如果服务器的并发连接请求量比较大,建议调高此值,以增加并行连接数量
值过小会经常出现ERROR 1040: Too many connections错误,可以过’conn%’通配符查看当前状态的连接数量,以定夺该值的大小。
mysql> show variables like ‘max_connections’;
mysql> show status like ‘max_used_connections’;
max_used_connections / max_connections * 100% (理想值≈ 85%)
如果max_used_connections跟max_connections相同 那么就是max_connections设置过低或者超过服务器负载上限了,低于10%则设置过大。
back_log
MySQL能暂存的连接数量。当主要MySQL线程在一个很短时间内得到非常多的连接请求,这就起作用。
如果MySQL的连接数据达到max_connections时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过back_log,将不被授予连接资源。
当观察你主机进程列表(mysql> show full processlist),发现大量264084 | unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时,就要加大back_log 的值了。
mysql> show full processlist;
+—–+——+—————–+———-+———+——+——-+———————–+
| Id | User | Host | db | Command | Time | State | Info |
+—–+——+—————–+———-+———+——+——-+———————–+
| 211 | root | localhost:55611 | appstore | Query | 0 | NULL | show full processlist |
+—–+——+—————–+———-+———+——+——-+———————–+
默认数值是50,可调优为128,对于Linux系统设置范围为小于512的整数。
interactive_timeout
一个交互连接在被服务器在关闭前等待行动的秒数。一个交互的客户被定义为对mysql_real_connect()使用CLIENT_INTERACTIVE 选项的客户。
默认数值是28800,可调优为7200。
key_buffer_size
key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度。
通过检查状态值Key_read_requests和Key_reads,可以知道key_buffer_size设置是否合理。
比例key_reads / key_read_requests应该尽可能的低,至少是1:100,1:1000更好(上述状态值可以使用SHOW STATUS LIKE ‘key_read%’获得)。
key_buffer_size只对MyISAM表起作用。即使你不使用MyISAM表,但是内部的临时磁盘表是MyISAM表,也要使用该值。可以使用检查状态值created_tmp_disk_tables得知详情。
mysql> show variables like ‘key_buffer_size’;
mysql> show global status like ‘key_read%’;
计算索引未命中缓存的概率:
key_cache_miss_rate =Key_reads / Key_read_requests * 100%,设置在1/1000左右较好
默认配置数值是8388600(8M),主机有4GB内存,可以调优值为268435456(256MB)。
query_cache_size
MySQL将查询结果存放在缓冲区中,今后对于同样的SELECT语句(区分大小写),将直接从缓冲区中读取结果
通过检查状态值Qcache_*,可以知道query_cache_size设置是否合理
如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲不够的情况,如果Qcache_hits的值也非常大,则表明查询缓冲使用非常频繁,此时需要增加缓冲大小;
如果Qcache_hits的值不大,则表明你的查询重复率很低,这种情况下使用查询缓冲反而会影响效率,那么可以考虑不用查询缓冲。
此外,在SELECT语句中加入SQL_NO_CACHE可以明确表示不使用查询缓冲。
mysql> show status like ‘Qcache%’;
query_cache_type、query_cache_limit、query_cache_min_res_unit
query_cache_type指定是否使用查询缓冲,可以设置为0、1、2,该变量是SESSION级的变量。
query_cache_limit指定单个查询能够使用的缓冲区大小,缺省为1M。
query_cache_min_res_unit是在4.1版本以后引入的,它指定分配缓冲区空间的最小单位,缺省为4K。检查状态值Qcache_free_blocks,如果该值非常大,则表明缓冲区中碎片很多,这就表明查询结果都比较小,此时需要减小query_cache_min_res_unit。
查询缓存碎片率= Qcache_free_blocks / Qcache_total_blocks * 100%
如果查询缓存碎片率超过20%,可以用FLUSH QUERY CACHE整理缓存碎片,或者试试减小query_cache_min_res_unit,如果你的查询都是小数据量的话。
查询缓存利用率= (query_cache_size – Qcache_free_memory) / query_cache_size * 100%
查询缓存利用率在25%以下的话说明query_cache_size设置的过大,可适当减小;查询缓存利用率在80%以上而且Qcache_lowmem_prunes > 50的话说明query_cache_size可能有点小,要不就是碎片太多。
查询缓存命中率= (Qcache_hits – Qcache_inserts) / Qcache_hits * 100%
示例服务器查询缓存碎片率=20.46%,查询缓存利用率=62.26%,查询缓存命中率=1.94%,命中率很差,可能写操作比较频繁吧,而且可能有些碎片。
record_buffer_size
每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。
默认数值是131072(128K),可改为16773120 (16M)
read_rnd_buffer_size
如果需要排序大量数据,可适当调高该值。但MySQL会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
一般可设置为16M
sort_buffer_size
每个需要进行排序的线程分配该大小的一个缓冲区。增加这值加速ORDER BY或GROUP BY操作。
默认数值是2097144(2M),可改为16777208 (16M)。
join_buffer_size
联合查询操作所能使用的缓冲区大小
/*******
*
* record_buffer_size,read_rnd_buffer_size,sort_buffer_size,join_buffer_size为每个线程独占,也就是说,如果有100个线程连接,则占用为16M*100
*
*******/
table_cache
表高速缓存的大小。每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。
通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_cache的值。
如果你发现open_tables等于table_cache,并且opened_tables在不断增长,那么你就需要增加table_cache的值了
mysql> show status like ‘open%tables’;
1G内存机器,推荐值是128-256。内存在4GB左右的服务器该参数可设置为256M或384M。
max_heap_table_size
用户可以创建的内存表(memory table)的大小。
tmp_table_size
通过设置tmp_table_size选项来增加一张临时表的大小
建议尽量优化查询,要确保查询过程中生成的临时表在内存中,避免临时表过大导致生成基于硬盘的MyISAM表。
mysql> show global status like ‘created_tmp%’;
每次创建临时表,Created_tmp_tables增加,如果临时表大小超过tmp_table_size,则是在磁盘上创建临时表,Created_tmp_disk_tables也增加,Created_tmp_files表示MySQL服务创建的临时文件文件数,比较理想的配置是:
Created_tmp_disk_tables / Created_tmp_tables * 100% <= 25%比如上面的服务器Created_tmp_disk_tables / Created_tmp_tables * 100% =1.20%
默认为16M,可调到64-256最佳,线程独占,太大可能内存不够I/O堵塞
thread_cache_size
可以复用的保存在缓存中的线程的数量。如果有,新的线程从缓存中取得,当断开连接的时候如果有空间,客户的线置在缓存中。如果有很多新的线程,为了提高性能可以这个变量值。
通过比较 Connections和Threads_created状态的变量,可以看到这个变量的作用。
默认值为110,可调优为80。
thread_concurrency
推荐设置为服务器 CPU核数的2倍,例如双核的CPU, 那么thread_concurrency的应该为4
wait_timeout
指定一个请求的最大连接时间,对于4GB左右内存的服务器可以设置为5-10。
innodb_buffer_pool_size
对于InnoDB表来说,innodb_buffer_pool_size的作用就相当于key_buffer_size对于MyISAM表的作用一样
对于单独的MySQL数据库服务器,最大可以把该值设置成物理内存的80%。
innodb_flush_log_at_trx_commit
主要控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为0、1、2三个。
0,表示当事务提交时,不做日志写入操作,而是每秒钟将log buffer中的数据写入日志文件并flush磁盘一次;
1,则在每秒钟或是每次事物的提交都会引起日志文件写入、flush磁盘的操作,确保了事务的ACID;
2,每次事务提交引起写入日志文件的动作,但每秒钟完成一次flush磁盘操作。
innodb_log_buffer_size
log缓存大小,一般为1-8M,默认为1M,对于较大的事务,可以增大缓存大小。
可设置为4M或8M。
innodb_additional_mem_pool_size
该参数指定InnoDB用来存储数据字典和其他内部数据结构的内存池大小。缺省值是1M。通常不用太大,只要够用就行,应该与表结构的复杂度有关系。如果不够用,MySQL会在错误日志中写入一条警告信息。
根据MySQL手册,对于2G内存的机器,推荐值是20M,可适当增加。
innodb_thread_concurrency=8
推荐设置为 2*(NumCPUs+NumDisks),默认一般为8