转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46794245
一、优化简单介绍html
mysql优化是多方面的。原则是下降系统的瓶颈,下降资源的占用。添加系统的反应速度。mysql
好比,经过优化文件系统。提升磁盘I/O的读写速度;经过优化操做系统调度策略,提升mysql在高负荷状况下的负载能力。优化表结构、索引、查询语句等使查询响应更快在mysql中,可以使用show status语句查询一些mysql的性能參数sql
show status like 'value';
当中value是要查询的參数值,一些常用性能參数例如如下:数据库
connections:链接mysqlserver的次数缓存
uptime:mysqlserver的上线时间网络
slow_queries:慢查询的次数mysql优化
com_select:查询操做次数多线程
com_insert:插入操做次数并发
com_update:更新操做次数数据库设计
com_delete:删除操做次数
假设查询mysqlserver的链接次数,可以运行例如如下语句
show status like 'connections';
假设查询mysqlserver的慢查询次数。可以运行例如如下语句
show status like 'slow_queries';
二、优化查询
查询是数据库最频繁的操做。提升查询速度可以有效地提升mysql数据库的性能
(1)分析查询语句
经过对查询语句的分析。可以了解查询语句的运行状况找出查询语句运行的瓶颈
mysql中提供了EXPLAIN语句和DESCRIBE语句。用来分析查询语句
EXPLAIN语句的基本的语法
EXPLAIN [EXTENDED] SELECT SELECT_OPTION
使用EXTENDEDkeyword,EXPLAIN语句将产生附加信息。
SELECT_OPTION是SELECT 语句的查询选项,包含FROM WHERE子句等
运行该语句。能够分析EXPLAIN后面的select语句的运行状况。并且能够分析所查询的表的一些特征
使用EXPLAIN语句来分析1个查询语句
USE TEST; EXPLAIN EXTENDED SELECT * FROM PERSON;
如下对结果进行解释
· id
SELECT识别符。这是SELECT的查询序列号。
· select_type
SELECT类型,可以为下面不论什么一种:
SIMPLE:简单SELECT(不使用UNION或子查询)
PRIMARY:表示主查询,或者是最外层的查询语句(多表链接的时候)
UNION:表示链接查询的第二个或后面的查询语句
DEPENDENT UNION:UNION链接查询中的第二个或后面的SELECT语句。取决于外面的查询
UNION RESULT:UNION链接查询的结果
SUBQUERY:子查询中的第一个SELECT语句
DEPENDENT SUBQUERY:子查询中的第一个SELECT语句。取决于外面的查询
DERIVED:导出表的SELECT(FROM子句的子查询)
· table
表示查询的表
· type
表示表的联接类型
如下给出各类联接类型,依照从最佳类型到最坏类型进行排序:
(1)system
表仅有一行(=系统表)。这是const联接类型的一个特例。
(2)const
表最多仅仅有一个匹配行。它将在查询開始时被读取。
余下的查询优化中被做为常量对待。const表查询速度很是快,因为它们仅仅读取一次。
const用于常数值比較PRIMARY KEY或UNIQUE索引的所有部分的场合。
在如下的查询中,tbl_name可以用于const表:
SELECT * from tbl_name WHERE primary_key=1;SELECT * from tbl_name WHERE primary_key_part1=1和 primary_key_part2=2;
(3)eq_ref
对于每个来自于前面的表的行组合。从该表中读取一行。
这多是最好的联接类型,除了const类型。
它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY时。
eq_ref可以用于使用“=” 操做符比較的带索引的列。比較值可以为常量或一个使用在该表前面所读取的表的列的表达式。
在如下的样例中,MySQL可以使用eq_ref联接来处理ref_tables:
SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
(4)ref
对于每个来自于前面的表的随意行组合。将从该表中读取所有匹配的行。
假设联接仅仅使用索引键的最左边的前缀,或假设索引键不是UNIQUE或PRIMARY KEY,则使用ref。
假设使用的键只匹配少许行,该联接类型是不错的。
ref可以用于使用=或<=>操做符的带索引的列。
在如下的样例中,MySQL可以使用ref联接来处理ref_tables:
SELECT * FROM ref_table WHERE key_column=expr; SELECT * FROM ref_table,other_table WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1=other_table.column AND ref_table.key_column_part2=1;
(5)ref_or_null
该联接类型如同ref,但是加入了MySQL可以专门搜索包括NULL值的行。在解决子查询中经常使用该联接类型的优化。
在如下的样例中,MySQL可以使用ref_or_null联接来处理ref_tables:
SELECT * FROM ref_table WHERE key_column=expr OR key_column IS NULL;
(6) index_merge
该联接类型表示使用了索引合并优化方法。
在这样的状况下,key列包括了所用到的索引的清单。key_len列包括了所用到的索引的最长长度。
(7) unique_subquery
该类型替换了如下形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找类型,可以全然替换子查询,效率更高。
(8) index_subquery
该联接类型相似于unique_subquery,只是索引类型不需要是惟一索引,可以替换IN子查询,但仅仅适合下列形式的子查询中的非惟一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
(9) range
仅仅检索给定范围的行,使用一个索引来检索行数据。key列显示使用了哪一个索引,key_len显示所使用索引的长度。
在该类型中ref列为NULL。
当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操做符。用常量比較keyword列时,类型为range。
如下介绍几种检索指定行数据的状况
SELECT * FROM tbl_name WHERE key_column = 10; SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20; SELECT * FROM tbl_name WHERE key_column IN (10,20,30); SELECT * FROM tbl_name WHERE key_part1= 10 AND key_part2 IN (10,20,30);
(10) index
该联接类型与ALL一样。除了扫描索引树。其它状况都比ALL快,因为索引文件一般比数据文件小。
当查询仅仅使用做为单索引一部分的列时,MySQL可以使用该联接类型。
(11) ALL
对于每个来自于先前的表的行组合,进行完整的表扫描。
假设第一个表没标记为const,这样运行计划就不会很是好。
一般可以添加不少其它的索引来摆脱ALL。使得行能基于前面的表中的常数值或列值被检索出。
possible_keys
possible_keys列指出MySQL能供给使用的索引键有哪些。
注意,该列全然独立于EXPLAIN输出所看到的的表的次序。
这意味着在possible_keys中的某些索引键实际上不能按生成的表次序使用。
假设该列是NULL,则没有相关的索引。在这样的状况下,可以经过检查WHERE子句查看可否够引用某些列或适合的索引列来提升查询性能。
假设是这样。创造一个适当的索引并且再次用EXPLAIN检查查询。
假设要查询一张表有什么索引,可以使用
SHOW INDEX FROM tbl_name
key
key列显示MySQL实际决定使用的键(索引)。假设没有选择索引,那么可能列的值是NULL。
要想强制MySQL使用或忽略possible_keys列中的索引。在查询中可以使用
FORCE INDEX -- 强逼使用某个索引 USE INDEX --使用某个索引 IGNORE INDEX -- 忽略某个索引
对于MyISAM引擎和BDB引擎的表,执行 ANALYZE TABLE 可以帮助优化器选择更好的索引。
对于MyISAM表。可以使用myisamchk --analyze。
key_len
key_len列显示MySQL决定使用的索引键的长度(按字节计算)。
假设键是NULL。则长度为NULL。
注意经过key_len值咱们可以肯定MySQL将实际使用一个多索引键索引的几个字段。
ref
ref列显示使用哪一个列或常数与索引一块儿查询记录。
rows
rows列显示MySQL预估运行查询时必须要检索的行数。
Extra
该列包括MySQL处理查询时的具体信息。
如下解释了该列可以显示的不一样的文本字符串:
Distinct
MySQL发现第1个匹配行后,中止为当前的行组合搜索不少其它的行。
Not exists
MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,再也不为前面的的行组合在该表内检查不少其它的行。
如下是一个可以这样优化的查询类型的样例:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
假定t2.id定义为NOT NULL。
在这样的状况下。MySQL使用t1.id的值扫描t1并查找t2中的行。
假设MySQL在t2中发现一个匹配的行。它知道t2.id毫不会为NULL,并且再也不扫描t2内有一样的id值的行。换句话说,对于t1的每个行,MySQL仅仅需要在t2中查找一次,无论t2内实际有多少匹配的行。
range checked for each record (index map: #)
MySQL没有发现好的可以使用的索引。但发现假设来自前面的表的列值已知,可能部分索引可以使用。
对前面的表的每个行组合,MySQL检查可否够使用range或index_merge訪问方法来获取行。
这并不很是快,但比运行没有索引的联接要快得多。
可以參考一下这篇文章:一个用户SQL慢查询分析,缘由及优化
里面就提到了range checked for each record
Using filesort
MySQL需要额外的一次传递,以找出怎样按排序顺序检索行。
经过依据联接类型浏览所有行并为所有匹配WHERE子句的行保存排序keyword和行的指针来完毕排序。
而后keyword被排序。并按排序顺序检索行
假设是order by操做就会用到这个Using filesort,固然filesort不是指使用文件来排序,你们不要误会了。。。
Using index
从仅仅使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。
当查询仅仅使用做为单一索引一部分的列时,可以使用该策略。
Using temporary
为了解决查询,MySQL需要建立一个暂时表来容纳结果。
典型状况如查询包括可以按不一样状况列出列的GROUP BY和ORDER BY子句时。
通常用到暂时表都会看到 Using temporary
Using where
WHERE子句用于限制哪个行匹配下一个表或发送到client。
除非你专门从表中索取或检查所有行。假设Extra值不为Using where并且表联接类型为ALL或index,查询可能会有一些错误。
Using index for group-by
相似于訪问表的Using index方式,Using index for group-by表示MySQL发现了一个索引。可以用来查询GROUP BY或DISTINCT查询的所有列。而不要额外搜索硬盘訪问实际的表。
并且,按最有效的方式使用索引。以便对于每个组,仅仅读取少许索引条目。
DESCIBE语句的用法与EXPLAIN语句是同样的。并且分享结果也是同样的DESCIBE语句的语法例如如下
DESCRIBE SELECT select_options
DESCIBE可以缩写成DESC
(2)索引对查询速度的影响
mysql中提升性能的一个最有效的方式就是对数据表设计合理的索引。索引提供了高效訪问数据的方法。并且加快查询速度。所以索引对查询速度有着相当重要的影响。
假设查询没有索引,查询语句将扫描表中所有记录。在数据量大的状况下,这样查询的速度会很是慢。假设使用索引进行查询,查询语句可以依据索引高速定位到待查询记录。从而下降查询的记录数,达到提升查询速度的目的。
如下是查询语句中不使用索引和使用索引的对照,首先分析未使用索引的查询状况,EXPLAIN语句运行例如如下
EXPLAIN SELECT `ID`,`name` FROM `test`.`emp` WHERE `name` ='nihao'
可以看到。rows列的值是3说“SELECT `ID`,`name` FROM `test`.`emp` WHERE `name` ='nihao'” 语句扫描了表中的3条记录
而后在emp表加上索引
CREATE INDEX ix_emp_name ON emp(name)
现在再分析上面的查询语句,运行的EXPLAIN语句结果例如如下
结果显示,rows列的值为1。这表示这个查询语句仅仅扫描了表中的一条记录,其它查询速度天然比扫描3条记录快。而且possible_keys 和key的值都是ix_emp_name 。这说明查询时使用了ix_emp_name 索引。假设表中记录有100条、1000条、10000条优点就显现出来了
(3)使用索引查询
索引可以提升查询速度,但并不是使用带有索引的字段查询时,索引都会起做用。
如下的几种状况跟跟SQLSERVER同样,有可能用不到索引
(1)使用likekeyword的查询语句
使用likekeyword进行查询的时候,假设匹配字符串的第一个字符为“%”。索引不起做用。仅仅有“%”不在第一个位置,索引才会起做用
使用likekeyword,并且匹配字符串中含有“%”字符,EXPLAIN语句例如如下
USE test; EXPLAIN SELECT * FROM `test`.`emp` WHERE `name` LIKE '%x';
USE test; EXPLAIN SELECT * FROM `test`.`emp` WHERE `name` LIKE 'x%';
name上有索引ix_emp_name
第一个查询type为ALL,表示要全表扫描
第二个查询TYPE为index。表示会扫描索引
like keyword可否利用上索引跟SQLSERVER是同样的
我以前写过一篇文章:like语句百分号前置会使用到索引吗?
(2)使用多列索引的查询语句
mysql可以为多个字段建立索引。一个索引可以包含16个字段(跟SQLSERVER同样)对于多列索引,仅仅有查询条件中使用了
这些字段中的第一个字段时,索引才会被使用。这个字段叫:前导索引或前导列
在表person中name,age字段建立多列索引,验证多列索引的状况
CREATE INDEX ix_person_name_age ON `person` (name,age) EXPLAIN SELECT ID,Name,Age,job FROM `person` WHERE `Name` ='suse'
EXPLAIN SELECT ID,Name,Age,job FROM `person` WHERE `age` =12
从第一条查询看出,WHERE `Name` ='suse'的记录有一条。扫描了一条记录并且使用了ix_person_name_age 索引
从第二条记录可以看出,rows列的值为4,说明共扫描了4条记录。并且key列值为NULL,说明EXPLAIN SELECT ID,Name,Age,job FROM `person` WHERE `age` =12
语句并无使用索引。因为age字段是多列索引的第二个字段。仅仅有查询条件中使用了name字段才会使用ix_person_name_age 索引
这个跟SQLSERVER是同样的。具体请看:SQLSERVER汇集索引与非汇集索引的再次研究(下)
(3)使用ORkeyword的查询语句
查询语句的查询条件中仅仅有ORkeyword,而且OR先后的两个条件中的列都是索引时,查询中才使用索引,不然,查询不使用索引
查询语句使用ORkeyword的状况
咱们再建立一个索引
CREATE INDEX ix_person_age ON `person` (age) EXPLAIN SELECT Name,Age FROM `person` WHERE `Name` ='SUSE' OR `job`='SPORTMAN'
EXPLAIN SELECT Name,Age FROM `person` WHERE `AGE` =2 OR `Name` ='SUSE'
你们要注意。这里跟刚才不同,此次咱们select的字段仅仅有name和age。而不是select出全部字段
因为并无在job这个字段上创建索引,因此第一个查询使用的是全表扫描
第二个查询因为name字段和age字段都有索引,那么mysql可以利用这两个索引的当中之中的一个,这里是ix_person_name_age索引来查找记录。利用索引来查找记录会快很是多
(4)优化子查询
mysql从4.1版本号開始支持子查询。使用子查询可以进行SELECT语句的嵌套查询,即一个SELECT查询的结果做为还有一个SELECT语句的条件
子查询可以一次性完毕很是多逻辑需要多个步骤才干完毕的SQL操做。子查询尽管使查询语句灵活。但是运行效率不高。
运行子查询时,mysql需要为内层查询语句结果创建一个暂时表。而后外层查询语句从暂时表中查询记录
查询完成后,再撤销暂时表。
所以。子查询的速度会受到必定影响。假设查询的数据量特别大,这样的影响就会更大。
在mysql中。可以使用链接(join)查询来取代子查询。
链接查询不需要创建暂时表,其速度比子查询快,假设查询中使用索引的话,性能会更好。
因此很是多网上的文章都说尽可能使用join来取代子查询,尽管网上也说mysql5.7对于子查询有很是大的改进,但是假设不是使用mysql5.7仍是需要注意的
假设系统中join语句特别多还需要注意改动my.ini或my.cnf文件里的join_buffer_size大小。预防性能问题
优化数据库结构
一个好的数据库设计方案对于数据库的性能常常起到事半功倍的效果。
数据库结构的设计需要考虑数据冗余、查询和更新速度、字段的数据类型是否合理等多方面
(1)将字段很是多的表拆分红多个表
有时候有些字段使用频率很是低或者字段的数据类型比較大,那么可以考虑垂直拆分的方法,把不常用的字段和大字段拆分出去
(2)添加中间表
对于需要经常联合查询的表,可以创建中间表以提升查询效率。经过创建中间表,把需要经常联合查询的数据插入到中间表中,而后将原来的联合查询改成对中间表的查询。以此来提升查询效率。
(3)添加冗余字段
设计数据库表时应尽可能遵循范式理论,尽量下降冗余字段,但是现今存储硬件愈来愈廉价,有时候查询数据的时候需要join多个表。这样在高峰期间会影响查询的效率。咱们需要反范式而为之。添加一些必要的冗余字段,以空间换时间需要这样作会添加开发的工做量和维护量。但是假设能换来可观的性能提高,这样作也是值得的
(4)优化插入记录的速度
插入记录时,影响插入速度的主要是索引、惟一性校验、一次插入记录条数等。
依据实际状况,可以分别进行优化
对于myisam表。常见优化方法例如如下:
一、禁用索引
对于非空表,插入记录时,mysql会依据表的索引对插入的记录创建索引。假设插入大量数据,创建索引会减小插入记录的速度。
为了解决问题,可以在插入记录以前禁用索引。数据插入完成后再开启索引
禁用索引语句例如如下:
ALTER TABLE table_name DISABLE KEYS ;
当中table_name是禁用索引的表的表名
又一次开启索引语句例如如下:
ALTER TABLE table_name ENABLE KEYS ;
对于空表批量导入数据,则不需要进行此操做,因为myisam表是在导入数据以后才创建索引。
二、禁用惟一性检查
插入数据时,mysql会对插入的记录进行惟一性校验。这样的惟一性校验也会减小插入记录的速度。
为了减小这样的状况对查询速度的影响,可以在插入记录以前禁用惟一性检查,等到记录插入完成以后再开启
禁用惟一性检查的语句例如如下:
SET UNIQUE_CHECKS=0;
开启惟一性检查的语句例如如下:
SET UNIQUE_CHECKS=1;三、使用批量插入
插入多条记录时,可以使用一条INSERT语句插入一条记录,也可以使用一条INSERT语句插入多条记录。
第一种状况
INSERT INTO emp(id,name) VALUES (1,'suse'); INSERT INTO emp(id,name) VALUES (2,'lily'); INSERT INTO emp(id,name) VALUES (3,'tom');
另一种状况
INSERT INTO emp(id,name) VALUES (1,'suse'),(2,'lily'),(3,'tom')
另一种状况要比第一种状况要快
四、使用LOAD DATA INFILE批量导入
当需要批量导入数据时。假设能用LOAD DATA INFILE语句,就尽可能使用。因为LOAD DATA INFILE语句导入数据的速度比INSERT语句快很是多
对于INNODB引擎的表,常见的优化方法例如如下:
一、禁用惟一性检查
插入数据时。mysql会对插入的记录进行惟一性校验。
这样的惟一性校验也会减小插入记录的速度。
为了减小这样的状况对查询速度的影响,可以在插入记录以前禁用惟一性检查,等到记录插入完成以后再开启
禁用惟一性检查的语句例如如下:
SET UNIQUE_CHECKS=0;
开启惟一性检查的语句例如如下:
SET UNIQUE_CHECKS=1;
二、禁用外键约束
插入数据以前运行禁止对外键的检查,数据插入完毕以后再恢复对外键的检查。禁用外键检查的语句例如如下:
SET FOREIGN_KEY_CHECKS=0;
恢复对外键的检查语句例如如下
SET FOREIGN_KEY_CHECKS=1;
三、禁止本身主动提交
插入数据以前禁止事务的本身主动提交,数据导入完毕以后。运行恢复本身主动提交操做或显式指定事务
USE test; START TRANSACTION; INSERT INTO emp(name) VALUES('ming'); INSERT INTO emp(name) VALUES('lily'); commit;
(5)分析表、检查表、优化表、修复表和CHECKSUM表
mysql提供了分析表、检查表和优化表的语句
分析表主要是分析keyword的分布。
检查表主要是检查表是否存在错误;
优化表主要是消除删除或者更新形成的空间浪费
修复表主要对myisam表文件进行修复
CHECKSUM表主要对表传输数据前和传输后进行比較
一、分析表
mysql中提供了ANALYZE TABLE 语句分析表。ANALYZE TABLE 语句的基本的语法例如如下
ANALYZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE TBL_NAME [,TBL_NAME]...
LOCALkeyword是NO_WRITE_TO_BINLOGkeyword的别名,两者都是运行过程不写入二进制日志,tbl_name为分析的表的表名可以有一个或多个
使用ANALYZE TABLE 分析表的过程当中,数据库系统会本身主动对表加一个仅仅读锁。在分享期间,仅仅能读取表的记录。不能更新和插入记录
ANALYZE TABLE 语句能分析INNODB、BDB和MYISAM类型的表
使用ANALYZE TABLE 来分析emp表,运行语句例如如下:
ANALYZE TABLE emp;
上面结果显示说明
table:表示分析的表名
op:表示运行的操做。analyze表示进行分析操做
msg_type:表示信息类型其值通常是状态(status)、信息(info)、注意(note)、警告(warning)和错误(error)之中的一个
msg_text:显示信息
实际上分析表跟SQLSERVER里的更新统计信息是几乎相同的
主要就是为了索引的基数更加准确。从而使查询优化器能够更加准确的预估行数
emp表的记录行数是18
分析表以后。Cardinality 基数更加准确了
二、检查表
mysql中使用check table语句来检查表。check table语句能够检查innodb和myisam类型的表是否存在错误。
对于myisam类型的表,check table语句还会更新keyword统计数据。
而且,check table也可以检查视图是否有错误,
比方在视图定义中被引用的表已不存在。
该语句基本的语法例如如下:
CHECK TABLE TBL_NAME [,tbl_name]...[option]... option={QUICK|FAST|MEDIUM|EXTENDED|CHANGED}
当中。tbl_name是表名。option參数有5个取值各自是QUICK、FAST、MEDIUM、EXTENDED、CHANGED
各个选项的意思各自是
QUICK:不扫描行。不检查错误的链接
FAST:仅仅检查没有被正确关闭的表
MEDIUM:扫描行。以验证被删除的链接是有效的,也可以计算各行的keyword校验和,并使用计算出的校验和验证这一点
EXTENDED:对每行的所有keyword进行一个全面的keyword查找。这可以确保表是100%一致的,但是花的时间较长
CHANGED:仅仅检查上次检查后被更改的表和没有被正确关闭的表
option仅仅对myisam表有效。对innodb表无效。
check table语句在运行过程当中也会给表加上仅仅读锁。
三、优化表
mysql中使用OPTIMIZE TABLE语句来优化表。该语句对INNODB和MYISAM表都有效。但是,OPTIMIZE TABLE语句仅仅能优化表中的
VARCHAR、BLOB、TEXT类型的字段
OPTIMIZE TABLE语句的基本的语法例如如下:
OPTIMIZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE TBL_NAME [,TBL_NAME]...
LOCAL和NO_WRITE_TO_BINLOGkeyword的意义和分析表一样,都是指定不写入二进制日志
tbl_name是表名
经过OPTIMIZE TABLE语句可以消除删除和更新形成的文件碎片。
OPTIMIZE TABLE语句在运行过程当中也会给表加上仅仅读锁。
提示:一个表使用了TEXT或者BLOB这种数据类型,假设已经删除了表的一大部分,或者已经对含有可变长度行的表(含有VARCHAR、BLOB或TEXT列的表)进行了很是多更新。则应使用OPTIMIZE TABLE来又一次利用未使用的空间。并整理数据文件的碎片。在多数设置中,根本不需要执行OPTIMIZE TABLE。即便对可变长度的行进行了大量更新,也不需要经常执行。每周一次或每个月一次就能够,并且仅仅需要对特定表进行OPTIMIZE TABLE OPTIMIZE TABLE语句相似于SQLSERVER的重建索引和收缩数据文件的功能
四、修复表
mysql中使用Repair Table来修复myisam表,仅仅对MyISAM和ARCHIVE类型的表有效。
REPAIR [LOCAL|NO_WRITE_TO_BINLOG] TABLE TBL_NAME [,tbl_name]...[option]... option={QUICK|EXTENDED|USE_FRM}
选项的意思各自是:
QUICK:最快的选项,仅仅修复索引树。
EXTENDED:最慢的选项,需要逐行重建索引。
USE_FRM:仅仅有当MYI文件丢失时才使用这个选项。全面重建整个索引。
与Analyze Table同样,Repair Table也可以使用local来取消写入binlog。
五、Checksum 表
数据在传输时,可能会发生变化,也有可能因为其余缘由损坏,为了保证数据的一致。咱们可以计算checksum(校验值)。
使用MyISAM引擎的表会把checksum存储起来,称为live checksum,当数据发生变化时,checksum会对应变化。
语法例如如下:
CHECKSUM TABLE tbl_name [, tbl_name] ... [ QUICK | EXTENDED ]
quick:表示返回存储的checksum值
extended:表示又一次计算checksum
假设没有指定选项,则默认使用extended。
Checksum 表主要用来对照在传输表数据以前和表数据以后。表的数据是否发生了变化,好比插入了数据或者删除了数据,或者有数据损坏
CHECKSUM值都会改变。
优化MYSQLserver
水电费优化mysqlserver主要从两个方面入手,一方面是对硬件进行优化;还有一方面是对mysqlserver的參数进行优化
一、优化server硬件
server的硬件性能直接决定着MYSQL数据库的性能。
硬件的性能瓶颈直接决定MYSQL数据库的执行速度和效率。
优化server硬件的几种方法
(1)配置较大的内存。
足够大的内存,是提升mysql数据库性能之中的一个。
内存速度比磁盘I/O快得多,可以经过添加系统缓冲区容量。使数据库
在内存停留时间更长,以下降磁盘I/O
(2)配置快速磁盘系统。以下降读盘等待时间,提升响应速度
(3)合理分布磁盘I/O,把磁盘I/O分散在多个设备上,以下降资源竞争,提升并行操做能力
(4)配置多处理器。mysql是多线程的数据库,多处理器可同一时候运行多个线程
二、优化MYSQL的參数
经过优化MYSQL的參数可以提升资源利用率。从而达到提升MYSQLserver的性能的目的。
MYSQLserver的配置參数都在my.cnf或者my.ini文件的[mysqld]组中。
如下对几个对性能影响较大的參数进行介绍
咱们先看一下与网络链接的性能配置项及对性能的影响。 ● max_conecctions:整个 MySQL 赞成的最大链接数。 这个參数主要影响的是整个 MySQL 应用的并发处理能力,当系统中实际需要的链接量大于 max_conecctions 的状况下,因为 MySQL 的设置限制,那么应用中一定会产生链接请求的等待, 从而限制了相应的并发量。因此通常来讲,仅仅要 MySQL 主机性能赞成,都是将该參数设置的尽 可能大一点。通常来讲 500 到 800 左右是一个比較合适的參考值 ● max_user_connections:每个用户赞成的最大链接数; 上面的參数是限制了整个 MySQL 的链接数。而 max_user_connections 则是针对于单个用户的连 接限制。在普通状况下咱们可能都较少使用这个限制。仅仅有在一些专门提供 MySQL 数据存储服 务,或者是提供虚拟主机服务的应用中可能需要用到。除了限制的对象差异以外,其它方面和 max_connections 同样。
这个參数的设置全然依赖于应用程序的链接用户数,对于普通的应用来 说,全然没有作太多的限制,可以尽可能放开一些。 ● net_buffer_length:网络包传输中。传输消息以前的 net buffer 初始化大小。 这个參数主要可能影响的是网络传输的效率,因为该參数所设置的仅仅是消息缓冲区的初始化大 小。因此形成的影响主要是当咱们的每次消息都很是大的时候 MySQL 老是需要屡次申请扩展该缓 冲区大小。
系统默认大小为 16KB。通常来讲可以知足大多数场景。固然假设咱们的查询都是非 常小。每次网络传输量都很是少。而且系统内存又比較紧缺的状况下。也可以适当将该值下降到 8KB。 ● max_allowed_packet:在网络传输中,一次传消息输量的最大值; 这个參数与 net_buffer_length 相相应,仅仅只是是 net buffer 的最大值。当咱们的消息传输量 大于 net_buffer_length 的设置时。MySQL 会本身主动增大 net buffer 的大小。直到缓冲区大小达 到 max_allowed_packet 所设置的值。系统默认值为 1MB,最大值是 1GB,必须设定为 1024 的倍 数。单位为字节。 ● back_log:在 MySQL 的链接请求等待队列中赞成存放的最大链接请求数。
链接请求等待队列,其实是指当某一时刻client的链接请求数量过大的时候,MySQL 主线程没 办法及时给每个新的链接请求分配(或者建立)链接线程的时候,尚未分配到链接线程的 所有请求将存放在一个等待队列中。这个队列就是 MySQL 的链接请求队列。当咱们的系统存在 瞬时的大量链接请求的时候,则应该注意 back_log 參数的设置。
系统默认值为 50,最大可以设 置为 65535。当咱们增大 back_log 的设置的时候。同一时候还需要主义 OS 级别对网络监听队列的限 制,因为假设 OS 的网络监听设置小于 MySQL 的 back_log 设置的时候,咱们加大“back_log”设 置是没有意义的。 上面介绍了网络链接交互相关的主要优化设置,如下咱们再来看看与每个client链接想相应的连 接线程。 在 MySQL 中。为了尽可提升client请求建立链接这个过程的性能,实现了一个 Thread Cache 池,将 空暇的链接线程存放在当中。而不是完毕请求后就销毁。这样,当有新的链接请求的时候,MySQL 首先会 检查 Thread Cache 池中是否存在空暇链接线程,假设存在则取出来直接使用,假设没有空暇链接线程。 才建立新的链接线程。
在 MySQL 中与链接线程相关的系统參数及状态变量说明例如如下: ● thread_cache_size:Thread Cache 池中应该存放的链接线程数。 当系统最初启动的时候,并不会当即就建立 thread_cache_size 所设置数目的链接线程存放在 Thread Cache 池中,而是随着链接线程的建立及使用,慢慢的将用完的链接线程存入当中。当 存放的链接线程达到 thread_cache_size 值以后。MySQL 就不会再续保存用完的链接线程了。
假设咱们的应用程序使用的短链接。Thread Cache 池的功效是最明显的。因为在短链接的数据 库应用中,数据库链接的建立和销毁是很是频繁的。假设每次都需要让 MySQL 新建和销毁相应 的链接线程,那么这个资源消耗其实是很是大的,而当咱们使用了 Thread Cache 以后。因为 链接线程大部分都是在建立好了等待取用的状态,既不需要每次都又一次建立。又不需要在使用 完 之 后 销 毁 , 所 以 可 以 节 省 下 大 量 的 系 统 资 源 。 所 以 在 短 连 接 的 应 用 系 统 中 , thread_cache_size 的值应该设置的相对大一些。不该该小于应用系统对数据库的实际并发请求 数。 而假设咱们使用的是长链接的时候,Thread Cache 的功效可能并无使用短链接那样的大。但 也并不是全然没有价值。
因为应用程序即便是使用了长链接,也很是难保证他们所管理的所有连 接都能处于很是稳定的状态,仍然会有很多链接关闭和新建的操做出现。在有些并发量较高。应 用server数量较大的系统中,每分钟十來次的链接建立与关闭的操做是非常常见的。而且假设应 用server的链接池管理不是太好,easy产生链接池抖动的话。所产生的链接建立和销毁操做将 会不少其它。
因此即便是在使用长链接的应用环境中,Thread Cache 机制的利用仍然是对性能大有 帮助的。仅仅只是在长链接的环境中咱们不需要将 thread_cache_size 參数设置太大,通常来讲 可能 50 到 100 之间应该就可以了。 ● thread_stack:每个链接线程被建立的时候,MySQL 给他分配的内存大小。 当 MySQL 建立一个新的链接线程的时候,是需要给他分配必定大小的内存堆栈空间,以便存放 client的请求 Query 以及自身的各类状态和处理信息。只是通常来讲假设不是对 MySQL 的链接线 程处理机制十分熟悉的话,不该该轻易调整该參数的大小,使用系统的默认值(192KB)基本上 可以所有的普通应用环境。假设该值设置过小。会影响 MySQL 链接线程可以处理client请求的 Query 内容的大小,以及用户建立的 Procedures 和 Functions 等 计算出系统新建链接链接的 Thread Cache 命中率。也就是经过 Thread Cache 池中取得链接线程的次数与系统接收的总链接次数的比率,如 下: Threads_Cache_Hit = (Connections - Threads_created) / Connections * 100% 咱们可以经过上面的这个运算公式计算一下上面环境中的 Thread Cache 命中率:Thread_Cache_Hit = (127 - 12) / 127 * 100% = 90.55% 通常来讲,当系统稳定运行一段时间以后,咱们的 Thread Cache 命中率应该保持在 90%左右甚至更 高的比率才算正常。可以看出上面环境中的 Thread Cache 命中比率基本还算是正常的。 Table Cache 相关的优化 咱们先来看一下 MySQL 打开表的相关机制。因为多线程的实现机制。为了尽量的提升性能,在 MySQL 中每个线程都是独立的打开本身需要的表的文件描写叙述符,而不是经过共享已经打开的表的文件描写叙述 符的机制来实现。固然。针对于不一样的存储引擎可能有不一样的处理方式。如 MyISAM 表,每个client线 程打开不论什么一个 MyISAM 表的数据文件都需要打开一个文件描写叙述符。但假设是索引文件。则可以多个线程 共享同一个索引文件的描写叙述符。对于 Innodb 的存储引擎,假设咱们使用的是共享表空间来存储数据,那 么咱们需要打开的文件描写叙述符就比較少,而假设咱们使用的是独享表空间方式来存储数据,则相同。由 于存储表数据的数据文件较多,则相同会打开很是多的表文件描写叙述符。
除了数据库的实际表或者索引打开 之外。暂时文件相同也需要使用文件描写叙述符,相同会占用系统中 open_files_limit 的设置限额。
为了解决打开表文件描写叙述符太过频繁的问题,MySQL 在系统中实现了一个 Table Cache 的机制,和前 面介绍的 Thread Cache 机制有点相似,主要就是 Cache 打开的所有表文件的描写叙述符。当有新的请求的时 候不需要再又一次打开,使用结束的时候也不用当即关闭。经过这种方式来下降因为频繁打开关闭文件 描写叙述符所带来的资源消耗。咱们先看一看 Table Cache 相关的系统參数及状态变量。 在 MySQL 中咱们经过 table_cache(从 MySQL5.1.3 開始改成 table_open_cache),来设置系统中为 咱们 Cache 的打开表文件描写叙述符的数量。
经过 MySQL 官方手冊中的介绍,咱们设置 table_cache 大小的时 候应该经过 max_connections 參数计算得来,公式例如如下: table_cache = max_connections * N; 当中 N 表明单个 Query 语句中所包括的最多 Table 的数量。但是我我的理解这种计算事实上并不是太 准确。分析例如如下: 首先,max_connections 是系统同一时候可以接受的最大链接数。但是这些链接并不必定都是 active 状 态的,也就是说可能里面有很多链接都是处于 Sleep 状态。而处于 Sleep 状态的链接是不可能打开不论什么 Table 的。 其次,这个 N 为运行 Query 中包括最多的 Table 的 Query 所包括的 Table 的个数也并不是太合适,因 为咱们不能忽略索引文件的打开。尽管索引文件在各个链接线程之间是可以共享打开的链接描写叙述符的, 但总仍是需要的。而且。假设我 Query 中的每个表的訪问都是经过现经过索引定位检索的,甚至可能还 是经过多个索引。那么该 Query 的运行所需要打开的文件描写叙述符就不少其它了,多是 N 的两倍甚至三倍。 最后,这个计算的公式仅仅能计算出咱们同一时刻需要打开的描写叙述符的最大数量,而 table_cache 的 设置也不必定非得依据这个极限值来设定,因为 table_cache 所设定的仅仅是 Cache 打开的描写叙述符的数量的 大小,而不是最多可以打开的量的大小。 join_buffer_size :当咱们的 Join 是 ALL 。 index , rang 或者 index_merge 的时候使用的 Buffer; 实际上这种 Join 被称为 Full Join。实际上參与 Join 的每个表都需要一个 Join Buffer,因此在 Join 出现的时候,至少是两个。Join Buffer 的设置在 MySQL 5.1.23 版本号以前最大为 4GB,但是从 5.1.23 版本号開始,在除了 Windows 以外的 64 位的平台上可以超出 4BG 的限制。系统默认是 128KB。
● sort_buffer_size:系统中对数据进行排序的时候使用的 Buffer; Sort Buffer 相同是针对单个 Thread 的,因此当多个 Thread 同一时候进行排序的时候。系统中就会出现 多个 Sort Buffer。通常咱们可以经过增大 Sort Buffer 的大小来提升 ORDER BY 或者是 GROUP BY 的处理性能。系统默认大小为 2MB。最大限制和 Join Buffer 同样。在 MySQL 5.1.23 版本号以前最大 为 4GB,从 5.1.23 版本号開始,在除了 Windows 以外的 64 位的平台上可以超出 4GB 的限制。 假设应用系统中很是少有 Join 语句出现,则可以不用太在意 join_buffer_size 參数的大小设置,但是 假设 Join 语句不是很是少的话,我的建议可以适当增大 join_buffer_size 的设置到 1MB 左右,假设内存充 足甚至可以设置为 2MB。对于 sort_buffer_size 參数来讲,通常设置为 2MB 到 4MB 之间可以知足大多数 应用的需求。固然。假设应用系统中的排序都比較大,内存充足且并发量不是特别的大的时候,也可以 继续增大 sort_buffer_size 的设置。
在这两个 Buffer 设置的时候,最需要注意的就是不要忘记是每个 Thread 都会建立本身独立的 Buffer,而不是整个系统共享的 Buffer,不要因为设置过大而形成系统内存 不足。
配置完參数以后,需要从新启动MYSQL服务才干生效
怎样使用查询缓冲区
查询缓冲区可以提升查询的速度。但是这样的方式仅仅适合查询语句多、更新较少的状况。默认状况下查询缓冲区的大小为0,也就是不可用
可以改动query_cache_size以调整查询缓冲区大小。改动 query_cache_type以调整查询缓冲区的类型。
在my.ini中改动query_cache_size和query_cache_type的值例如如下所看到的
[mysqld] query_cache_size=512M query_cache_type=1
query_cache_type=1表示开启查询缓冲区。仅仅有在查询语句中包括SQL_NO_CACHEkeyword时,才不会使用查询缓冲区。
可以使用FLUSH QUERY CACHE语句来刷新缓冲区,清理查询缓冲区中的碎片
注意:开启查询缓冲区是有风险的,假设命中率不高,或者更新改动语句较多,都会使查询缓冲区失效,从而使命中率更加低
建议使用memcached等软件来作二级缓存,除非系统中改动语句较少,命中率较高,这样才会看到明显的性能提高