数据类型

MySQL中定义数据字段的类型对你数据库的优化是非常重要的。
MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。

数值类型

MySQL支持所有标准SQL数值数据类型。
这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。
关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。
BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。
作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。

类型 大小 范围(有符号) 范围(无符号) 用途
TINYINT 1 byte (-128,127) (0,255) 小整数值
SMALLINT 2 bytes (-32 768,32 767) (0,65 535) 大整数值
MEDIUMINT 3 bytes (-8 388 608,8 388 607) (0,16 777 215) 大整数值
INT或INTEGER 4 bytes (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整数值
BIGINT 8 bytes (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 极大整数值
FLOAT 4 bytes (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 单精度 浮点数值
DOUBLE 8 bytes (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 双精度 浮点数值
DECIMAL 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 依赖于M和D的值 依赖于M和D的值 小数值

日期和时间类型

表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每个时间类型有一个有效值范围和一个”零”值,当指定不合法的MySQL不能表示的值时使用”零”值。
TIMESTAMP类型有专有的自动更新特性,将在后面描述。

类型 大小 ( bytes) 范围 格式 用途
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 ‘-838:59:59’/‘838:59:59’ HH:MM:SS 时间值或持续时间
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00/9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值
TIMESTAMP 4 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYYMMDD HHMMSS 混合日期和时间值,时间戳

字符串类型

字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。

类型 大小 用途
CHAR 0-255 bytes 定长字符串
VARCHAR 0-65535 bytes 变长字符串
TINYBLOB 0-255 bytes 不超过 255 个字符的二进制字符串
TINYTEXT 0-255 bytes 短文本字符串
BLOB 0-65 535 bytes 二进制形式的长文本数据
TEXT 0-65 535 bytes 长文本数据
MEDIUMBLOB 0-16 777 215 bytes 二进制形式的中等长度文本数据
MEDIUMTEXT 0-16 777 215 bytes 中等长度文本数据
LONGBLOB 0-4 294 967 295 bytes 二进制形式的极大文本数据
LONGTEXT 0-4 294 967 295 bytes 极大文本数据

注意:char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符。
CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。
BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。
有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。

笛卡尔积

笛卡尔乘积是指在数学中,两个集合XY的笛卡尔积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员

  • 有两个集合A,B 取这两个集合的所有组成情况
  • 要完成多表查询,需要消除无用的数据

数据库范式

  • 第一范式 1NF
    • 没一列都是不可分割的原子数据
  • 第二范式 2NF
    • 在1NF的基础上非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)
    • 函数依赖
      • A —> B 如果通过A属性(属性组)的值,可以确定唯一B属性的值 则称B依赖于A
      • 例如:学号 —> 名称 (学号,课程)—> 分数
    • 完全函数依赖
      • A —> B 如果A是一个属性组,则B属性值得确定需要依赖A属性组中的所有的属性值
      • 例如:(学号,课程)—> 分数
    • 部分函数依赖
      • A —> B 如果A是一个属性组,则B属性值得确定只需要依赖A属性组中的某一些值
      • 例如:(学号,课程)—> 分数
    • 传递函数依赖
      • A —> B , B —> C 如果通过A属性(属性组)的值,可以确定唯一值B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称为C传递函数依赖于A
      • 例如: 学号 —> 系名 系名 —> 系主任
      • 如果在一张表中,一个属性或属性组被其他所有属性完全依赖,则称这个属性(属性组)为该表的码
      • 例如:该表中码为:(学号,课程名称)
      • 主属性:码属性组中的所有属性
      • 非主属性:除码属性组之外的属性
  • 第三范式 3NF
    • 在2NF的基础上,任何非主属性不依赖于其他非主属性(在2NF基础上消除传递依赖)

事务

事务的四大特征

  • 事务特征(ACID)
    • 原子性(Atomicity)指事务是一个不可分割的整体,其中的操作要么全执行或全不执行
    • 一致性(Consistency)事务前后属性的完整性必须保持一致
    • 隔离性(Isolation)事务的隔离性是多个事务并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
    • 持久性(Durability)指一个事务一旦被提交,他对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

事务提交方式

  • 自动提交
    • mysql数据库默认自动提交
    • 一条DML语句会自动提交一次事务
  • 手动提交
    • Oracle数据库默认手动提交
    • 需要先开启事务再提交 或者回滚

修改事务的默认提交方式

  • 1 代表自动提交
  • 0 代表手动提交 ```plsql — 查看默认提交方式
    select @@autocommit;

— 修改默认提交方式 set @@autocommit = 0;

  1. <a name="UTXlp"></a>
  2. ## 事务隔离级别
  3. **隔离级别从小到大安全性越高,但是效率越来越低**
  4. - **read uncommitted 读未提交 **
  5. - 产生问题:脏读、不可重复读、幻读
  6. - **read committed 读已提交 **
  7. - 产生问题:不可重复读、幻读
  8. - **repeateable read 可重复读**
  9. - 产生问题:幻读
  10. - 默认事务隔离级别
  11. - **serializable **可序列化的
  12. - 可以解决所有问题
  13. 多个事务之间相互独立,但是多个事务操作同一数据则会引发一些问题,设置不同的隔离基本就可以解决这些问题。
  14. 1. 脏读:一个事务读取到另一个事务中没有提交的数据
  15. 1. 不可重复读(虚读):在同一个事务中,两次读取的数据不一致
  16. 1. 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改
  17. ```plsql
  18. -- 设置隔离级别需要重新打开mysql窗口
  19. -- 查询数据库隔离级别
  20. select @@tx_isolation;
  21. -- 设置数据库隔离级别
  22. set global transaction isolation level 级别;

索引

InnoDB

InnoDB索引实现

  • 主键索引
    • InnoDB存储引擎的主键索引,叶子节点中索引关键字和数据是在一起存放的,非叶子节点存存储主键信息
  • 辅助索引
    • InnoDB的辅助索引,叶子节点上存放的是索引关键字和对应的主键

辅助索引的B+树,先根据关键字找到对应的主键,再取主键索引树上找到对应的行记录数据。
从索引树上可以看到,InnoDB的索引关键字和数据都是在一起存放的,体现在磁盘存储上。

例如创建一个user表,会在磁盘上只存储两种结构:user.frm(存储表的结构)、user.idb(存储索引和数据)
InnoDB的索引树叶子节点包含了完整的数据记录,这种索引叫做聚集索引。

因为InnoDB的数据文件本身要按照主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有指定显示,则MyISAM系统会自动选择一个可以唯一标识的数据记录列作为主键,如果不存在这种列,则Mysql会自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。

索引设计原则

  • NORMAL:普通索引。
    • 索引列没有任何限制
  • PRIMARY:主键索引。
    • 索引列唯一且不能为空一张表只能有一个主键索引(主键索引通常在建表的时候就指定)
  • UNIQUE:唯一索引。
    • 索引列的值必须是唯一的,但允许有空;
  • FULLTEXT:全文搜索的索引。
    • FULLTEXT 用于搜索很长一篇文章的时候,效果最好。用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。

索引的分类

按照功能分类

  • 普通索引:最基本的索引,没有任何的限制
  • 唯一索引:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值组合必须唯一
  • 主键索引:一种特殊的唯一索引,不允许有空值。在建表时有主键列同时创建主键索引
  • 联合索引:将单列索引进行组合
  • 外键索引:只有InnoDB引擎支持外键索引,用来保证数据的一致性、完整性和实现级联操作
  • 全文索引:快速匹配全部文档的方式,InnoDB引擎5.6版本以后才支持全文索引。Memory引擎不支持
  • 单值索引:一个索引只包含单个列,一个表可以有多个单列索引
  • 唯一索引:索引列的值必须唯一,但允许有空值
  • 复合索引:一个索引包含多个列

索引提示

  • FORCE INDEX
    • 强制使用索引
  • USE INDEX
    • 使用索引
  • IGNORE INDEX
    • 忽略索引
      1. SELECT * FROM table_name FORCE INDEX (`index_name`)

索引失效的几种情况

  1. 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
  2. 联合索引,不是使用的第一部分,则不会使用索引
  3. like查询以%开头
  4. 字符串不加单引号
  5. 范围查询右边的字段

避免索引失效

  1. 全值匹配,对索引中索引的列都指定具体值 该情况下,索引生效,执行效率高
  2. 最左前缀法则 如果索引包含了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始,并且不跳过索引中的列
  3. 范围查询右边的字段,不能使用索引
  4. 不要在索引列上进行运算操作,否则索引失效
  5. 字符串不加单引号,索引将失效

优化

  1. -- 查询以Com开头的数据的操作状态
  2. show status like 'Com____';
  3. -- 查询innodb数据库的操作状态
  4. show global status lick 'Innodb_rows_%';
  5. -- 查询当前连接中执行的sql(慢连接)
  6. show processlist

explain

  • id:id的值不同,则代表查询的顺序不同 可以得到表结构的加载顺序
  • select_type: 表示select的类型
    • SIMPLE:简单的select查询,查询中不包含子查询或者UNION
    • PRIMARY:查询中若包含任何复杂的子查询,最外层查询标记为该标识
    • SUBQUERY:在select或where列表中包含了子查询
    • DERIVED:在from列表中包含子查询,被标记为DERIVED(衍生)mysql会递归执行这些子查询,把结果放在临时表中
    • UNION:若第二个select出现在union之后,则标记为union;若union包含在from子句的子查询中,外层select将被标记为derived
    • UNION RESULT:从union表获取结果的select
  • table:输出结果集的表
  • partitions:匹配的分区
  • type:表示表的连接类型
  • possible_keys:表示查询时,可能使用的索引
  • key:表示实际使用的索引
  • key_len:索引字段的长度
  • ref:列与索引的比较
  • rows:扫描出的行数(估算的行数)
  • filtered:按表条件过滤的行百分比
  • Extra:执行情况的描述和说明

image.png

profile

查看每条sql语句的耗时时间

  1. -- 查询是否支持profile
  2. select @@have_profiling;
  3. -- 查询是否打开profile
  4. select @@profiling;
  5. -- 当前会话开启profile
  6. set profiling=1;
  7. -- 查询每个操作的耗时
  8. show profiles;
  9. -- 查看查询语句执行阶段的耗时时间
  10. show profile frq query 查询语句id;

FAQ

InnoDB 与 MyISAM 的区别

对比项 MyISAM InnoDB
外键 ×
事务 ×
行表锁 表锁,即操作一条记录锁住全表,不适合高并发 行锁,操作时只锁一行,适合高并发
缓存 只缓存索引,不缓存真实数据 不仅缓存索引还缓存数据,对内存要求高,耗费资源
关注点 节省资源、消耗少、简单业务 并发写、事务、更大资源
  • 对比MyISAM,InnoDB写效率差,更加耗费资源
  • 相比之下,InnoDB适合大量数据操作,MyISAM适合简单业务处理
  • 除增删外还需要更新、删除操作应选择InnoDB
    • 行锁的缘故
  • MyISAM崩溃后数据无法恢复,与不支持事务相关
  • 无特殊原因不推荐MyISAM存储引擎