Mysql优化

印象深刻的是刚进入一家公司,给了一个excel,里面的内容是线上慢查询的sql。因为sql太长过于复杂,然后就开启了顺着sql梳理业务的模式。

这里只是单纯的优化sql,但出现系统慢的情况,IO优化应该按照以下思路进行。

优化思路

每个人理解的性能优化都不一样,对于数据库的性能优化,我理解的就是响应时间更短。

硬件层面

  • cpu。使用更快CPU,甚至更多的CPU,特别是cpu一级二级缓存大小
  • 内存读写速度
  • 硬盘读写速度
  • 网络IO速度

软件层面

  • 操作系统。unix更快更安全更稳定。
  • 文件系统。ext4顺序读写更好,随机若些。NTFS对于频繁修改的数据容易产生磁盘碎片。
  • 硬盘调度算法
  • 虚拟内存设置

以上偏硬件的优化内容,这些和基础运维和费用成本有直接关系。


mysql服务器配置优化

配置项 作用范围 功能 建议
query_cache_size 全局 查询缓存 建议不使用
sort_buffer _size 每个线程可以单独设置 排序缓冲池大小 默认
join_buffer_size 每个线程可以单独设置 如果一个查询中关联多张表,可以为每个关联分配一个关联缓冲 (join buffer) ,所以每个查询可能有多个关联缓冲。
table_cache_size 全局 缓存表的信息 默认
thread_cache_size 全局 线程池大小 默认
query_cache_size 全局 查询缓存带下,mysql会在启动的时候分配该空间,后面修改也会重新分配并初始化大小。 不建议使用
read_buffer_size 全局 每个线程对表进行顺序扫描时分配的缓冲区大小。太小,就会导致顺序频繁的磁盘IO。太大,浪费内存 默认。尽量避免全表扫描
read_rnd_buffer_size 全局 每个线程进行随机读取的时候分配的缓冲区大小。优缺点同上 同上
sort_buffer_size 全局 每个线程执行sql需要排序操作时分配的缓冲区大小。同上 同上
innodb_log_file_size 全局 redolog日志文件大小 ,设置过小会导致频繁的刷盘,性能低,如果出现故障的时候,还可能会出现不完整事务日志记录;过大,崩溃恢复慢,并且会占用更大的文件 根据系统负载、性能,业务需求调整
innodb_1og_fles_in_group 全局 设置innodb_log_file的个数的 系统默认即可
Innodb_os_1og_written show innodb status查看 查看innodb对日志文件写出了多少数据 默认

innnodb 缓冲池

show innodb status 可以查看脏页的刷新量:Inodbbuffer_pool_pages_dirty

缓冲池过大,很多数据在内存里面,查询起来是快一些。当需要刷新到磁盘到时候会很慢,预热和关闭大时间都会变长。

缓冲池过小,刷盘都时间变快,但是内存里的数据少了,查询变慢。

可以监控Inodbbuffer_pool_pages_dirty状态变量或者使用innotop 来监控SHOW INNODB STATUS 来观察脏页的刷新量。 更小的innodb_max dirty_pages_pct变量值并不保证InnoDB将在缓冲池中保持更少的脏页。它只是控制InnoDB是否可以"偷懒(Lazy)" 的阈值。InnoDB默认通过一个 后台线程来刷新脏页,并且会合并写人,更高效地顺序写出到磁盘。这个行为之所以被称为 "偷懒 (Lazy)",是因为它使得InnoDB延迟了缓冲池中刷写脏页的操作,直到一些其他数据必须使用空间时才刷写 。当脏页的百分比超过这个阈值 ,InnoDB 将快速地刷写脏页,尝试让脏页的数量更低。当事务日志没有足够的空间剩余时,InnoDB 也将进人"激烈刷写(FuriousFlushing)"模式,这就是大日志可以提升性能的一个原因。

InnoDB怎样刷新日志缓冲。当InnoDB 把日志缓冲刷新到磁盘日志文件时,先会使用 一 个 Mutex 锁住缓冲区,刷新到所需要的位置,然后移动剩下的条目到缓冲区的前面。当 Mutex释放时,可能有超过一个事务已经准备好刷新其日志记录。InnoDB有一个GroupC ommit功能,可以在一个I/0操作内提交多个事务。

日志缓冲必须呗刷新到磁盘,这样才能保证提交的事务被完全持久化。如果和持久化相比,更在乎性能,那么就可以调整 innodb_flush_1og_at_trxcommit 来控制redolog缓冲区的刷新频率。
innodb_flush_1og_at_trxcommit可配置选项

配置项 内容
0 每秒钟把缓冲区中的数据刷新到relodlog中,但是事务提交的时候数据不会真正的持久化
1 每次事务提交的时候都刷新缓冲区到redolog文件中,并且事务提交都刷新到磁盘。这样能保证任何已提交的事务不会丢失。除非磁盘或者操作系统是"伪刷新" 。这个级别也是innodb默认设置
2 每次事务提交时,把日志缓冲写到日志文件,但是没有持久化到存储中;这个设置在断电或者数据库崩溃时会丢失数

双写缓冲

为了防止把缓冲区数据写入磁盘的时候系统发生故障、断电等因素,导致数据不完整的情况,所以有了双写缓冲。

实际是指在写入磁盘之前,先把这些内存中的数据顺序写入到双写缓冲(磁盘中顺序文件),写入成功以后才会写入数据磁盘。

在数据库启动和恢复过程中,InnoDB 会检查数据文件中的数据页是否完整。如果发现某一个数据页有问题,就会从双写缓冲中读取对应的完整的数据副本。这样就可以保证数据的完整性。

是要两次写入磁盘,但这个双写缓冲是顺序写入,速度还可以。

innodb并发控制

innodb_thread_concurrency 可以控制一次性能有多少个线程进入到内核,0表示不限制。

因为大多数是磁盘IO操作,所以建议设置值=CPU * 磁盘数量 * 2

concurrent_insert 可以控制myisam并发插入的线程数。

选项 作用
0 不允许并发插入,所有插入都会加表锁
1 如果表中没有空洞,就允许并发插入
2 强制插入表尾,时间长了会有碎片

优化大数据

blob和text类型的数据,尽量不用和其他字段在一起使用。如果一定要使用,必须做到和其他表隔离。

排序优化

当排序的数据行长度不超过max_length_for_sort_data时,会使用单路排序;

如果排序数据的长度超过max_length_for_sort_data时,会使用多路排序;

所以,配置该字段会影响排序算法选择。

其他参数

temp_table_size 控制临时表大小;
max_connections 最大连接数;
thread_cache_size 内存池大小;
innodb_io_capacity 每秒多少个IO操作;
innodb_buffer_pool_size inno_db_file_size 非常重要,如果你不了解,可以自己学习一下mysql的innodb引擎;

。。。。。