印象深刻的是刚进入一家公司,给了一个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引擎;
。。。。。