前言

数据库在系统中是非常重要的一环,当数据量大的时候,数据库就会有瓶颈,也就是查询变慢,我们需要对数据库进行优化

建表时优化

Schema 和数据类型优化

整数

TinyInt,SmallInt,MediumInt,Int,BigInt 使用的存储 8,16,24,32,64 位存储空间,使用Unsigned 表示不允许负数,可以使正数的上限提高一倍

实数

  • Float,Double 支持近似的浮点运算
  • Decimal  用于存储精确小数

字符串

  • Varchar 存储变长的字符串。需要 1 或 2 个额外的字节记录字符串的长度
  • char    定长,适合存储固定长度的字符串,如MD5
  • Blob,Text  为了存储很大的数据而设计的,分别采用二进制和字符的方式

时间类型

  • DateTime  保存大范围的值,占8个字节
  • TimeStamp  推荐,与Unix 时间戳相同,占四个字节

优化点建议

  • 尽量使用对应数据类型。比如,不要用字符串类型保存时间,用整型保存IP
  • 选择更小的数据类型。能用 TinyInt 不用 Int
  • 标识列(如 主键),建议使用整型,不推荐字符串类型,占用空间更多,而且计算速度比整型慢
  • 不推荐 ORM 系统自动生成的Schema ,通常具有不注重数据类型,使用很大的Varchar 类型,索引利用不合理等问题
  • 真实场景混用范式和反范式。冗余高查询效率高,插入更新效率低,冗余低,插入更新效率高,查询效率低
  • 创建完全的独立的汇总表/缓存表,定时生成数据,用于用户耗时时间长的操作,对于精确度要求高的汇总操作,可以采用 历史结果 + 最新记录的结果来达到快速查询的目的
  • 数据迁移,表升级的过程中可以使用影子表的方式,通过修改原表的表名,达到保存历史数据,同时不影响新表使用的目的
  • 不建议列值默认为 null

不建议为null的原因:

  • 不能使用算术比较运算符,如=、<或<>来测试NULL

You cannot use arithmetic comparison operators such as =, <, or <> to test for NULL.

  • COUNT()、MIN()和SUM()等聚合(组)函数忽略空值
  • 使用DISTINCT、GROUP BY或ORDER BY时,所有空值都被视为相等。

官方文档:“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”

Mysql难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列需要更多的存储空间(见上面的e文),还需要mysql内部进行特殊处理。可空列被索引后,每条记录都需要一个额外的字节,还能导致MYisam 中固定大小的索引变成可变大小的索引。

You can add an index on a column that can have NULL values if you are using the MyISAM, InnoDB, or MEMORY storage engine. Otherwise, you must declare an indexed column NOT NULL, and you cannot insert NULL into the column.

你可以在包含NULL值的列上添加索引,如果您使用的是MyISAM、InnoDB或内存存储引擎。除此之外,必须声明索引列NOT NULL,并且不能将NULL插入该列。

索引

索引包含一个或多个列的值。MySQL只能高效的利用索引的最左前缀列

索引的优势:

  • 减少查询扫描的数据量
  • 避免排序和临时表
  • 将随机IO变成顺序IO(顺序IO 的效率高于随机IO)

B+Tree

使用最多的索引类型,采用B-Tree数据结构来存储数据(每一个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的遍历)。B-Tree索引适用于全键值,键值范围,键前缀查找,支持排序

限制:

  • 如果不是按照索引的最左原则匹配,则无法使用索引
  • 不能跳过索引中的列,如果使用第一列和第三列索引,则只能使用第一列索引
  • 如果查询中有个范围查询,则其右边的所有列都无法使用索引优化查询

hash索引

只有精确匹配索引所有的列,查询才有效。存储引擎会对所有的索引列计算一个hash码,哈希索引将所有的哈希码存储在索引中,并保存指向每个数据行的指针

 限制

  • 无法用于排序
  • 不支持部分匹配
  • 只支持等值查询,如 = ,in () ,不支持  <>

优化建议:

  • 注意每种索引的适用范围和适用限制
  • 索引的列如果是表达式的一部分或者是函数的参数,则失效
  • 针对特别长的字符串,可以使用前缀索引,根据索引的选择性选择合适的前缀长度
  • 使用多列索引的时候,可以通过AND 和 OR 语法连接
  • 重复索引没必要 如  A,B  和 A
  • 索引在 where 条件查询 和 group by 语法查询的时候特别有效
  • 将范围查询放在条件查询的最后,防止范围查询导致的右边索引失效(经测试,索引 (int,string)int是个范围,a < 2 and b = "b" ,走的还是全索引)
  • 索引最好不要选用过长的字符串,并且索引列也不宜为null

