MySQL实践——MySQL数据库性能调优全攻略

数据库调优从以下几个方面进行调优

  1. 数据库配置
  2. SQL优化
  3. 硬件设置
  4. 文件系统
  5. 操作系统

1. 数据库配置

  • InnoDB存储引擎与PostgreSQL非常不同
  • InnoDB的缓冲池用来管理所有数据库对象
  • 写文件操作通过O_DIRECT选项来避免两次缓存
  • InnoDB缓冲池越大性能越好
    1. 通常是系统内存60%~80%
  • PostgreSQL缓冲池仅用来管理最热的数据
  • 强烈的依赖操作系统的缓存来处理数据
  • PostgreSQL缓存越大性能越差
    1. 通常是系统内存通常25%~30%
 #配置文件
innodb_buffer_pool_size = 100G
innodb_buffer_pool_instances = 16
innodb_page_size = 4096
innodb_flush_method = O_DIRECT
#在线设置buffer pool大小
# MySQL 5.7 online resize buffer pool
mysql> set global innodb_disable_resize_buffer_pool_debug=off;
Query OK, 0 rows affected (0.00 sec)
mysql> set global innodb_buffer_pool_size=256*1024*1024;
Query OK, 0 rows affected (0.00 sec)
  • FUZZY CHECKPOINT
    1. 刷新部分脏页,对系统影响较小
    2. 5.6:独立的刷新线程
    3. 5.7:并行刷新线程
    4. innodb_io_capacity
  • SHARP CHECKPOINT
    1. 刷新全部的脏页,系统hang住
    2. innodb_fast_shutdown
  • Neighbor Page Flush
    1. innodb_flush_neighbors
innodb_io_capacity = 1000/4000/8000
innodb_page_cleaners = 1 / 4
innodb_fast_shutdown = 0/1
innodb_flush_neighbors = 0/1/2
  • 重做日志
    1. 记录页操作的日志
    2. 与二进制日志完全不同
    3. 循环覆盖写
    4. 默认没有类似PG或者Oracle的归档
  • 重做日志大小限制
    1. before 5.6: max 4G
    2. start from 5.6: max 512G
innodb_log_file_size = 1900M / 4G
innodb_log_buffer_size = 8M / 32M
innodb_log_files_in_group = 2/3
innodb_log_group_home_dir = /redolog/

在这里插入图片描述

  • undo段
    1. 实现回滚
    2. 实现MVCC功能
    3. PostgreSQL没有undo段!!!
  • undo段数量
    1. before MySQL 5.5: 1024
    2. start from MySQL 5.5: 128*1024
  • undo回收
    1. purge
innodb_undo_directory = /undolog/
innodb_undo_logs = 128
innodb_undo_tablespaces = 3

innodb_undo_log_truncate = 1
innodb_max_undo_log_size = 1G
innodb_purge_rseg_truncate_frequency = 128

innodb_purge_batch_size = 300
innodb_purge_threads = 4/8

在这里插入图片描述

  • 线程池
    1. 保障高并发下的性能平稳
    2. MariaDB线程池没有优先级队列
    3. 推荐MySQL/InnoSQL/Percona线程池
    4. 推荐默认开启用线程池
thread_handling = pool‐of‐threads 
thread_pool_size = 32 # CPU
thread_pool_oversubscribe = 3
extra_port = 3333 #额外的端口

在这里插入图片描述
在这里插入图片描述

  • MySQL日志配置
    1. binary log
    2. error log
    3. slow log
    4. general log(通常不推荐)
      events_statements_current
      events_statements_history(_long)
# 二进制文件
log‐bin = /binlog/mysqld‐bin
log‐expire‐day = 7
syslog
syslog_tag = stock #mysqld_stock
log‐slow‐queries
long_query_time = 2
log‐queries‐not‐using‐indexes
log‐slow‐admin‐statements
min‐examined‐row‐limit
log_throttle_queries_not_using_indexes
log_slow_slave_statements
[mysqld]
performance_schema
mysql> select * from setup_consumers\G
************************ 1. row ***********************
NAME: events_stages_current
ENABLED: NO
…………

