数据库-调优

Mysql原版文档 https://dev.mysql.com/doc

Mysql中文文档 https://www.docs4dev.com/docs/zh/mysql/5.7/reference/manual-info.html

数据结构可视化 https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

数据库调优分为[客户端层面,服务端层面]

 客户端层面
     1.SQL优化 
     2.调用代码的逻辑优化
     3.表优化
     4.读写分离

 服务端层面
     1.硬件优化
     2.数据库参数优化
        2.1 MySQL 日志设置优化
        2.2 MySQL 查询缓存优化
        2.3 MYSQL 网络连接优化
        2.4 MYSQL 存储引擎优化
     3.系统参数优化
        3.1 配置TCP/IP堆栈连接数
        3.2 配置文件句柄数
        3.3 配置软硬件限制
        3.4 配置sysctl调优TCP参数

下面会详细介绍各个优化点

客户端层面

1.SQL优化

  • 1.1 不要关联大表

  • 1.2.避免在索引列上使用计算

  • 1.4.避免使用前置百分号。

  • 1.5.避免在where子句中对字段进行函数操作,否则将导致全表扫描。

  • 1.6.索引并不是越多越好,降低了insert和update的效率。一个表的索引数最好不要超过6个。

  • 1.7.避免大事务操作,提高系统并发能力。

  • 1.8.主键条件进行查询;

  • 1.9.不要在主键上面进行更新操作,减少因为主键值的变化带来数据的移动。

  • 1.10.mysql innoDB的主键尽量有序

  • 1.10.主键占用空间越小越好

2.SQL调用逻辑优化

3.表优化

4.读写分离


服务端层面

1.硬件优化

1.固态硬盘
2.磁盘阵列(RAID)
3.内存 注:同时要将数据库参数的缓存池大小调大
4.CPU 
5.网络

2.数据库参数优化

2.1 MySQL 日志设置优化

一. 分离日志文件和数据文件,把它们放不同存储.尽量日志数据放在单独的存储上(通过API放在其他电脑), 提升磁盘IO的性能

二. 数据库服务器只打开系统错误日志,别的都关掉,尽可能减少IO损耗,

  • 2.1.1、错误日志(ErrorLog)

  • 2.1.2、二进制日志(Binlog) 所有环境需打开,MYSQL实现复制的基本条件

     mysql> show variables like '%binlog%';
        
     “binlog_cache_size":在对数据增删改的过程中容纳二进制日志SQL 语句的缓存大小。
        
     “max_binlog_cache_size”:和"binlog_cache_size"相对应,但是所代表的是binlog 能够使用的最大cache 内存大小
        
     “max_binlog_size”:Binlog 日志最大值,一般来说设置为512M 或者1G,但不能超过1G。
        
     “sync_binlog”:这个参数是对于MySQL 系统来说是至关重要的,他不仅影响到Binlog 对MySQL 所带来的性能损耗,而且还影响到MySQL 中数据的完整性。
         a)sync_binlog=0,当事务提交之后,MySQL 不做fsync 之类的磁盘同步指令刷新binlog_cache 中的信息到磁盘,而让Filesystem 自行决定什么时候来做同步,或者cache 满了之后才同步到磁盘。
         b)sync_binlog=n,当每进行n 次事务提交之后,MySQL 将进行一次fsync 之类的磁盘同步指令来将binlog_cache 中的数据强制写入磁盘。
         c),“sync_binlog”设置为0 和设置为1 的系统写入性能差距可能高达5 倍甚至更多。
    
  • 2.1.3、查询日志(Query Log) 生产系统中需关闭,查询日志会对IO带来较大负担

  • 2.1.4、慢查询日志(Slow Query Log) 所有环境需打开,超过特定数值(由我们自行设置)的SQL 语句。

     mysql> show variables like 'log_slow%';
     | log_slow_queries | ON |
     mysql> show variables like 'long_query%'
     | long_query_time | 1 |
        
     下面参数可以直接写到my.cnf配置文件中
     log-slow-query=on
     slow_query_log_file=/data/mysqld-slow.log
     log-slow-admin-statements
     log-queries-not-using-indexes
     long_query_time=1 --超过1秒的查询都会被记录下来
     log-short-format --短格式记录慢日志
    
  • 2.1.5、事务日志 tr_logs(3group)–>innodb

2.2 MySQL 查询缓存优化
mysql> show variables like '%query_cache%';

“have_query_cache”:该MySQL 是否支持Query Cache;

“query_cache_limit”:Query Cache 存放的单条Query 最大Result Set ,默认1M;

