MySQL索引与锁的机制 三 MYSQL 索引机制

                                                          MYSQL 索引机制


数据库的检索过程:

  • Mysql 的 基本存储 结构是 ,  各个数据页 组成一个双向的 链表,单个数据页中的记录 又组成一个 单向的 链表
  • 每个数据 页 都会为 存储的记录 生成一个页目录, 在通过 主键(索引) 查找 某条记录时, 可在 页目录中 使用 二分法 快速定位 对应的 槽,  让后再 遍历 该槽对应 分组中的 记录 即可 快速 找到 指定的 记录数据。 以 非主键 作为 搜索条件 只能从最小 记录开始 依次 遍历 单链表中的每条记录 即:

1. 遍历双向链表,找到所在的页

2. 从所在的页中 查找相应的 记录,  由于不根据 主键查询, 只能遍历所在页的 单链表当数据量过大时(比如上亿条) 结果会很慢         

  • select * from users where id              = 10010      主键(索引)

  • select * from users where username = 'tom'        非主键(无索引)

 

 


 

 

索引与创建索引:

什么是索引:

  • 索引 是对数据库 表中的一列或多列的值 进行排序的 一种 存储结构(B+树), 可以加快数据库的检索速度

  • 索引 的作用相当于数 的 目录,可以根据目录中的 页码快速 找到 所需的内容

  • 没有使用 索引 需要遍历 双向链表来 定位 对应的页,  现在通过索引 就可以很快定位 到对应的页上, 索引 底层结构就是 B+ 树(也有 hash 表), B+ 树作为 树的 一种实现, 能够让我们 很快底查找出对应的记录

索引的创建:

CREATE TABLE users(
    userid INT NOT NULL auto_increment  PRIMARY KEY,
    username VARCHAR(20)  NOT NULL,
    pwd VARCHAR(16),
    INDEX idx_username(username)                 #创建索引

    #INDEX idx_username(username(10))         #前 10个字符作为索引 
)


ALTER TABLE users ADD INDEX idx_username(username)                #可重复的索引
ALTER TABLE users ADD UNIQUE idx_username(username)             #不可重复的索引
ALTER TABLE users ADD PRIMARY KEY idx_username(username)   #不可重复的索引, 表中数据的 唯一标识


DROP INDEX  idx_username ON users                                           #删除索引

ALTER TABLE users DROP INDEX idx_username                          #删除索引
ALTER TABLE users DROP PRIMARY KEY                                    #删除索引

SHOW INDEX FROM users
SHOW KEY FROM users

联合索引:

CREATE * FROM users(
    userid INT NOT NULL,
    username VARCHAR(20) NOT NULL,
    pwd VARCHAR(20) NOT NULL,
    phone VARCHAR(20),
    INDEX idx_username_pwd(username, pwd, phone)                        #指定 联合索引
)

SELECT * FROM users WHERE username = 'tom' AND pwd = 'malocfree'

 

  • 相当于创建了 (username, pwd, phone),(username, pwd),(username) 三个索引
  • 最左匹配:遇到范围查询(>, <, between, like, 左匹配等)就不能进行 一步匹配, 后续退化为 线性查找; 如为 一个表 创建 联合索引 (a,b,c,d), 查询 select * from mytable where a = 1 and b = 2 and c > 3 and d = 4,  则会 一次 命中   a, b,c  却无法命中 d
  • 联合索引 (a,b,c,d)   查询条件 c > 7 and b = 5 and a = 1 and d < 3 与 a = 1 and c > 7 and b =5 and d <3 等顺序都是可以的。 Mysql 会 自动优化 为  a = 1 and b =5 and c > 7 and d < 3,  依次命中 a b c

 

 

 


索引注意事项:

适合建立索引的情况:

  1. 表的主 关键字,自动建立唯一索引

  2. 表的字段唯一约束

  3. 直接条件查询 的字段

  4. 查询中与 其他表关联的字段

  5. 查询中排序的字段

  6. 查询中 统计 或者 分组的 字段(max 和 group by 的字段)

不适合建立索引的情况:

  1. 表记录太少(一般索引表 与 数据表 不在同一个数据库, 需要先访问索引表 在通过 索引表访问 数据表)

  2. 经常插入, 删除, 修改的 表 字段(B+树 平衡调整)

  3. 数 经常 重复 且 分布均匀 的表 字段(b比如 性别, 星期几 等等)

 

索引并不总是 最好用的工具, 总的来说  只有当  索引帮助 存储引擎 快速 查找到记录 带来的好处 大于 其带来的 额外工作时。 索引才是 有效的对于非常小的表, 大部分情况下 全表扫描 更加高效。 对于 中到大型的表, 索引就非常有效了。 但对于 特大型的表, 建立 和 使用索引的 代价 将随之增加。 这种情况下 则需要一种技术 可以 直接区分出查询 需要的 一组数据, 而不是 一条记录 一条记录的 匹配, 例如: 可以使用分区技术

  根据 每天 把数据表 分区

CREATE TABLE IF NOT EXISTS mytable(
	id INT NULL auto_increment PRIMARY KEY,
	mname VARCHAR(20),
  pwd VARCHAR(20)	
) PARTITIONED BY (ymd date)

 

 

 


 

 

聚簇索引 与 非聚簇索引:

● 聚簇索引

以主键 创建的索引, 在叶子结点处  储存的记录 包含了表中所有的列(key- value)

●  二级索引(非聚簇索引)

非主键 创建 的索引,在叶子结点 处 储存的记录内容是 主键,使用非 聚簇 索引 查询数据时,拿到叶子结点的 主键, 再去 聚簇索引的 B+树 上查询 想要的数据(这个过程叫做 回表)

每增加 一种索引, 就会新建一颗 对应的 B+ 树, 彼此独立的树

●MyISAM  单独为表的 主键常见一个  B+ 树的索引, 在 B+ 树 的叶子 结点中 存储的不是 完整的用户记录, 而是主键值 + 行号的 组合。 也就是 先通过 索引 找到 对应的 行号, 在通过行号 去找 对应的记录。 两次

● InnoDB 存储引擎 只需要 根据 主键值 对应 聚簇 索引 进行 一次查找 即可 找到对应的记录数据, MyISAM  中需要进行 一次回表操作, 意味着MyISQL  中建立的 索引 全部是二级的

 

 


 

 

Hash 索引:

● 哈希索引就是 采用 哈希算法, 把键值换算 成行的哈希值, 检索时 不需要 类似 B+ 那样 从根节点到 叶子结点 逐级查询, 只需要 一次哈希 算法 即可立刻 定位到 相应的位置,速度快

● 局限性

  1. 无法利用 索引 完成排序

  2. 不支持 最左匹配原则

  3. 在有大量重复键值的情况下, 存在 hash 冲突 效率低

  4. 不支持 匹配范围

主流数据库  采用  B+ 树索引  InnoDB 使用的是 自适应 哈希 索引, 即会 根据表的 使用情况 自动为 表生成 哈希索引,不能 人为干预

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nicepainkiller

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值