数据库优化的目的
优化用户体验,提高响应速度,使得应用具有一个良好的用户体验。
数据库优化的几个方面
这几个方面优化的效果是逐渐降低的,并且优化的成本也是逐渐增加的。
SQL及索引
表结构
MySQL配置
系统配置和硬件
1.SQL及索引
SQL语句的优化步骤:
开启MySQL慢查日志(slow_query_log)。
分析MySQL慢查日志,通过使用一些MySQL慢查日志分析工具(mysqldumpslow、pt-query-digest)。
优先查找出一些查询次数多且执行时间长的SQL语句。
explain查询SQL语句的执行计划,针对执行计划进行优化。
具体的SQL语句优化:
网查。
索引优化:
索引字段长度越小越好。因为数据库中数据存储单位是“页”,索引字段长度越小一次IO读取的索引会更多,越容易命中对应的值。(大意就是不要选择text列上面建立一个索引,而是选择简单的数据类型比如int。)
联合索引顺序,离散度大的列放到联合索引的前面。(离散度就是差异程度,列上不同的值越多,离散程度就越大。)
使用pt-duplicate-key-checker工具检查重复及冗余索引,删除重复及冗余的索引。
2.表结构
表的范式化,一般是指第三范式(3NF)。
反范式化,针对业务,表做适当的冗余。
使用可以存下你的数据的最小数据类型。
尽可能使用简单的数据类型。(int类型要比varchar类型mysql处理起来更简单)
尽可能使用not null定义字段,使用一个默认值来替代空值,除了需要存储为null的情况。(null 并不是真正意义上的空值,null 也会占用空间。null 列一般需要一个额外的字节作为判断是否为 null 的标志位,占用更多的存储空间。使得索引、索引统计和值比较更加复杂,每个索引记录需要一个额外的字节作为判断是否为 null 的标志位。)
尽量少用text等大类型,非用不可时考虑分表。
表的垂直拆分,解决表的宽度过宽的问题。(把不常用的字段拆分出一张表;把大字段拆分出一张表;把经常使用的字段拆分出一张表。)
表的水平拆分,解决表的数据量过大的问题。(一般对主键做hash运算来分散到几张表中。)
3.MySQL配置
MySQL可以通过启动时指定配置参数和使用配置文件两种方法进行配置,在大多数情况下配置文件位于/etc/mysql/my.cnf。
一些常见参数:
参数
作用
max_connections
Mysql最大连接数。参数对性能影响不大,一般设置的大一些避免”Too many connections”的错误。
innodb_buffer_pool_size
Innodb缓冲池总大小。建议内存的80%,建议大于表数据加索引的和。
innodb_buffer_pool_instances
Innodb缓冲池的个数。
innodb_log_buffer_size
Innodb日志缓冲大小,由于日志最长每秒就会刷新,所以一般不用太大。
innodb_flush_log_at_trx_commit
0:事务提交时,不将重做日志缓冲写入磁盘,而是依靠 InnoDB 的主线程每秒执行一次刷新到磁盘。因此如果 MySQL 发生宕机,那么就有可能丢失一部分事务。
1:事务提交时,会将重做日志缓冲写入磁盘,并且立即刷新(fsync())。注意,因为操作系统的“延迟写”特性,此时的刷入只是写到了操作系统的缓冲区中,因此执行同步操作才能保证一定持久化到了硬盘中。
2:事务提交时,会将重做日志缓冲写入磁盘,但是不会立即进行刷新操作,因此只是写到了操作系统的缓冲区。此时若操作系统发生宕机而没有即使的同步,也可能会丢失一部分数据。
一般建议为2,安全性要求较高则使用默认值1。
innodb_read_io_threads
Innodb读的IO进程数。
innodb_write_io_threads
Innodb写的IO进程数。
innodb_file_per_table
Innodb的表使用独立的表空间,默认为OFF,也就是所有表都会建立在共享表空间中。建议为ON。
innodb_stats_on_metadata
使用 SHOW INDEX、SHOW TABLE STATUS、SHOW [FULL] TABLES时,会自动更新统计信息,或者对应的从 INFORMATION_SCHEMA.TABLES和INFORMATION_SCHEMA.STATISTICS 表中查询时,刷新innodb表的统计信息。默认为ON,建议设置为OFF。
4.系统配置和硬件
数据库是基于操作系统的,目前大多数MySQL都是安装在Linux系统之上,所以操作系统的一些参数配置也会影响到MySQL的性能。
网查参考:
一、内核相关(/etc/sysctl.conf)
#每一个端口最大的监听队列的长度
net.core.somaxconn = 65535
#当网络接受速率大于内核处理速率时,允许发送到队列中的包数目
net.core.netdev_max_backlog = 65535
#保持未连接的包最大数量,tcp队列的大小
net.ipv4.tcp_max_syn_backlog = 65535
#减少tcp的TIME_WAIT,加快资源回收
net.ipv4.tcp_max_tw_buckets = 8000
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
#tcp发送和接收缓冲区的大小
net.core.wmem_default = 87380
net.core.wmem_max = 16777216
net.core.rmem_default = 87380
net.core.rmem_max = 16777216
#加快回收tcp失效连接
net.ipv4.tcp_keepalive_time = 120 # 链接有效时间
net.ipv4.tcp_keepalive_intvl = 30 # tcp未获得相应时重发间隔
net.ipv4.tcp_keepalive_probes = 3 # 重发数量
二、资源限制(/etc/security/limit.conf)
#打开文件数
soft nofile 65535
hard nofile 65535
硬件:
硬件方面,就是一些性价比的取舍。对于CPU,MySQL很多操作都是使用单核来完成的,所以我们在选择CPU时可以尽量选择一些单核性能较强的CPU。对于磁盘,一般采用RAID1+0。
RAID0:也称条带,多个磁盘链接成一个硬盘使用。优点:IO性能好、成本低。缺点:容易损坏,一旦一个盘坏就会影响数据,损坏概率为磁盘倍数。
RAID1:也称镜像,由两块硬盘组成的阵列,其中一块正常使用,另外一块是专门做备份存放的。优点:不容易丢失数据,一个损坏还有可以使用另一个。缺点:速度慢,而且两块硬盘只能用一块硬盘的容量。