2. SQL优化

  • 子查询
    1. before 5.6:
      lazy: rewrite to exists
      poor performance
    2. from 5.6:(MariaDB 5.3)
      semi‐join
tbs@localhost:[(none)]>show variables like 'optimizer_switch'\G                                                                                                              
*************************** 1. row ***************************
Variable_name: optimizer_switch
        Value: index_merge=on,index_merge_union=on,index_merge_sort_union=on,
          index_merge_intersection=on,engine_condition_pushdown=on,
         index_condition_pushdown=on,mrr=on,mrr_cost_based=on,
        block_nested_loop=on,batched_key_access=off,materialization=on,
         semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,
        subquery_materialization_cost_based=on,use_index_extensions=on,
         condition_fanout_filter=on,derived_merge=on,prefer_ordering_index=on
1 row in set (0.00 sec)
SELECT o_custkey FROM orders
WHERE o_custkey IN 
( SELECT c_custkey FROM customer
WHERE c_acctbal <500 );
select `dbt3`.`orders`.`o_custkey` AS `o_custkey` from 
`dbt3`.`customer` join `dbt3`.`orders` where 
((`dbt3`.`orders`.`o_custkey` = `dbt3`.`customer`.`c_custkey`) 
and (`dbt3`.`customer`.`c_acctbal` <(500)))

在这里插入图片描述
在这里插入图片描述

SELECT * FROM part
WHERE p_partkey IN
( SELECT l_partkey FROM lineitem
WHERE l_shipdate BETWEEN '1997‐01‐01' AND '1997‐02‐01' )
ORDER BY p_retailprice DESC LIMIT 10;

在这里插入图片描述

2.1 JOIN语法

-- 语法1
SELECTFROM 
a,b
WHERE a.x = b.x

-- 语法2
SELECTFROM a
INNER JOIN b
on a.x = b.x

-- 语法3
SELECTFROM a
JOIN b
on a.x = b.x
Q:上述这些语法是否有区别?

A:没有任何区别

Q:哪个性能更好?

A:没有任何区别
A:好吧,如果要认真算的话,那么3最好,因为字节数最少

Q:那为什么需要不同的语法?

A:ANSI SQL 89、ANSI SQL 92语法标准
A:ANSI 92标准开始支持OUTER JOIN
A:INNER JOIN可以省略INNER关键字

2.2 JOIN算法

  • nested_loop join
    1. simple nested‐loop join
    2. index nested‐loop join
    3. block nested‐loop join
  • classic hash join
    1. Only support in MariaDB
  • bached key access join
    1. from MySQL 5.6
    2. from MariaDB 5.5
  • simple nested_loop join
For each row r in R do 
For each row s in S do 
If r and s satisfy the join condition 
Then output the tuple <r,s>

在这里插入图片描述

在这里插入图片描述

  • index nested_loop join
For each row r in R do 
lookup r in S index 
if found s == r
Then output the tuple <r,s>

扫描成本: O(Rn) 优化器倾向于使用小表做驱动表
在这里插入图片描述

  • block nested‐loop join
    1. 优化simple nested‐loop join
    2. 减少内部表的扫描次数
 For each tuple r in R do 
store used columns as p from R in join buffer
For each tuple s in S do 
If p and s satisfy the join condition 
Then output the tuple <p,s>

系统变量join_buffer_size决定了Join Buffer的大小,Join Buffer可被用于联接是ALL,index,range的类型Join Buffer只存储需要进行查询操作的相关列数据,而不是整行的记录扫描成本呢?
在这里插入图片描述

  • classic hash join
    1. based on block nested loop join
      inner table may scan many times
    2. not grace hash join
      inner table scan only once
For each tuple r in R do 
store used columns as p from R in join buffer
build hash table according join buffer
for each tuple s in S do
probe hash table
if  find
Then output the tuple <p,s>
SET join_cache_level=4+;
SET optimizer_switch='join_cache_hashed=on';

在这里插入图片描述
减少外表扫描次数
减少内表比较次数
扫描成本?

SELECT MAX(l_extendedprice) FROM orders, lineitem
WHERE
o_orderdate BETWEEN '1995‐01‐01' AND '1995‐01‐31' 
AND l_orderkey=o_orderkey;

