没有索引会怎么样
-
数据库中的数据最终是存储在磁盘上的。
-
mysql服务器,本质上是内存进程,CURD操作全都是在内存中进行的—索引也是如此。
所以,需要将数据从磁盘读进内存,才能进行操作。 -
如果没有索引,表中的数据会向链表一样前后相连,查找某个数据的方式是线性查找效率很低,这是一方面;另一方面需要将数据从磁盘全部读入内存,IO次数多,这是另一方面导致查找效率低的原因。
-
提高算法效率: 1. 组织数据的结构 2.算法本身
总结:如果没有索引就会导致查找效率很低。
磁盘
从硬件方面理解为什么没有索引效率低。
内存与磁盘IO效率低的主要原因
是两者IO效率低的原因,就是磁盘定位数据所在的位置花费的时间比较久,其实两者进行数据传送的效率挺高。
磁盘定位数据所在的位置:确定盘面–>确定柱面(磁道)–>确定扇区。
内存与磁盘IO的基本单位
一般是4KB
MySQL,OS和磁盘的关系
MySQL与磁盘的交互的基本单位是16kb
建立共识
- 总结:
1.page的大小为16kb,也是MySQL与磁盘交互的基本单位。
2.MySQL申请了Buffer Pool充当缓存
3.提高效率,要减少系统与磁盘的IO次数
4.OS与磁盘的IO的基本单位是4kb
一个现象和结论
Create Table: CREATE TABLE `user` (
`id` int(11) NOT NULL,
`age` int(11) NOT NULL,
`name` varchar(16) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 --默认就是InnoDB存储引擎--插入多条记录,注意,我们并没有按照主键的大小顺序插入哦
mysql> insert into user (id, age, name) values(3, 18, '杨过');
Query OK, 1 row affected (0.01 sec)
mysql> insert into user (id, age, name) values(4, 16, '小龙女');
Query OK, 1 row affected (0.00 sec)
mysql> insert into user (id, age, name) values(2, 26, '黄蓉');
Query OK, 1 row affected (0.01 sec)
mysql> insert into user (id, age, name) values(5, 36, '郭靖');
Query OK, 1 row affected (0.00 sec)
mysql> insert into user (id, age, name) values(1, 56, '欧阳锋');
Query OK, 1 row affected (0.00 sec)
现象
向一个具有主键的表中无序的插入数据但数据会自动排序。
谁做的?
MySQL做的
理解MySQL中的page
- MySQL中一定需要,且存在着大量的page–>MySQL必须对这些page进行管理
- 如何管理?—>先描述,再组织
- page不仅仅是一个内存块,其中必须写入对应的管理信息。
struct page
{struct page* next;struct page* prev;char buffer[NUM];
}
在Buffer Pool中对page进行了建模
为什么?–>支持高效查找
方便引入页内目录
-
数据是链式存储的,查找数据是线性查找–>提高查找效率的方法
1.page内
在单个page中引入目录,引入目录的前提是这个数据时有序的,这个可以类比一下看书时的目录
这样就可以加快在单个page中的查找效率了
2.page间
如果有很多个page呢?page间也是用链前后链接的,一定不能用线性查找,查找效率太低了;另一方面将这些page加载进内存IO次数很高。
-
引入页目录
页目录中只有索引(4 byte)和指针 (8byte)
(16kb1024byte)/ (4 byte+8 byte) = 1365 个
每个页目录大约可以管理1365个页
如果page比想象中的更多,那么就在加一层页目录
这样大约能管理100 万(13651365)页 ,大约是 16GB(100万*16 kb)的数据
索引的实现形式
常使用的是B+树,有的使用哈希
B+树的特点:
-
叶子节点保存数据,路上节点没有数据,即非叶子节点不要数据,只要目录项。
1.1 路上节点没有数据–>可以存更多的目录项;目录页可以管理更多的叶子page;这棵树一定矮胖 -->矮途径的节点减少–>找到目标数据只需要更少的page,IO次数减少,在IO层面上提高了查找的效率。
1.2 每一个节点都有目录项,可以大大提高检索效率
以上的两点整体提高了搜索的效率。
2.叶子节点全部用链表前后关联起来
这是B+树的特点比较希望进行范围查找
- 上面的图就是 MySQL innodb下的索引结构–>一般在该结构下进行CURD操作。
- 没有主键,也是这样吗?
是的,MySQL会自动形成一个默认的,隐藏的主键,但查找数据时,只能进行线性查找。
其他数据结构为什么不行?
- 链表:线性遍历,查找效率低。
- 二叉搜索树: 可能退化为链表,线性查找,效率低。
- AVL树和红黑树:相较于B+树,树瘦高–>意味着IO次数更多
- 哈希:不支持区间查找
- B-树 vs B+树
B树中的节点中都有数据,IO相较于B+树更多
B树中叶节点没有相连,意味着B树不支持范围查找。
聚簇索引 vs 非聚簇索引
聚簇索引
数据和索引不分离
Inoodb就是聚簇索引,
非聚簇索引
数据和索引分离
叶节点中存放的不是数据,而是地址(指向数据)
辅助(普通)索引
聚簇索引的普通索引
在建立一张索引和数据表,索引是指定列的索引,而数据则是对应的主键信息。
通过普通索引查找信息的流程是,通过普通索引找到主键值,再用找到的主键值查找主索引表就可以了。
聚簇索引的普通索引
再建立一张普通索引表,修改叶节点指向的地址就可以了。
索引操作
索引主要有三种形式:主键,唯一键,普通索引
创建主键索引
创建表时
给没有主键的表添加
删除主键
查询索引
-
show keys from 表名
-
show index from 表名
-
desc 表名
添加唯一键
唯一键也可以看做普通索引,那么就会创建一个新的索引表。
删除唯一键
删除唯一键后,那张关于唯一键的索引表也被删除了。
添加普通索引
新增了普通索引的索引表
- 创建一个自己命名的普通索引表
删除普通索引
同时删除普通索引的索引表结构
复合索引
- 复合索引就是多列充当索引。
创复合索引的第一列为key,复合索引可以直接通过key值查找,直接返回复合索引中其他列的值,不需要在去查一遍主索引表。这也就是索引覆盖–>覆盖的是主键值。
创建复合索引
看上去是三张索引表,实际上是两张。一张是主键索引表,另一张是复合索引表
全文索引
- 只能在MyIsam中使用
- 主要的应用场景是查询一列中的某些字段
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
)engine=MyISAM;INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...'),
('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial we will show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');
创建全文索引
-
查询有没有database数据
这种是没有使用索引的,如果数据量很大,那么这种方式会很慢。 -
如何使用全文索引