“query_cache_min_res_unit”:Query Cache 每个Result Set 存放的最小内存大小,默认4k;

“query_cache_size”:系统中用于Query Cache 内存的大小;

“query_cache_type”:系统是否打开了Query Cache 功能;

“query_cache_wlock_invalidate”:针对于MyISAM 存储引擎,设置当有WRITE LOCK

“sort_buffer_size“ 查询排序时缓冲区大小,只对order by和group by起作用,可增大此值为16M

如果我们要了解Query Cache 的使用情况,则可以通过Query Cache 相关的状态变量来获取,如通过如下命令:
mysql> show status like 'Qcache%';
  
“Qcache_free_blocks”:Query Cache 中目前还有多少剩余的blocks。如果该值显示较大,则说明Query Cache 中的内存碎片较多了,可能需要寻找合适的机会进行整理()。

“Qcache_free_memory”:Query Cache 中目前剩余的内存大小。通过这个参数我们可以较为准确的观察出当前系统中的Query Cache 内存大小是否足够,是需要增加还是过多了;

“Qcache_hits”:多少次命中。通过这个参数我们可以查看到Query Cache 的基本效果;

“Qcache_inserts”:多少次未命中然后插入。通过“Qcache_hits”和“Qcache_inserts”两个参数我们就可以算出Query Cache 的命中率了:Query Cache 命中率= Qcache_hits / ( Qcache_hits + Qcache_inserts );

“Qcache_lowmem_prunes”:多少条Query 因为内存不足而被清除出Query Cache。通过“Qcache_lowmem_prunes”和“Qcache_free_memory”相互结合,能够更清楚的了解到我们系统中Query Cache 的内存大小是否真的足够,是否非常频繁的出现因为内存不足而有Query 被换出

“Qcache_not_cached”:因为query_cache_type 的设置或者不能被cache 的Query 的数量;

“Qcache_queries_in_cache”:当前Query Cache 中cache 的Query 数量;

“Qcache_total_blocks”:当前Query Cache 中的block 数量;

Query Cache 的限制

1) 5.1.17 之前的版本不能Cache 绑定变量的Query,但是从5.1.17 版本开始,Query Cache 已经开始支持帮定变量的Query 了;
2) 所有子查询中的外部查询SQL 不能被Cache;
3) 在Procedure,Function 以及Trigger 中的Query 不能被Cache;
4) 包含其他很多每次执行可能得到不一样结果的函数的Query 不能被Cache。
2.3 MYSQL 网络连接优化

mysql> show variables like ‘thread%’; mysql> show status like ‘connections’; mysql> show status like ‘%thread%’;

max_conecctions:整个MySQL 允许的最大连接数;

max_user_connections:每个用户允许的最大连接数;

thread_stack:每个连接线程被创建的时候,MySQL 给他分配的内存大小。系统的默认值(192KB)

back_log:在MySQL 的连接请求等待队列中允许存放的最大连接请求数.

系统默认值为50,最大可以设置为65535。
当我们增大back_log 的设置的时候,同时还需要注意OS 级别对网络监听队列的限制,
因为如果OS 的网络监听设置小于MySQL 的back_log 设置的时候,
我们加大“back_log”设置是没有意义的。

thread_cache_size:Thread Cache 池中应该存放的连接线程数。

 当系统最初启动的时候,并不会马上就创建thread_cache_size 所设置数目的连接线程存放在Thread Cache 池中,
 而是随着连接线程的创建及使用,慢慢的将用完的连接线程存入其中。
 当存放的连接线程达到thread_cache_size 值之后,MySQL 就不会再续保存用完的连接线程了。
2.4 MYSQL 存储引擎优化

1、MyI SAM存储引擎优化(查询缓存+索引缓存)

2、Innodb存储引擎优化(查询缓存+innodb_buffer_pool(索引/修改数据))

物理块-->表-->索引(硬盘)-->索引缓存(buffer)-->查询缓存(cache)-->查询

1、MyI SAM存储引擎优化(所有写操作都是直接操作物理磁盘,所以只能优化它的查询功能)

1)MyISAM 索引缓存相关的几个系统参数和状态参数:

◆ key_buffer_size,索引缓存大小;

这个参数用来设置整个MySQL 中的常规Key Cache 大小。一般来说,如果我们的MySQL 是运行在32 位平台上,此值建议不要超过2GB 大小。如果是运行在64 位平台纸上则不用考虑此限制,但也最好不要超过4GB。

◆ key_buffer_block_size,索引缓存中的Cache Block Size;