查询时优化

查询质量的三个重要指标

  • 响应时间(服务时间,排队时间)
  • 扫描的行
  • 返回的行

查询优化的点

  • 避免查询无关的列,如使用Select * 返回所有的列
  • 避免查询无关的行
  • 切分查询。将一个对服务器压力较大的任务分解到一个较长的时间中,并分多次执行。如要删除一万条数据,可以分10次执行,每次执行完成后暂停一段时间,再继续执行,过程中可以释放服务器资源给其他任务
  • 分解关联查询,将多表关联查询的一次查询,分解成对单表的多次查询。可以减少锁的竞争,查询本身的查询效率也比较高。因为Mysql 的连接和断开都是轻量级操作,不会由于查询拆分多次,造成效率的问题
  • 注意count 的操作只能统计不为null 的列,所以统计总行数使用 count (*)

count(1)与count(*)得到的结果一致,包含null值。

count(字段)不计算null值

  • group by 按照标识分组效率高,分组结果不宜出现行分组列之外的列
  • 关联查询延迟关联,可以根据查询条件先缩小各自要查询的范围,再关联
  • limit 分页优化,可以根据索引覆盖扫描,再根据索引列关联自身查询其他列

如:

select
id,
name,
age
where
student s1
inner join (
select
id
from
student
order by
age
limit 50,5
) as s2 on s1.id = s2.id
  • Union 查询默认去重,如果不是业务必须,建议使用效率更高的Union All
  • in 和 exists

1)、在两个表差不多大的时候,in和 exists 没区别

2)、在外表比内表大时,如 select  * from a where (select name from b where id = 2)

a 表大于 b 表,这种用in

3)、外表比内表小,用 exists

  • not in 和 not exists   ,用not exists

补充

1、隐式转换

条件中的字段类型和表结构类型不一致,MySQL 会自动加转换函数,导致索引作为函数中的参数失效

2、like

查询前面部分未输入,以% 开头无法命中索引

3、5.7 版本的一个特性

支持JSON 格式数据,并提供相关内置函数

create table json_test (name JSON );insert into json_test values ('{"name":"value1", "name2":"value2"}');select * from json_test where JSON_CONTAINS (name,'$.name1');

4、关注 explain 在性能分析中的使用 

1)select_type

simple 表示简单的select ,没有union 和子查询

primary 有子查询,最外面的 select 查询就是 primary

union union中的第二个或随后的select 查询,不依赖外部查询的结果

dependent union union 中的第二个或随后的 select 查询,依赖外部查询结果

2)type 

system 表仅有一行(=系统表),这是const 连接类型的一个特例

const  常量查询

ref 非谓语索引访问,只有普通索引

eq_ref 使用唯一索引或组件查询

all 全表查询

index 根据索引查询全表

range 范围查询

3)possible_keys

表中可能存在帮助查询的索引

4)key

选择使用的索引

5)key_len

使用索引的长度 ,如果是聚合索引,能根据这个判断走的什么索引,(a,b)  a   a,b

6)rows

扫描的行数,越大越不好

7)extra 

Only index 信息从索引中检索出,比扫描表快

where used 使用 where 限制

Using filesort 可能存在内存或磁盘排序

Using temporary 对查询结果排序时使用临时表

如何根据需求创建表

需求

1、乘客通过网站注册登录

2、实名认证通过mork实现

3、铁路部门管理员有如下功能

  • 车次、车厢、经停站、时刻表的增删改查
  • 用户管理:用户增删改查、黑名单管理,为用户分配角色
  • 角色管理:角色增删改查,为角色分配相应的功能
  • 菜单管理:菜单增删改查

4、定时任务:生成火车票

5、普通用户拥有如下功能

  • 修改信息:密码、住址、电话、邮箱
  • 代沟功能:录入其他乘客信息,合并下单支付
  • 余票查询:可以通过车次、出发站、到达站、日期等条件查询
  • 购买车票下单:选择车次,选择乘车人,座位类型后下单
  • 订单支付:第三方支付、支付宝支付、微信支付

6、支付成功后通知用户

分析:

名词:实体、属性

动词:关系

设计数据库的时候要满足范式

  • 第一范式:每列属性不可拆分
  • 第二范式:表中的每行记录的内容都和主键相关,每列和主键相关
  • 第三范式:每列都和主键列直接关系,而不是间接关系

不忘初心,方得始终;初心易得,始终难守。