MySQL 5.5 125.3sec
在这里插入图片描述
MariaDB 5.3 23.104sec ~5x
在这里插入图片描述

  • batched key access join
    1. not enabled by default
    2. optimize random I/O
 For each tuple r in R do 
store used columns as p from R in join buffer
For each tuple s in S do 
If p and s satisfy the join condition 
use mrr inter face to sort row Id
Then output the tuple <p,s>
mysql> SET optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';

在这里插入图片描述

2.3 JOIN经典问题

2.3.1 行号问题

在这里插入图片描述

2.3.2 子查询
SELECT emp_no,dept_no,
(SELECT COUNT(1) FROM dept_emp t2  
WHERE t1.emp_no<=t2.emp_no) AS row_num
FROM dept_emp t1;

在这里插入图片描述

2.3.3 CROSS JOIN
SELECT emp_no,dept_no,@a:=@a+1 AS row_num
FROM dept_emp,(SELECT @a:=0 ) t;

在这里插入图片描述

2.3.4 实现类似Oracle的rank()函数
SET @prev_value = NULL;
SET @rank_count = 0;
SELECT id, rank_column, CASE
WHEN @prev_value = rank_column THEN @rank_count
WHEN @prev_value := rank_column THEN @rank_count := @rank_count + 1
END AS rank
FROM rank_table
ORDER BY rank_column
+‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+
| id   | rank_column | rank |
+‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+
|    1 |          10           |    1   |
|    2 |          20           |    2   |
|    3 |          30           |    3   |
|    4 |          30           |    3   |
|    5 |          30           |    3   |
|    6 |          40           |    4   |
|    7 |          50           |    5   |
|    8 |          50           |    5   |
|    9 |          50           |    5   |
+‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐ ‐‐+‐‐‐‐‐‐+

3. 软硬件设置

3.1 内存

3.1.1 NUMA
  1. Non‐Uniform Memory Access
  2. 非一致存储访问结构
    在这里插入图片描述
3.1.2 NUMA的内存分配策略有四种:
  1. default:总是在本地节点分配
  2. bind:强制分配到指定节点上
  3. interleave:在所有节点或者指定的节点上交织分配
  4. preferred:在指定节点上分配,失败则在其他节点上分配
  • 单实例MySQL
    1. 考虑关闭NUMA特性
      BIOS中关闭
      内存启动关闭numa=off
      MySQL启动时关闭
  • 多实例MySQL
    1. 通过NUMA绑定到指定CPU
kernel /vmlinuz‐2.6.32‐220.el6.x86_64 ro
root=/dev/mapper/VolGroup‐root rd_NO_LUKS
LANG=en_US.UTF‐8 rd_LVM_LV=VolGroup/root rd_NO_MD
quiet SYSFONT=latarcyrheb‐sun16 rhgb crashkernel=auto 
rd_LVM_LV=VolGroup/swap rhgb crashkernel=auto quiet 
KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM numa=off 
numactl ‐‐interleave=all  mysqld &

numactl –hardware
numactl –cpubind=0 –localalloc
echo "vm.swappiness = 0" >>/etc/sysctl.conf

3.2 网卡

3.2.1 网卡软中断

在这里插入图片描述

  • 解决方案
    1. 启用网卡多队列
      set_irq_affinity.sh
      service irqbalance stop
#./set_irq_affinity.sh 0 eth0
#./set_irq_affinity.sh 8 eth1

在这里插入图片描述

3.3 RAID卡

在这里插入图片描述

3.3.1 BBU
  1. Battery Backup Unit
  2. 非低端RAID卡都带BBU
  3. 需要电池保证写入的可靠性
  4. 电池有充放电时间
3.3.2 RAID卡缓存
  1. Write Backup
  2. Write Through
  3. 写缓存并非默认开启

查看电量百分比

[root@test_raid ~]# megacli ‐AdpBbuCmd ‐GetBbuStatus ‐aALL |grep "Relative State of Charge"
Relative State of Charge: 100 %

查看充电状态

[root@test_raid ~]# megacli ‐AdpBbuCmd ‐GetBbuStatus ‐aALL |grep "Charger Status"
Charger Status: Complete

查看缓存策略