在前面我们已经介绍了,在Key Cache 中的所有数据都是以Cache Block 的形式存在,而key_buffer_block_size 就是设置每个Cache Block 的大小,实际上也同时限定了我们将“.MYI”文件中的Index Block 被读入时候的File Block 的大小。

2、Innodb存储引擎优化

1)Innodb缓存相关优化

2)事务优化

3)数据存储优化

innodb_buffer_pool_size 参数用来设置Innodb 最主要的Buffer(Innodb_Buffer_Pool)的大小,也就是缓存用户表及索引数据的最主要缓存空间,对Innodb 整体性能影响也最大。官方建议将Innodb 的Buffer Pool 设置为整个系统物理内存的50% ~ 80% 之间。

mysql> show status like 'Innodb_buffer_pool_%';

| Innodb_buffer_pool_pages_data | 70 |

| Innodb_buffer_pool_pages_dirty | 0 |

| Innodb_buffer_pool_pages_flushed | 0 |

| Innodb_buffer_pool_pages_free | 1978|

| Innodb_buffer_pool_pages_latched | 0 |

| Innodb_buffer_pool_pages_misc | 0 |

| Innodb_buffer_pool_pages_total | 2048 |

| Innodb_buffer_pool_read_ahead_rnd | 1 |

| Innodb_buffer_pool_read_ahead_seq | 0 |

| Innodb_buffer_pool_read_requests | 329 |

| Innodb_buffer_pool_reads | 19 |

| Innodb_buffer_pool_wait_free | 0 |

| Innodb_buffer_pool_write_requests | 0 |

从上面的值我们可以看出总共2048 pages, 还有1978 是Free 状态的仅仅只有70 个page 有数据,read 请求329 次, 其中有19 次所请求的数据在buffer pool 中没有, 也就是说有19 次是通过读取物理磁盘来读取数据的, 所以很容易也就得出了Innodb Buffer Pool 的Read 命中率大概在为:(329 - 19)/ 329 * 100% = 94.22%。

innodb_additional_mem_pool_size 所设置的是用于存放Innodb 的字典信息和其他一些内部结构所需要的内存空间。 所以我们的Innodb 表越多,所需要的空间自然也就越大, 系统默认值仅有1MB。当然,如果Innodb 实际运行过程中出现了实际需要的内存比设置值更大的时候, Innodb 也会继续通过OS来申请内存空间, 一个常规的几百个Innodb 表的MySQL, 如果不是每个表都是上百个字段的话,20MB 内存已经足够了。

◆ innodb_flush_log_at_trx_commit = 0,Innodb 中的Log Thread 每隔1 秒钟会将log buffer中的数据写入到文件,同时还会通知文件系统进行文件同步的flush 操作,保证数据确实已经写入到磁盘上面的物理文件。但是,每次事务的结束(commit 或者是rollback)并不会触发Log Thread 将log buffer 中的数据写入文件。所以,当设置为0 的时候,当MySQL Crash 和OS Crash 或者主机断电之后,最极端的情况是丢失1 秒时间的数据变更。(fsync)

◆ innodb_flush_log_at_trx_commit = 1,这也是Innodb 的默认设置。我们每次事务的结束都会触发Log Thread 将log buffer 中的数据写入文件并通知文件系统同步文件。这个设置是最安全的设置,能够保证不论是MySQL Crash 还是OS Crash 或者是主机断电都不会丢失任何已经提交的数据。(fsync)

◆ innodb_flush_log_at_trx_commit = 2,当我们设置为2 的时候,Log Thread 会在我们每次事务结束的时候将数据写入事务日志,但是这里的写入仅仅是调用了文件系统的文件写入操作。而我们的文件系统都是有缓存机制的,所以Log Thread 的这个写入并不能保证内容真的已经写入到物理磁盘上面完成持久化的动作。文件系统什么时候会将缓存中的这个数据同步到物理磁盘文件Log Thread 就完全不知道了。所以,当设置为2 的时候,MySQL Crash 并不会造成数据的丢失,但是OS Crash 或者是主机断电后可能丢失的数据量就完全控制在文件系统上了。(async)

分散IO 提升磁盘响应:

建议将数据文件和事务日志文件分别存放于不同的物理磁盘上面以降低磁盘的相互争用,提高整体IO 性能。

可以通过以下两个参数指定:

innodb_log_group_home_dir 参数来指定Innodb 日志存放位置,同时再通过设置数据文件位置

innodb_data_home_dir 参数来告诉Innodb 我们希望将数据文件存放在哪里。

innodb_autoextend_increment 参数让我们可以自行控制表空间文件每次增加的大小。

