- mysql都有哪些索引类型;为什么b+树,红黑树、b树为什么不好;
- mysql的主键,唯一索引区别;
- 怎么建索引
- 一条sql怎么优化?
- 数据库的三大范式?
- B+树索引、哈希索引;
- hash索引查询单条确实比较快,但是他是无序的,查询多条或者排序的话性能就比较低了,并且在内存资源紧张的情况下,树索引可以分批装入内存进行计算。
如果我们要进行模糊查找的话,显然哈希表这种结构是不支持的,只能遍历这个表。而B+树则可以通过最左前缀原则快速找到对应的数据。 - 因为红黑树子节点只有两个,造成树较高,树越高,那么查询事件复杂度就越高,并且需要更多的磁盘IO,严重影响性能。B树是一个多路搜索树,也就是每个节点可以有多个子节点,这样是为了降低树的高度,减少磁盘IO次数。
- 相比于B树,B+树有以下优势:
更少的IO次数: B+树的非叶节点只包含键,而不包含真实数据,因此每个节点存储的记录个数比B数多很多(即阶m更大),因此B+树的高度更低,访问时所需要的IO次数更少。此外,由于每个节点存储的记录数更多,所以对访问局部性原理的利用更好,缓存命中率更高。
更适于范围查询: 在B树中进行范围查询时,首先找到要查找的下限,然后对B树进行中序遍历,直到找到查找的上限;而B+树的范围查询,只需要对链表进行遍历即可。
更稳定的查询效率: B树的查询时间复杂度在1到树高之间(分别对应记录在根节点和叶节点),而B+树的查询复杂度则稳定为树高,因为所有数据都在叶节点。
二叉查找树(BST):解决了排序的基本问题,但是由于无法保证平衡,可能退化为链表;
平衡二叉树(AVL):通过旋转解决了平衡的问题,但是旋转操作效率太低;
红黑树:通过舍弃严格的平衡和引入红黑节点,解决了AVL旋转效率过低的问题,但是在磁盘等场景下,树仍然太高,IO次数太多;
B树:通过将二叉树改为多路平衡查找树,解决了树过高的问题;
B+树:在B树的基础上,将非叶节点改造为不存储数据的纯索引节点,进一步降低了树的高度;此外将叶节点使用指针连接成链表,范围查询更加高效。
普通索引:最基本的索引,没有任何限制
唯一索引:与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。
主键索引:它 是一种特殊的唯一索引,不允许有空值。
全文索引:仅可用于 MyISAM 表,针对较大的数据,生成全文索引很耗时好空间。
组合索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。
- 主键索引:
主键索引可以做外键
一个表最多只能创建一个主键索引,但可以创建多个唯一索引。 - 唯一索引:
被索引的数据列不允许包含重复的值
在执行CREATE TABLE语句时可以创建索引,也可以单独用CREATE INDEX或ALTER TABLE来为表增加索引。
- 新建表中添加索引
① 普通索引 create table t_dept( no int not null primary key, name varchar(20) null, sex varchar(2) null, info varchar(20) null, index index_no(no) )
- 在已建表中添加索引
① 普通索引 create index index_name on t_dept(name);
- 以修改表的方式添加索引
① 普通索引 alter table t_dept add index index_name(name);一条sql怎么优化?
- explain分析sql语句,查看执行计划,分析索引是否用上,分析扫描行数
- 避免使用 SELECt * FROM TABLE,用具体的列替换,避免全表扫描。
- 避免在WHERe子句中对字段进行表达式操作,会导致引擎放弃使用索引而进行全表扫描。
- 避免在WHERe子句中对字段进行函数操作,会导致引擎放弃使用索引而进行全表扫描。
explain解释:
| 字段 | 解释 |
|---|---|
| ID | 每个select子句的标识ID |
| select_type | select语句的类型 |
| table | 表名 |
| type | 当前表内访问的方式(下面详解) |
| possible_keys | 可能使用到的索引 |
| key | 经过优化器评估最终使用的索引 |
| key_length | 使用到的索引长度 |
| ref | 引用到上一个表的列 |
| rows | 最终记录索引要扫描经过的记录数 |
| filtered | 表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。 |
| Extra | 下面详解 |
Type:
| 值 | 解释 |
|---|---|
| all | 全表扫描,MySQL遍历全表查询匹配行 |
| index | 索引全扫描,MySQL遍历整个索引查找匹配行 |
| range | 索引范围查找,常见于< <= > >= bweteen |
| ref | 使用非唯一索引扫描或唯一索引的前缀扫描,返回某个单独值的记录行,ref还经常出现在join操作中 |
| const,system | 单表中最多的一个匹配行,查询起来很迅速,这个匹配行中的其他值可以被OPTIMIZER在当前查询中当作常量处理 |
| NULL | 不适用访问表或者索引,直接得到结果 |
| ref_or_null | 类似于ref区别条件中包含对NULL查询 |
| index_merge | 索引合并优化 |
| unique_subquery | IN的后面是一个查询主键字段的子查询 |
| index_subquery | 与unique_subquery类似,区别在IN后面是查询非唯一索引的子查询等 |
Extra:
| 值 | 解释 |
|---|---|
| Using index | 表示这个语句使用了覆盖索引,选择了索引a,不需要回表; |
| Using temporary | 表示使用了临时表; |
| Using filesort | 表示需要排序; |
| Deleting all rows | 对于DELETE,一些存储引擎(如MyISAM)支持一种处理方法,可以简单而快速地删除所有的行,如果引擎使用此优化,则会显示此值。 |
| Using index | 表示这个语句使用了覆盖索引,选择了索引a,不需要回表; |
| Using where | 表示MySQL将对提取的条件进行过滤,过滤条件字段无索引; |
| Using join buffer(Block Nested Loop),Using join buffer(Batched Key Access) | Block Nested - Loop Join算法,将外层循环的行/结果集存入join buffer中,内层循环的每一行与整个buffer中的记录做对比,从而减少内层循环的次数。优化器管理参数optimizer_switch中的block_nested_loop参数控制着BNL是否被用于优化器。默认条件下是开启的,若设置为OFF,优化器在选择join方式的时候会选择NLJ(Nested Loop Join)算法。 |
第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。
第二范式(2NF):所有的非主键列必须完全依赖于主键,不允许有不依赖于主键的列。
第三范式(3NF):所有的非主键列必须直接依赖于主键,不允许有间接依赖于主键的列。



