赞
踩
注:索引深入部分参考:https://www.cnblogs.com/rickiyang/p/13559507.html
索引的概念
索引的分类
举栗
/* SQLyog Ultimate v12.09 (64 bit) MySQL - 5.7.11-log : Database - educ ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`educ` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `educ`; /*Table structure for table `course` */ DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `Cno` BIGINT(20) NOT NULL, `Cname` VARCHAR(20) DEFAULT NULL, `Cpno` VARCHAR(10) DEFAULT NULL COMMENT '先行课', `Ccredit` VARCHAR(10) DEFAULT NULL, PRIMARY KEY (`Cno`), =========================> 主键索引 UNIQUE KEY `Cname` (`Cname`) ====================> 唯一索引 ) ENGINE=INNODB DEFAULT CHARSET=utf8;==============> 数据库引擎 /*Data for the table `course` */ INSERT INTO `course`(`Cno`,`Cname`,`Cpno`,`Ccredit`) VALUES (1,'数据库','5','4'),(2,'数学',NULL,'2'),(3,'信息系统','1','4'),(4,'操作系统','6','3'),(5,'数据结构','7','4'),(6,'数据处理',NULL,'2'),(7,'PASCAL语言','6','4'); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
增加索引举栗
建立表的时候
alter table add index xxx
create index on xxx table(xxxCol)
ALTER TABLE educ.student ADD FULLTEXT INDEX
Sage(
Sage);
SHOW INDEX FROM student
写函数插入100万数据
DELIMITER $$ CREATE FUNCTION mock_data() RETURNS INT BEGIN DECLARE num INT DEFAULT 1000000; DECLARE i INT DEFAULT 1; WHILE i<=num DO INSERT INTO USER(`name`,`email`,`phone`,`password`,`age`) VALUES( CONCAT('用户',i), '2589165806@qq.com', CONCAT('17',FLOOR(RAND()* 999999999)), UUID(), FLOOR(RAND() * 100)); SET i = i + 1; END WHILE; RETURN i; END SELECT mock_data();
耗时41s
EXPLAIN
测试select查询:EXPLAIN SELECT * FROM USER WHERE NAME = '用户99999';
根据name字段创建索引:CREATE INDEX id_user_name ON USER(`name`)
再次测试查询
DELIMITER $$ CREATE FUNCTION mock_data() RETURNS INT BEGIN DECLARE num INT DEFAULT 1000000; DECLARE i INT DEFAULT 1; WHILE i<=num DO INSERT INTO USER(`name`,`email`,`phone`,`password`,`age`) VALUES( CONCAT('用户',i), '2589165806@qq.com', CONCAT('17',FLOOR(RAND()* 999999999)), UUID(), FLOOR(RAND() * 100)); SET i = i + 1; END WHILE; RETURN i; END SELECT mock_data(); SELECT * FROM USER; SELECT * FROM USER WHERE NAME = '用户99999'; # 总耗时 : 0.692 sec EXPLAIN SELECT * FROM USER WHERE NAME = '用户99999'; # 创建索引 CREATE INDEX id_user_name ON USER(`name`) # 创建索引之后的查询 SELECT * FROM USER WHERE NAME = '用户99999'; # 总耗时 : 0.009 sec EXPLAIN SELECT * FROM USER WHERE NAME = '用户99999'; # 1rows
注意
这里有一个很重要的一点就是 B+ 树的非叶子节点不保存数据,只有索引。
也就是所有的数据全放在最底层的叶子节点上,而且最底层的叶子节点是按照从小到大 指针串起来的
一棵 m 阶的 B+ 树和 m 阶的 B 树的异同点在于:
对于 B 树和 B+ 树来说,两种数据结构都是为了减少磁盘 I/O 读写过于频繁而生,本身节点的个数是有限的,采用多叉结构就是为了让每一层放尽可能多的节点以此来降低整棵树的高度。但是为什么 InnoDB 索引结构最终选择了 B+ 树而不是B 树呢?
B+ 树的磁盘读写代价更低
B+ 树内部非叶子节点本身并不存储数据,所以非叶子节点的存储代价相比 B 树就小的多。存储容量减少同时也缩小了占用盘块的数量,那么数据的聚集程度直接也影响了查询磁盘的次数。
B+ 树查询效率更加稳定
树高确定的前提下所有的数据都在叶子节点,那么无论怎么查询所有关键字查询的路径长度是固定的。
B+ 树对范围查询的支持更好
B+ 树所有数据都在叶子节点,非叶子节点都是索引,那么做范围查询的时候只需要扫描一遍叶子节点即可;而 B 树因为非叶子节点也保存数据,范围查询的时候要找到具体数据还需要进行一次中序遍历。
在 MYSQL 中索引属于存储引级别的概念,存储引擎不同,索引的实现方式也不一样。
索引的类型
聚集(主键)索引
二级索引:除了主键索引之外的索引,二级索引B+树的叶子节点存储的不是数据,而是主键索引 对应的 主键值(也就是主键叶子节点的指针),查数据的时候,进行两次B+ 树查找
覆盖索引:简单来说就是只查询索引就能获取到数据不必再回表查询,换句话说要查询的列已经被索引列覆盖。
联合索引:对多个字段建立一个索引,有一个 左前匹配原则 需要注意,也就是确保查询走的是 联合索引而不是扫全表
缺点
磁盘空间占用。这个对于当前磁盘比买菜还便宜的硬件大通货时代其实算不上问题,但是要注意的是如果当前 MySQL 服务所在的机器有很多的大表,并且还创建了每一种可能的组合的索引,那么索引文件提及的增长可能超乎你的想象。
维护索引对更新类操作所带来的耗时。当对索引涉及到的列做更新或者新增操作时都会去维护相关的索引,这里也是一个耗时的点,所以索引不在多,而在精。
参考:https://blog.codinglabs.org/articles/theory-of-mysql-index.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。