skip-locking--忽略外部文件锁定(如VFS层的锁定)

skip-networking--启动mysql时不启动网络模块,只允许通过socket连接。

查询binlog事件 :

列出所有binlog文件
mysql> show binary logs;

查看当前正在写入的binlog文件
mysql> show master status;

只查看第一个binlog文件的内容
mysql> show binlog events limit 100,10;

查看指定binlog文件的内容
mysql> show binlog events in 'mysql-bin.000002' limit 100,10;

查询状态 :

show status like ‘%Aborted_clients%’

Aborted_clients 由于客户没有正确关闭连接已经死掉,已经放弃的连接数量。
Aborted_connects 尝试已经失败的MySQL服务器的连接的次数。
Connections 试图连接MySQL服务器的次数。
Created_tmp_tables 当执行语句时,已经被创造了的隐含临时表的数量。
Delayed_insert_threads 正在使用的延迟插入处理器线程的数量。
Delayed_writes 用INSERT DELAYED写入的行数。
Delayed_errors 用INSERT DELAYED写入的发生某些错误(可能重复键值)的行数。
Flush_commands 执行FLUSH命令的次数。
Handler_delete 请求从一张表中删除行的次数。
Handler_read_first 请求读入表中第一行的次数。
Handler_read_key 请求数字基于键读行。
Handler_read_next 请求读入基于一个键的一行的次数。
Handler_read_rnd 请求读入基于一个固定位置的一行的次数。
Handler_update 请求更新表中一行的次数。
Handler_write 请求向表中插入一行的次数。
Key_blocks_used 用于关键字缓存的块的数量。
Key_read_requests 请求从缓存读入一个键值的次数。
Key_reads 从磁盘物理读入一个键值的次数。
Key_write_requests 请求将一个关键字块写入缓存次数。
Key_writes 将一个键值块物理写入磁盘的次数。
Max_used_connections 同时使用的连接的最大数目。
Not_flushed_key_blocks 在键缓存中已经改变但是还没被清空到磁盘上的键块。
Not_flushed_delayed_rows 在INSERT DELAY队列中等待写入的行的数量。
Open_tables 打开表的数量。
Open_files 打开文件的数量。
Open_streams 打开流的数量(主要用于日志记载)
Opened_tables 已经打开的表的数量。
Questions 发往服务器的查询的数量。
Slow_queries 要花超过long_query_time时间的查询数量。
Threads_connected 当前打开的连接的数量。
Threads_running 不在睡眠的线程数量。
Uptime 服务器工作了多少秒。

示例,set global 可以写到配置文件里

set global query_cache_type=OFF;
set global query_cache_size=0;
set global innodb_flush_log_at_trx_commit=0;
set global innodb_io_capacity=100;

innodb_buffer_pool_size=2g
#innodb_log_file_size=128m
innodb_flush_method=O_DIRECT
innodb_buffer_pool_instances=8

3.系统参数优化

3.1 配置TCP/IP堆栈连接数
    vim /etc/sysctl.conf
    
    net.ipv4.ip_local_port_range = 32768 61000 
3.2 配置文件句柄数,需要重启mysql
    vim /etc/security/limits.conf
    
    mysql soft nofile 65535
    mysql hard nofile 65535
    mysql soft nproc 65535
    mysql hard nproc 65535
3.3 配置软硬件限制.

-H 设置硬件资源限制. -S 设置软件资源限制, -n设置内核可以同时打开的文件描述符的最大值【每个进程可以打开的文件数目】【也包含打开的SOCKET数量】

    ulimit -HSn 65535 
3.4 配置sysctl调优TCP参数.
    vim /etc/sysctl.conf

    net.ipv4.tcp_fin_timeout = 30 //TIME_WAIT超时时间,默认是60s
    net.ipv4.tcp_tw_reuse = 1 //1表示开启复用,允许TIME_WAIT socket重新用于新的TCP连接,0表示关闭
    net.ipv4.tcp_tw_recycle = 1  //1表示开启TIME_WAIT socket快速回收,0表示关闭
    net.ipv4.tcp_max_tw_buckets = 4096  //系统保持TIME_WAIT socket最大数量,如果超出这个数,系统将随机清除一些TIME_WAIT并打印警告信息
    net.ipv4.tcp_max_syn_backlog = 4096 //进入SYN队列最大长度,加大队列长度可容纳更多的等待连接

参考

bplug树

innodb辅助索引回表

覆盖索引非回表.png

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

备案信息公示
京ICP备18003381号
京ICP备18003381号-1