孤尽训练营打卡日记day04--MySQL优化相关推荐

  1. 孤尽训练营打卡日记day28--第四周总结

    前言 光阴似箭,日月如梭.转眼已经过去了一个月,孤尽训练营第四周也已经结束,今天我们一起来对这一周的内容做个简单回顾. 第一次课 单元测试和系统安全规约 什么是单元测试? 对软件组成单元进行的测试,其 ...

  2. 孤尽训练营打卡日记day14--第二周总结

    前言 光阴似箭,日月如梭!跟着孤尽老师学习的第二周也即将结束,训练营的日子也已经过去了一半.古人云,学而不思则罔,思而不学则殆.今天我们来对第二周的学习做个总结. 内容回顾 day08 首先,孤尽老师 ...

  3. 孤尽训练营打卡日记day24--系统安全规约

    前言 现在是大数据的时代,数据是非常重要的,一张照片就有可能泄漏了你的位置信息.在我们的系统中,安全一直是老生常谈的话题,怎么维护我们的系统安全,在我们日常开发中,怎么避免出现安全问题,我们跟着Joe ...

  4. 孤尽训练营打卡日记day19--OAuth2基础

    前言 我们现在的系统架构都是微服务的架构,也就是说,一个完整的功能,是由后台多个工程一起完成的.那么就会有一个问题,明明是多个工程,但是我们只需要登录一次,这是怎么实现的呢?今天我们跟着刘雪松老师一起 ...

  5. 利用油猴脚本显示扇贝网真实打卡日记

    本文首发在我的个人博客:https://jlice.top/p/7kmxm/.欢迎大家前去参观,么么哒~ 前一段时间发现扇贝网页版显示的打卡日记和手机上看到的不一致,感觉应该是网页版开发滞后的原因.这 ...

  6. 训练营打卡Day57

    训练营打卡Day57 文章目录 训练营打卡Day57 题121:[1143. 最长公共子序列](https://leetcode.cn/problems/longest-common-subseque ...

  7. 训练营打卡Day45

    训练营打卡Day45 文章目录 训练营打卡Day45 题105:[70. 爬楼梯](https://leetcode.cn/problems/climbing-stairs/) 思路 代码 题106: ...

  8. 无基础学c语言的打卡日记总论

    背景知识:笨人浙江考生,选课是政史地.目前在读大一,知道自己的专业学c并且还学数学分析和高等代数,一开始不以为意. 学校用的教材是谭浩强老师的c语言程序设计.推荐的,小白友好. 上课之前有很认真的自习 ...

  9. 阿里天池龙珠训练营打卡2

    阿里天池龙珠训练营打卡2 文章目录 列表添加元素 删除列表中的元素 获取列表的元素 列表的一些其他方法 字符串常用内置方法 字符串格式化 列表配合集合去重 列表添加元素 list.append(obj ...

最新文章

  1. SpringMVC调用接口一直乱码
  2. C#进行Visio二次开发之知识点考核试题
  3. python setup脚本编写
  4. apt update无法连接上 127.0.0.1:10808
  5. 那些年,我们处理过的SQL问题
  6. Linux下文件开头的feff的问题
  7. [译]git fetch
  8. Codeforces 837D 动态规划
  9. HTML设置地址栏收藏夹图标
  10. Unity3D开发游戏坦克大战
  11. 子网掩码是什么,IP段的24是什么写法(CIDR写法,斜杠记法斜线记法)
  12. html八边形怎么显示,如何用几何画板自定义工具画正八边形
  13. 【C语言】动态申请空间
  14. 研发团队管理:IT研发中项目和产品原来区别那么大,项目级的项目是项目,产品级的项目是产品!!!
  15. mininet 主机双网关拓扑设计
  16. 室内导航技术蓝牙aoa定位运用
  17. 全新2022测算系统完整版+支持对接结
  18. A Game of Thrones(84)
  19. docker push: retrying in 5 seconds... keep doing this
  20. 虚拟主播也带货?直播电商的变与不变

热门文章

  1. 路径规划服务基于java实现
  2. unity3d中ScriptingBackend选择mono和il2cpp的区别
  3. 什么是jason?jason应该如何使用和解读?jason的语法格式
  4. windows7的快速启动栏
  5. 设计模式之Tank大战02
  6. python批量添加qq好友_Python QQ批量登录
  7. Java 并发编程解析 | 如何正确理解Java领域中的内存模型,主要是解决了什么问题?
  8. BCG Application Management
  9. Android编译详解之lunch命令
  10. 吉首大学第十届“新星杯”大学生程序设计大赛 A题题解