• 历时七天,史上最强MySQL优化总结,从此优化So Easy!


    一、概述

    1. 为什么要优化

    • 一个应用吞吐量瓶颈往往出现在数据库的处理速度上
    • 随着应用程序的使用,数据库数据逐渐增多,数据库处理压力逐渐增大
    • 关系型数据库的数据是存放在磁盘上的,读写速度较慢(与内存中的数据相比)

    2. 如何优化

    • 表、字段的设计阶段,考量更优的存储和计算
    • 数据库自身提供的优化功能,如索引
    • 横向扩展,主从复制、读写分离、负载均衡和高可用
    • 典型SQL语句优化(收效甚微)

    二、字段设计

    1. 典型方案

    ①. 对精度有要求

    • decimal
    • 小数转整数

    ②. 尽量使用整数表示字符串(IP)

    • inet_ aton("ip' )
    • inet_ ntoa(num)

    ③. 尽可能使用not null

    • nuI数值的计算逻辑比较复杂

    ④. 定长和非定长的选择

    • 较长的数字数据可以使用decimal
    • char为定长(超过长度的内容将被截掉), varchar为非定长,text对内容 长度的保存额外保存而varchar对长度的保存占用数据空间

    ⑤. 字段数不要过多字段注释是必要的、字段命名见名思意、可以预留字段以备扩展

    2. 范式

    ①. 第一范式:段原子性(关系型数据库有列的念,默认就符合了)

    ②. 第二范式:消除对主键的部分依赖(因为主键可能不止一个);使用一 个与业务无关的字段作为主键

    ③. 第三范式:消除对主键的传递依赖;高内聚, 如商品表可分为商品简略信息表和商品详情表两张表

    三、存储引擎的选择(MyISAM和Innodb)

    1. 功能差异

    Innodb支持事务、 行级锁定、外健

    2. 存储差异

    ①. 存储方式:MyISAM的数据和索弓 |是分开存储的(.MYI.MYD) , 而Innodb是存在一起的(.frm)

    ②. 表可移动性:可以通过移动表对应的MYI和MYD能够实现表的移动,而Innodb还有 额外的关联文件

    ③. 碎片空间:MyISAM删除数据时会产生碎片空间(占用表文件空间),需要定期通过optimizetable table-name手动优化。而Innodb不会。

    ④. 有序存储:Innodb插入数据时按照主键有序来插入。因此表中数据默认按主键有序(耗费写入时间,因为需要在b+ tree中查找插入点,但查找效率高)

    3. 选择差异

    ①. 读多写少用MyISAM:新闻、博客网站

    ②. 读多写也多用Innodb:

    • 支持事务/外键,保证数据-致性、完整性
    • 并发能力强(行锁)

    四、索引

    1. 什么是索引

    从数据中提取的具有标识性的关键字,并且有到对应数据的映射关系

    2. 类型

    ①. 主键索引primary key:要求关键字唯一且不为null

    ②. 普通索引key:符合索引仅按照第一字段有序

    ③. 唯一索引unique key:要求关键字唯一

    ④. 全文索引fulltext key (不支持中文)

    3. 索引管理语法

    ①. 查看索引

    • show create table student
    • desc student

    ②. 建立索引

    • 创建时指定,如first. name varchar(1 6),last name(1 6) , key name(first_ name,last_ name)
    • 更改表结构:alter table student add key/unique key/primary key/ultext key key. name(first_ name,last_ name)

    ③. 删除索引

    • alter table student drop key key_ name
    • 如果删除的是主键索引,并且主键自增长,则需要alter modify先取消自增长再删除

    4. 执行计划explain

    分析SQL执行是否用到了索引,用到了什么索引

    5. 索引使用的场景

    • where:如果查找字段都建立了索引,则会索引覆盖
    • order by:如果排序字段建立了索引,而索引又是有序排列的,直接根据索引拿对应数据即可,与读取查询出来的所有数据再排序相比效率很高
    • join:如果join on的条件字段建立了索引,查找会变得高效
    • 索引覆盖:直接对索引做查找,而不去读取数据

    6. 语法细节

    即使建立了索引,有些场景也不一定使用

    • where id+1 = ?建议写成where id = ?-1,即保证索弓|字段的独立出现
    • like语句不要在关键字前模糊匹配,即"%keyword不会使用索引,而"keyword% 会使用索引
    • or关键两边条件字段都建立索引时才会使用索引,只要有一边不是就会做全表扫描
    • 状态值。像性别这样的状态值,-个关键字对应很多条数据,会认为使用索引比全表扫描效率还低

    7. 索引的存储结构

    • btree:搜索多叉树:结点内关键字有序排列,关键字之间有一个指针,查找效率log(nodeSize,N),其中nodeSize指一 个结点内关键字数量 (这取决于关键字长度和结点大小)

    • b+ tree:由btree升级而来,数据和关键字存在一块空间,省去了由关键字到数据的映射找数据存放地的时间

    五、查询缓存

    1. 将select查询结果缓存起来,key为SQL语句,value为查询结果

    如果SQL功能一样,但只是多个空格或略微改动都会导致key的不匹配

    2. 客户端开启

    query. cache. _type
    复制代码
    • 0-不开启
    • 1-开启,默认缓存每条select,针对某个sq不缓存: select sql-no-cache
    • 2-开启,默认都不缓存,通过select sql-cache制定缓存哪-个条

    3. 客户端设置缓存大小

    query_ cache .size
    复制代码

    4. 重蛋缓存

    reset query cache
    复制代码

    5. 缓存失效

    日对数据表的改动会导致基 于该数据表的所有缓存失效(表层面的管理)

    六、分区

    1. 默认情况下一张表对应一组存储文件,但当数据量较大时(通常千万条级别)需要将数据分到多组存储文件,保证单个文件的处理效率

    2. partition by分区函数(分区字段)(分区逻辑)

    • hash-分区字段为整型
    • key-分区字段为字符串
    • range-基于比较,只支持less than
    • list-基于状态值

    3. 分区管理

    • 创建时分区:create table article0 partition by key(title) partitions 10
    • 修改表结构:alter table article add partition(分区逻辑)

    4. 分区字段应选择常用的检素字段,否则分区意义不大

    七、水平分割和垂直分割

    1. 水平

    多张结构相同的表存储同一类型数据

    单独一张表保证id唯一性

    2. 垂直

    分割字段到多张表,这些表记录是一对应关系

    八、集群

    1. 主从复制

    ①. 首先手动将slave和master同步一下

    • stop slave
    • master导出数据到slave执行一遍
    • show master status with read lock记录File和Position
    • 到slave.上change master to

    ②. start slave查看Slave_ IO_ Running和Slave_ SQL_ _Running,必须都为YES

    ③. master可读可写,但slave只能读,否则主从复制会失效需要重新手动同步

    ④. mysqlreplicate快速配置主从复制

    2. 读写分离(基于主从复制)

    ①. 使用原stcConecton

    WriteDatabase提供写连接

    ReadDatabase提供读连接

    ②. 借助Sping AOP和Aspec实现数据源动态切换

    • RoutingDataSourcelmpl extends AbstractRoutingDataSource,重写determineDatasource,注入到SqISessionFactory, 配置defaultTargetDatasource和targetDatasource (根据determineDatasource的返回值选择 具体数据源value-ref)

    • DatasourceAspect切面组件,配置切入点@Pointcut aspect0 (所有DAO类的所有方法),配置前置增强@Before(" aspect0") before(Joinpoint point), 通过point.getSignature.getName获取方法名,与METHOD TYPE MAP的前缀集合比对,将write/read设置到当前线程上(也是接下来要执行DAO方法的线程,前置增强将其拦截下来了)

    • DatasourceHandler,使用ThreadLocal在前置通知中将方法要使用的数据源绑定到执行该方法的线程上,执行方法要获取数据源时再根据当前线程获取

    3. 负载均衡

    算法

    • 轮询
    • 加权轮询
    • 依据负载情况

    4. 高可用

    为单机服务提供一个冗余机

    • 心跳检测
    • 虚IP
    • 主从复制

    九、典型SQL

    1. 线上DDL

    为了避免长时间表级锁定

    • copy策略,逐行复制,记录复制期间旧表SQL日志重新执行
    • mysq|5.6 online ddl,大大缩短锁定时间

    2. 批量导入

    ①. 先禁用索引和约束,导入之后统一建立

    ②. 避免逐条事务

    innodb为了保证一致性,默认为每条SQL加事务(也是要耗费时间的),批量导入前应手动建立事务,导入完毕后手动提交事务。

    3. limit offset,rows

    避兔较大的offset (较大页码数)

    offset用来跳过数据,完全可以用过滤筛选数据,而不是查出来之后再通过offset跳过

    4. select *

    尽量查询所需字段,减少网络传输延时(影响不大)

    5. order by rand()

    会为每条数据生成一个随机数最后根据随机数排序,可以使用应用程序生成随机主键代替

    6. limit 1

    如果确定了仅仅检索一条数据,建议都加上limit 1

    十、慢查询日志

    1. 定位查询效率较低的SQL,针对性地做优化

    2. 配置项

    • 开启slow_ query. log
    • 临界时间long_ query. time

    3. 慢查询日志会自己记录超过临界时间的SQL,并保存在datadir下的xxx-slow.log中

    十一、Profile

    1. 自动记录每条SQL的执行时间和具体某个SQL的详细步骤花费的时间

    2. 配置项日

    开启profiling

    3. 查看日志信息show profiles

    4. 查看具体SQL的详细步骤花费的时间日

    show profiles for query Query_ ID
    复制代码

    十二、典型的服务器配置

    1. max_ connections, 最大客户端连接数

    2. table_ open_ cache, 表文件缓存句柄数,加快表文件的读写

    3. key_ buffer. _size, 索引缓存大小

    4. innodb_ buffer. pool size, innodb的缓冲池大小,实现innodb各种功能的前提

    5. innodb_ file_ per_ table,每个表一个ibd文件, 否则innodb共享 表空间

    十三、压测工具MySQLSlap

    1. 自动生成sq|并执行来测试性能

    myqslap -a-to-generate sql -root -root
    复制代码

    2. 并发测试

    mysqlslap --auto-generate-sql --concurrency= 100 -uroot -proot,模拟100个客户端执行sql

    3. 多轮测试,反应平均情况

    mysqlslap --auto-generate-sql --concurrency= 100 --interations=3 -uroot -proot,模拟100个客户端执行sql.执行3轮

    4. 存储引擎测试

    • --engine=innodb:mysqlslap --auto-generate-sql --concurrency= 100 --interations=3 -- engine-innodb -uroot -proot,模拟100个客户端执行sql.执行3轮,innodb的处理性能

    • -- engine= myisam:mysqlslap -- auto-generate-sql --concurrency= 100 --interations=3 --engine-innodb -uroot -proot,模拟100个客户端执行sql.执行3轮,myisam的处理性能

    关注下面的标签,发现更多相似文章

    作者:Java架构筑基
    链接:https://juejin.im/post/5e1c2b2df265da3dec60ae7a
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    as3单播放mp3的cpu占用和windows上的media player差不多,占用很低
    Flash的Socket
    30个高质量的免费jquery滑块PSD文件
    40个创意的女性图片照片处理实例
    40个高品质各行各业免费3D样式PSD图标文件分享
    25美丽大气的jQuery滑块插件推荐
    40个金黄色的夏季摄影色彩推荐
    GNU make manual 翻译( 一百七十二)
    GNU make manual 翻译( 一百七十四)
    GNU make manual 翻译( 一百七十三)
  • 原文地址:https://www.cnblogs.com/seasonzone/p/13086562.html
Copyright © 2020-2023  润新知