Mysql知识点整理

索引相关

索引类型

主键索引:数据列不容许重复,不容许为NULL。一个表只能有一个主键索引。InnoDB的主键索引为聚簇索引,而MyISAM的主键索引为非聚簇索引。 建立:ALTER TABLE table_name ADD PRIMARY KEY (column);mysql

惟一索引:数据列不容许重复,容许为NULL,一个表中容许建立多个惟一索引。惟一索引能够用做业务防重。 建立:ALTER TABLE table_name ADD UNIQUE (column1, column2);git

普通索引:基本的索引类型,没有惟一性的限制,容许为NULL值。 建立:ALTER TABLE table_name ADD KEY (column1, column2)github

全文索引:是目前搜索引擎使用的一种关键技术,InnoDB不支持全文索引,MyISAM支持全文索引。 建立:ALTER TABLE table_name ADD FULLTEXT (column);算法

最左前缀原则

联合索引从左边的列到右边的列依次匹配,联合索引的最左前缀原则以下: 对于联合索引:index(co1, col2, col3)sql

  1. where col1=1where col1=1 and col2=2where col1=1 and col2=2 and col3=3都会走这个索引。第一个语句使用 col1,第二个语句使用 col1,col2,第三个使用 col1,col2,col3;
  2. where col2=2where col2=2 and col3=3不会走索引;
  3. where col3=3 and col2=2 and col1=1未经查询优化的话不会走索引,可是通过查询优化后会走索引...;
  4. where col1=1 and col3=3 仅使用 col1;
  5. where col1=1 and col2>2 and col3=3 仅使用 col1,col2;
  6. where col1=1 and col2 like 'xx%' 使用 col1,col2;
  7. where col1=1 and col2 like '%xx'' 仅使用 col1。

索引算法(B-Tree 和 HASH)

B-Tree索引数据库

B-Tree索引是一棵多路查找平衡树,InnoDB 和 MyISAM 存储引擎都支持 B-Tree 索引。InnoDB 支持聚簇索引,InnoDB 默认会为主键建立聚簇索引,聚簇索引的非叶子节点不保存数据,只有叶子节点会保存数据,聚簇索引的叶子节点还会保存相邻的后一个节点的指针。非聚簇索引叶子节点不保存数据,只保存主键索引。缓存

HASH索引安全

Hash 索引检索效率高,只须要一次定位,不像 B-Tree 索引须要从根节点到叶子节点,最后才能访问到页节点这样屡次的IO访问。 Hash索引虽然检索效率高,可是也有不少的不足之处:并发

  1. Hash 索引仅仅能知足”=”,”IN”和”<=>”查询,不能使用范围查询。 因为 Hash 索引比较的是进行 Hash 运算以后的 Hash 值,因此它只能用于等值的过滤,不能用于基于范围的过滤,由于通过相应的 Hash 算法处理以后的 Hash 值的大小关系,并不能保证和Hash运算前彻底同样。函数

  2. Hash 索引没法被用来避免数据的排序操做。 因为 Hash 索引中存放的是通过 Hash 计算以后的 Hash 值,并且 Hash 值的大小关系并不必定和 Hash 运算前的键值彻底同样,因此数据库没法利用索引的数据来避免任何排序运算;

  3. Hash 索引不能利用部分索引键查询。 对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一块儿计算 Hash 值,而不是单独计算 Hash 值,因此经过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也没法被利用。

  4. Hash 索引在任什么时候候都不能避免表扫描。 前面已经知道,Hash 索引是将索引键经过 Hash 运算以后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,因为不一样索引键存在相同 Hash 值,因此即便取知足某个 Hash 键值的数据的记录条数,也没法从 Hash 索引中直接完成查询,仍是要经过访问表中的实际数据进行相应的比较,并获得相应的结果。

  5. Hash 索引遇到大量Hash值相等的状况后性能并不必定就会比B-Tree索引高。 对于选择性比较低的索引键,若是建立 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会很是麻烦,会浪费屡次表数据的访问,而形成总体性能低下。

B-Tree vs. HASH索引

索引名 HASH B-Tree
是否支持最左前缀匹配原则 不支持,只有索引的所有字段都用上才会匹配到 支持,用上索引的第一个字段就能够匹配索引
MyISAM和InnoDB是否支持 不支持(只有Memory和NDB引擎索引支持) 支持
范围查询可否命中索引 不能够,只有“=”,“IN”,“<=>”(等价于的意思)查询能命中 能够
是否必定会全表扫描

索引设计原则

  1. 为常常须要排序、分组和联合的字段创建索引
  2. 为常常做为 where 条件查询的字段创建索引
  3. 在选择性好的列上创建索引,所谓选择性好是指筛选出来的数据少,例如性别的选择性就比较差,而姓名的选择性就高
  4. 联合索引须要注意索引的顺序,将选择性高的放在前面
  5. 索引虽然能加快查询,可是索引也是有代价的,首先索引会占用存储空间。其次索引的维护也是有消耗的。所以,索引不是越多越好。

