MYSQL应该是最流行了WEB后端数据库。WEB开发语言最近发展很快,PHP,Ruby,Python,Java各有特点,虽然NOSQL最近越來越多的被提到,但是相信大部分架构师还是会选择MYSQL来做数据存储。
MYSQL如此方便和稳定,以至于我们在开发WEB程序的时候很少想到它。即使想到优化也是程序级别的,比如,不要写过于消耗资源的SQL语句。但是除此之外,在整个系统上仍然有很多可以优化的地方。
1.选择合适的存储引擎:InnoDB
除非你的数据表使用来做只读或者全文检索(相信现在提到全文检索,没人会用MYSQL了),你应该默认选择InnoDB。
你自己在测试的时候可能会发现MyISAM比InnoDB速度快,这是因为:MyISAM只缓存索引,而InnoDB缓存数据和索引,MyISAM不支持事务。但是如果你使用innodb_flush_log_at_trx_commit=2可以获得接近的读取性能(相差百倍)。
1.1如何将现有的MyISAM数据库转换为InnoDB:
代码如下:mysql-u[USER_NAME]-p-e”SHOWTABLESIN[DATABASE_NAME];”|tail-n+2|xargs-I'{}’echo”ALTERTABLE{}ENGINE=InnoDB;”>alter_table.sql
perl-p-i-e’s/(search_[a-z_]+ENGINE=)InnoDB//1MyISAM/g’alter_table.sql
mysql-u[USER_NAME]-p[DATABASE_NAME]<alter_table.sql
1.2为每个表分别创建InnoDBFILE:
代码如下:innodb_file_per_table=1
这样可以保证ibdata1文件不会过大,失去控制。尤其是在执行mysqlcheck-o–all-databases的时候。
2.保证从内存中读取数据,讲数据保存在内存中
2.1足够大的innodb_buffer_pool_size
推荐将数据完全保存在innodb_buffer_pool_size,即按存储量规划innodb_buffer_pool_size的容量。这样你可以完全从内存中读取数据,最大限度减少磁盘操作。
2.1.1如何确定innodb_buffer_pool_size足够大,数据是从内存读取而不是硬盘?
方法1
mysql>SHOWGLOBALSTATUSLIKE'innodb_buffer_pool_pages_%'; +----------------------------------+--------+ |Variable_name|Value| +----------------------------------+--------+ |Innodb_buffer_pool_pages_data|129037| |Innodb_buffer_pool_pages_dirty|362| |Innodb_buffer_pool_pages_flushed|9998| |Innodb_buffer_pool_pages_free|0|!!!!!!!! |Innodb_buffer_pool_pages_misc|2035| |Innodb_buffer_pool_pages_total|131072| +----------------------------------+--------+ 6rowsinset(0.00sec)
发现Innodb_buffer_pool_pages_free为0,则说明bufferpool已经被用光,需要增大innodb_buffer_pool_size
InnoDB的其他几个参数:
代码如下:innodb_additional_mem_pool_size=1/200ofbuffer_pool
innodb_max_dirty_pages_pct80%
方法2
或者用iostat-d-x-k1命令,查看硬盘的操作。
2.1.2服务器上是否有足够内存用来规划
执行echo1>/proc/sys/vm/drop_caches清除操作系统的文件缓存,可以看到真正的内存使用量。
2.2数据预热
默认情况,只有某条数据被读取一次,才会缓存在innodb_buffer_pool。所以,数据库刚刚启动,需要进行数据预热,将磁盘上的所有数据缓存到内存中。数据预热可以提高读取速度。
对于InnoDB数据库,可以用以下方法,进行数据预热:
1.将以下脚本保存为MakeSelectQueriesToLoad.sql
SELECTDISTINCT CONCAT('SELECT',ndxcollist,'FROM',db,'.',tb, 'ORDERBY',ndxcollist,';')SelectQueryToLoadCache FROM ( SELECT engine,table_schemadb,table_nametb, index_name,GROUP_CONCAT(column_nameORDERBYseq_in_index)ndxcollist FROM ( SELECT B.engine,A.table_schema,A.table_name, A.index_name,A.column_name,A.seq_in_index FROM information_schema.statisticsAINNERJOIN ( SELECTengine,table_schema,table_name FROMinformation_schema.tablesWHERE engine='InnoDB' )BUSING(table_schema,table_name) WHEREB.table_schemaNOTIN('information_schema','mysql') ORDERBYtable_schema,table_name,index_name,seq_in_index )A GROUPBYtable_schema,table_name,index_name )AA ORDERBYdb,tb ;
2.执行
代码如下:mysql-uroot-AN</root/MakeSelectQueriesToLoad.sql>/root/SelectQueriesToLoad.sql
3.每次重启数据库,或者整库备份前需要预热的时候执行:
mysql-uroot</root/SelectQueriesToLoad.sql>/dev/null2>&1
2.3不要让数据存到SWAP中
如果是专用MYSQL服务器,可以禁用SWAP,如果是共享服务器,确定innodb_buffer_pool_size足够大。或者使用固定的内存空间做缓存,使用memlock指令。
3.定期优化重建数据库
mysqlcheck-o–all-databases会让ibdata1不断增大,真正的优化只有重建数据表结构:
CREATETABLEmydb.mytablenewLIKEmydb.mytable; INSERTINTOmydb.mytablenewSELECT*FROMmydb.mytable; ALTERTABLEmydb.mytableRENAMEmydb.mytablezap; ALTERTABLEmydb.mytablenewRENAMEmydb.mytable; DROPTABLEmydb.mytablezap;
4.减少磁盘写入操作
4.1使用足够大的写入缓存innodb_log_file_size
但是需要注意如果用1G的innodb_log_file_size,假如服务器当机,需要10分钟来恢复。
推荐innodb_log_file_size设置为0.25*innodb_buffer_pool_size
4.2innodb_flush_log_at_trx_commit
这个选项和写磁盘操作密切相关:
innodb_flush_log_at_trx_commit=1则每次修改写入磁盘
innodb_flush_log_at_trx_commit=0/2每秒写入磁盘
如果你的应用不涉及很高的安全性(金融系统),或者基础架构足够安全,或者事务都很小,都可以用0或者2来降低磁盘操作。
4.3避免双写入缓冲
代码如下:innodb_flush_method=O_DIRECT
5.提高磁盘读写速度
RAID0尤其是在使用EC2这种虚拟磁盘(EBS)的时候,使用软RAID0非常重要。
6.充分使用索引
6.1查看现有表结构和索引
代码如下:SHOWCREATETABLEdb1.tb1/G
6.2添加必要的索引
索引是提高查询速度的唯一方法,比如搜索引擎用的倒排索引是一样的原理。
索引的添加需要根据查询来确定,比如通过慢查询日志或者查询日志,或者通过EXPLAIN命令分析查询。
代码如下:ADDUNIQUEINDEX
ADDINDEX
6.2.1比如,优化用户验证表:
添加索引
代码如下:ALTERTABLEusersADDUNIQUEINDEXusername_ndx(username);
ALTERTABLEusersADDUNIQUEINDEXusername_password_ndx(username,password);
每次重启服务器进行数据预热
代码如下:echo“selectusername,passwordfromusers;”>/var/lib/mysql/upcache.sql
添加启动脚本到my.cnf
代码如下:[mysqld]
init-file=/var/lib/mysql/upcache.sql
6.2.2使用自动加索引的框架或者自动拆分表结构的框架
比如,Rails这样的框架,会自动添加索引,Drupal这样的框架会自动拆分表结构。会在你开发的初期指明正确的方向。所以,经验不太丰富的人一开始就追求从0开始构建,实际是不好的做法。
7.分析查询日志和慢查询日志
记录所有查询,这在用ORM系统或者生成查询语句的系统很有用。
代码如下:log=/var/log/mysql.log
注意不要在生产环境用,否则会占满你的磁盘空间。
记录执行时间超过1秒的查询:
代码如下:long_query_time=1
log-slow-queries=/var/log/mysql/log-slow-queries.log
8.激进的方法,使用内存磁盘
现在基础设施的可靠性已经非常高了,比如EC2几乎不用担心服务器硬件当机。而且内存实在是便宜,很容易买到几十G内存的服务器,可以用内存磁盘,定期备份到磁盘。
将MYSQL目录迁移到4G的内存磁盘
mkdir-p/mnt/ramdisk sudomount-ttmpfs-osize=4000Mtmpfs/mnt/ramdisk/ mv/var/lib/mysql/mnt/ramdisk/mysql ln-s/tmp/ramdisk/mysql/var/lib/mysql chownmysql:mysqlmysql
9.用NOSQL的方式使用MYSQL
B-TREE仍然是最高效的索引之一,所有MYSQL仍然不会过时。
用HandlerSocket跳过MYSQL的SQL解析层,MYSQL就真正变成了NOSQL。
10.其他
单条查询最后增加LIMIT1,停止全表扫描。
将非”索引”数据分离,比如将大篇文章分离存储,不影响其他自动查询。
不用MYSQL内置的函数,因为内置函数不会建立查询缓存。
PHP的建立连接速度非常快,所有可以不用连接池,否则可能会造成超过连接数。当然不用连接池PHP程序也可能将
连接数占满比如用了@ignore_user_abort(TRUE);
使用IP而不是域名做数据库路径,避免DNS解析问题
上述就是数据库技术:10个MySQL性能调优的方法分享的全部内容,如果对大家有所用处且需要了解更多关于mysql数据库学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/dtteaching/911962.html