[root@test_raid ~]# megacli ‐LDGetProp ‐Cache ‐LALL ‐a0
Adapter 0‐VD 0(target id: 0): Cache Policy:WriteBack, ReadAdaptive, Direct, No Write Cache if bad BBU

缓存策略

WT    (Write through)  
WB    (Write back)  
NORA  (No read ahead)  
RA    (Read ahead)  
ADRA  (Adaptive read ahead)  
Cached  
Direct  
‐RW|RO|Blocked|RemoveBlocked | WT|WB|ForcedWB [‐Immediate] 
|RA|NORA | DsblP | Cached|Direct | ‐EnDskCache|DisDskCache | 
CachedBadBBU|NoCachedBadBBU
‐Lx|‐L0,1,2|‐Lall ‐aN|‐a0,1,2|‐aALL
[root@test_raid ~]# megacli ‐LDSetProp WT ‐L0 ‐a0  
Set Write Policy to WriteThrough on Adapter 0, VD 0 (target id: 0) success 

3.4 SSD

在这里插入图片描述
在这里插入图片描述

3.4.1 SSD与传统磁盘差别
SSD优点
  1. 纯电设备
  2. 由Flash Memory组成
  3. 没有读写磁头
  4. IOPS高 • 50000+ IOPS
  5. 读写速度非对称
性能指标
  • RPM (rotations per minute)
  1. 5400
  2. 7200
  3. 10000
  4. 15000
  • SATA(串口硬盘)
    1. 120 ~ 150 IOPS
  • SAS
    1. 150 ~ 200 IOPS
性能下降

在这里插入图片描述

莫名的性能波动

在这里插入图片描述

SSD与数据库优化
  • 磁盘调度算法设置为:deadline或者noop
  • InnoDB存储引擎参数设置
    1. innodb_flush_neighbors=0
    2. innodb_log_file_size=4G

在这里插入图片描述
结论:

  • 性能更平稳
  • 可以有大约15%的性能提升
SSD选择

• PCIE or SATA/SAS
• SATA/SAS益于安装与升级
• SATA/SAS与PCIE的性能差距逐渐缩小
• PCIE的性能很少有应用可以完全使用
• 优先选择SATA/SAS接口的SSD

SSD品牌推荐

• Intel
• FusionIO
• 宝存

选购时注意“寿命”指标

• Intel 3500:275T
• Intel 3700:每天全量写10次,保证5年

4. 文件系统与操作系统

4.1 文件系统

  • 推荐xfs/ext4
  • noatime
  • nobarrier

4.2 操作系统

  • 推荐Linux操作系统
  • 关闭swap
  • 磁盘调度算法
mount ‐o noatime,nobarrier /dev/sdb1 /data

在这里插入图片描述

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MySQL性能调优与架构设计》是一本介绍MySQL数据库性能优化和架构设计的指南。MySQL是一种常用的开源关系型数据库管理系统,广泛应用于互联网、企业和各种应用程序中。但是,在实际应用中,由于数据量的增加和访问负载的变化等原因,MySQL的性能会受到影响,为此需要进行相应的调优和架构设计。 该PDF文件主要介绍了如何通过调优和优化来提高MySQL的性能。首先,它详细介绍了MySQL的架构和基本原理,包括MySQL的体系结构、并发控制、索引优化等。然后,它介绍了如何通过优化查询、优化索引、优化表结构、对数据库进行分库分表等来提高MySQL的性能。此外,还介绍了如何选择合适的硬件和操作系统、配置参数等,以提高MySQL的性能。 此外,该PDF还介绍了MySQL的高可用性架构设计,包括主从复制、主从链式复制、多主复制等。这些架构设计可以提高MySQL的可用性和容错能力,确保数据的安全性和持久性。 总之,MySQL性能调优与架构设计是一个重要的课题,涉及到数据库的整体性能和稳定性。对于那些需要处理大量数据和高并发的应用程序来说,MySQL性能调优和架构设计是至关重要的,可以提高系统的响应速度和可靠性,保证系统的稳定运行。这本PDF文件详细介绍了MySQL性能调优和架构设计的方法和技巧,对开发人员和系统管理员都是很有参考价值的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三月微风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值