数据类型

数字类型

整数: tinyint、smallint、mediumint、int、bigint

type Storage Minumun Value Maximum Value
(Bytes) (Signed/Unsigned) (Signed/Unsigned)
TINYINT 1 -128 127
0 255
SMALLINT 2 -32768 32767
0 65535
MEDIUMINT 3 -8388608 8388607
0 16777215
INT 4 -2147483648 2147483647
0 4294967295
BIGINT 8 -9223372036854775808 9223372036854775807
0 18446744073709551615

浮点数: float、double、real、decimal

属性 存储空间 精度 精确性 说明
FLOAT(M, D) 4 bytes 单精度 非精确 单精度浮点型,m总个数,d小数位
DOUBLE(M, D) 8 bytes 双精度 比Float精度高 双精度浮点型,m总个数,d小数位

FLOAT容易形成精度丢失

定点数DECIMAL

  1. 高精度的数据类型,经常使用来存储交易相关的数据
  2. DECIMAL(M,N).M表明总精度,N表明小数点右侧的位数(标度)1 < M < 254, 0 < N < 60;
  3. 存储空间变长

日期和时间

date、time、datetime、timestamp、year

类型 字节 精确性
DATE 三字节 2015-05-01 精确到年月日
TIME 三字节 11:12:00 精确到时分秒
DATETIME 八字节 2015-05-01 11::12:00 精确到年月日时分秒
TIMESTAMP 2015-05-01 11::12:00 精确到年月日时分秒
  • MySQL在5.6.4版本以后,TIMESTAMPDATETIME支持到微秒。
  • TIMESTAMP会根据系统时区进行转换,DATETIME则不会
  • 存储范围的区别
    • TIMESTAMP存储范围:1970-01-01 00::00:01 to 2038-01-19 03:14:07
    • DATETIME的存储范围:1000-01-01 00:00:00 to 9999-12-31 23:59:59
  • 通常使用TIMESTAMP国际化
  • 如存时间戳使用数字类型BIGINT

字符串类型

字符串: char、varchar 文本: tinytext、text、mediumtext、longtext

类型 单位 最大 特性
CHAR 字符 最大为255字符 存储定长,容易形成空间的浪费
VARCHAR 字符 能够超过255个字符 存储变长,节省存储空间
TEXT 字节 总大小为65535字节,约为64KB -
  • TEXT在MySQL内部大多存储格式为溢出页,效率不如CHAR
  • Mysql默认为utf-8,那么在英文模式下1个字符=1个字节,在中文模式下1个字符=3个字节。

二进制(可用来存储图片、音乐等)

tinyblob、blob、mediumblob、longblob

InnoDB和MyISAM的区别

  • InnoDB支持事务,MyISAM不支持。
  • MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用。
  • InnoDB支持外键,MyISAM不支持。
  • 从MySQL5.5.5之后,InnoDB是默认引擎。
  • InnoDB不支持FULLTEXT类型的索引。
  • InnoDB中不保存表的行数,如select count() from table时,InnoDB须要扫描一遍整个表来计算有多少行,可是MyISAM只要简单的读出保存好的行数便可。主要的是,当count()语句包含where条件时MyISAM也须要扫描整个表。
  • 对于自增加的字段,InnoDB中必须包含只有该字段的索引,可是在MyISAM表中能够和其余字段一块儿创建联合索引。
  • 清空整个表时,InnoDB是一行一行的删除,效率很是慢。MyISAM则会重建表。
  • InnoDB支持行锁(某些状况下仍是会锁整个表,如update table set a = 1 where user like '%lee%')

MVCC

MVCC的实现,是经过保存数据在某个时间点的快照来实现的,根据事务开始时间的不一样,每一个事务对于同一张表,同一时刻看到的数据多是不一样的。

InnoDB的 MVCC ,是经过在每行记录的后面保存两个隐藏的列来实现的。这两个列,一个保存了行的建立时间,一个保存了行的过时时间(或删除时间), 固然存储的并非实际的时间值,而是系统版本号。

能够认为MVCC是行级锁的一个变种,可是它在不少状况下避免了加锁操做,所以开销更低。虽然实现机制有所不一样,但大都实现了非阻塞的读操做,写操做也只锁定必要的行。

在MVCC协议下,每一个读操做会看到一个一致性的 snapshot,而且能够实现非阻塞的读。MVCC 容许数据具备多个版本,这个版本能够是时间戳或者是全局递增的事务 ID,在同一个时间点,不一样的事务看到的数据是不一样的。

  • select:知足如下两个条件innodb会返回该行数据:(1)该行的建立版本号小于等于当前版本号,用于保证在select操做以前全部的操做已经执行落地。(2)该行的删除版本号大于当前版本或者为空。删除版本号大于当前版本意味着有一个并发事务将该行删除了。
  • insert:将新插入的行的建立版本号设置为当前系统的版本号。
  • delete:将要删除的行的删除版本号设置为当前系统的版本号。
  • update:不执行原地update,而是转换成insert + delete。将旧行的删除版本号设置为当前版本号,并将新行insert同时设置建立版本号为当前版本号。

其中,写操做(insert、delete和update)执行时,须要将系统版本号递增。 因为旧数据并不真正的删除,因此必须对这些数据进行清理,innodb会开启一个后台线程执行清理工做,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫作purge。 经过MVCC很好的实现了事务的隔离性,能够达到repeated read级别,要实现serializable还必须加锁。

MVCC只在READ COMMITED 和 REPEATABLE READ 两个隔离级别下工做。READ UNCOMMITTED老是读取最新的数据行,而不是符合当前事务版本的数据行。而SERIALIZABLE 则会对全部读取的行都加锁。

InnoDB间隙锁

Record lock

单条索引记录上加锁,InnoDB 的行锁是经过索引实现的,如没有索引,则锁住的不是记录行而是整个表。

Gap lock

间隙锁,锁定一个范围,但不包括记录自己。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的状况。

Next-key lock

Next-key lock 就是 Record lock + Gap lock 的组合,它锁定的是一个范围,而且锁定记录自己。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。

间隙锁(Next-key lock)的条件

mysql的事务隔离级别是可重复读(RR,Repeatable Read),而且 innodb_locks_unsafe_for_binlog 参数设置为0

事务ACID

  1. 原子性(Atomicity):不可分割的操做单元,事务中全部操做,要么所有成功;要么撤回到执行事务以前的状态
  2. 一致性(Consistency):若是在执行事务以前数据库是一致的,那么在执行事务以后数据库也仍是一致的;
  3. 隔离性(Isolation):事务操做之间彼此独立和透明互不影响。事务独立运行。这一般使用锁来实现。一个事务处理后的结果,影响了其余事务,那么其余事务会撤回。事务的100%隔离,须要牺牲速度。
  4. 持久性(Durability):事务一旦提交,其结果就是永久的。即使发生系统故障,也能恢复。

delete drop truncate区别

truncate 和 delete只删除数据,不删除表结构 ,drop删除表结构,而且释放所占的空间。

删除数据的速度,通常来讲: drop> truncate > delete

delete属于DML语言,须要事务管理,commit以后才能生效。drop和truncate属于DDL语言,操做马上生效,不可回滚

使用场合:

  • 当你再也不须要该表时,用 drop;
  • 当你仍要保留该表,但要删除全部记录时, 用 truncate;
  • 当你要删除部分记录时(always with a where clause), 用 delete.

Mysql explain

explain 用于查看 SQL 语句执行计划,其结果主要包含如下几个重要参数:id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra,下面对这些字段出现的可能进行解释。

select_type

表示查询中每一个select子句的类型

  • SIMPLE(简单SELECT,不使用UNION或子查询等)
  • PRIMARY(查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
  • UNION(UNION中的第二个或后面的SELECT语句)
  • DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)
  • UNION RESULT(UNION的结果)
  • SUBQUERY(子查询中的第一个SELECT)
  • DEPENDENT SUBQUERY(子查询中的第一个SELECT,取决于外面的查询)
  • DERIVED(派生表的SELECT, FROM子句的子查询)
  • UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须从新评估外连接的第一行)

type

表示MySQL在表中找到所需行的方式,又称“访问类型”。

经常使用的类型有: ALL, index, range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)

  • ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
  • index: Full Index Scan,index与ALL区别为index类型只遍历索引树
  • range:只检索给定范围的行,使用一个索引来选择行
  • ref: 表示上述表的链接匹配条件,即哪些列或常量被用于查找索引列上的值
  • eq_ref: 相似ref,区别就在使用的索引是惟一索引,对于每一个索引键值,表中只有一条记录匹配,简单来讲,就是多表链接中使用primary key或者 unique key做为关联条件
  • const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的状况下,使用system
  • NULL: MySQL在优化过程当中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值能够经过单独索引查找完成。

possible_keys

指出MySQL能使用哪一个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不必定被查询使用 该列彻底独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。 若是该列是NULL,则没有相关的索引。在这种状况下,能够经过检查WHERE子句看是否它引用某些列或适合索引的列来提升你的查询性能。若是是这样,创造一个适当的索引而且再次用EXPLAIN检查查询

Key

key列显示MySQL实际决定使用的键(索引) 若是没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

explain 总结

  • EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响状况
  • EXPLAIN不考虑各类Cache
  • EXPLAIN不能显示MySQL在执行查询时所做的优化工做
  • 部分统计信息是估算的,并不是精确值
  • EXPALIN只能解释SELECT操做,其余操做要重写为SELECT后查看执行计划。

参考资料

ningyu1.github.io/site/post/5…
MySQL 的 MVCC 原理
MySQL - 索引详解

相关文章
相关标签/搜索