Mysql是一个程序员必须要学会的一种语言,很多人新手小白虽然会基础使用Mysql,但是不明白其索引设计的原理。
要先明白什么是索引,索引是高效帮助MySql获取数据的数据结构。
最近我的项目就经常需要使用索引进行调优,因此了解了相应知识,此次我就将自己理解的整理起来。
如图所示,二叉树的结构是,以根节点为基准,比较小的放右边,大的放左边。
因此当搜索时,根据数据一个一个搜索,效率相对比较慢
如图所示,同样的数据,二叉树和红黑树对比的数据结构却不一样。
黑色为根节点,红色为叶节点,红黑树的特点就是能够平衡数据。其原理与二叉树一样,但是多了一个平衡数据的算法,因此红黑树又称二叉平衡树。
当我们看到这里肯定会有疑问,既然红黑树这么好用,为什么 索引最终底层结构是B-Tree,为什么呢?
原因很简单,其实我们在公司真实使用的数据绝对不止展示的数据可言的,基本都上千万,上亿的数据量。
如果用红黑树,最后其实也和用二叉树没什么区别。
其实涉及到一个词, 深度,我们以二叉树举例,我们看到的数据量可以换成2 ^ n,而n就是深度,也就是所谓的高度;
当我们的数据量上千万甚至上亿,那么他的深度是多少?如果刚好我们要查询的数据恰好处在极端位置,那查询效率也不高!而B树就刚好解决这个问题!
B-Tree是优化红黑树改的高度,而进行横向扩展,致使结构深度比较小,查询效率也比较快。
若设置索引时除了BTREE还有一个HASH这个索引。
底层选择Hash表存储时,会将索引的每个字段做HASH运算,得到一个结果值,将这个结果值以及对应的数据磁盘地址指针存储到HASH映射表里。只要将查询条件做Hash运算,得到结果直接去映射表里查找。
Mysql虽然提供很多数据存储引擎,但我们接触最多还是两种存储引擎MylSAM和InnoDB,此次也只介绍这两种存储引擎。
MylSAM是早期的版本(MYSQL 5.5.5之前)默认的存储引擎,特点是:
MylSAM对应的文件有三个:.frm、.MYI和*.MYD(MYI存的是索引值,MYD存的是数据值)
总的来说,MylSAM比较适合用在查询为主的业务。
MylSAM一般索引是采用B树和B+树:
叶子节点data域存放的是数据的物理地址,索引结构和真正的数据结构其实是分开存储的(索引和数据是分开的)。
目前新版本已经将InnoDB作为默认的存储引擎,相比与MylSAM,InnoDB有更完善的事务支持,也支持外键和行级锁。特点有:
InnoDB对应的文件有两个:*.frm和 *.ibd(ibd里索引和数据都存在一起)。
索引实现
至于还有几种存储引擎,比较少用也比较少了解,在这里就简单介绍,MEMORY/HEAP存储引擎,该引擎支持HASH和BTREE索引。
我们知道Mysql的索引主要分为两种:
两者的区别:聚簇索引是索引文件和数据文件放在一起为一个文件,因此查询效率比较高;非聚簇索引是索引文件和数据文件分开连个文件。
因此InnoDb是聚簇,MylSAM是非聚簇。
这里引用‘王下邀月熊’的图片
而索引的实际应用,也是我们常用的几种:
以上都是我们比较熟知的一些Mysql索引。
当然也有一些我们所不太熟知的索引,比如空间索引 SPATIAL,原本只有在MylSAM引擎上才能使用,在MySQL5.7版本后InnoDB也开始支持。空间索引是对空间数据类型(坐标,地理位置等)的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。==创建空间索引的列,必须将其声明为NOT NULL。==在这里就不多介绍了!
(1)直接创建索引
CREATE INDEX index_name ON table(column(length))
(2)修改表结构的方式添加索引
ALTER TABLE table_name ADD INDEX index_name ON (column(length))
(3)创建表的时候同时创建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER NOT NULL ,
`content` text CHARACTER NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
INDEX index_name (title(length))
)
(4)删除索引
DROP INDEX index_name ON table
(1)直接创建索引
CREATE UNIQUE INDEX indexName ON table(column(length))
(2)修改表结构
ALTER TABLE table_name ADD UNIQUE indexName ON (column(length))
(3)创建表的时候直接指定
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER NOT NULL ,
`content` text CHARACTER NULL ,
`time` int(10) NULL DEFAULT NULL ,
UNIQUE indexName (title(length))
);
主键索引是一种特殊唯一索引,因为主键索引必须是主键,一个表只有一个主键,也不允许为空。
建表时就会自动创建主键索引。
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) NOT NULL ,
PRIMARY KEY (`id`)
);
联合索引就是将表里的几个字段建立一个组合索引
ALTER TABLE `table` ADD INDEX index_x_y (xxxx,yyyy);
而这样的组合索引,其实就相当于建立两个索引:
—xxxx,yyyy
—xxxx
至于上面提到的"最左前缀",简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引,如下面的几个SQL所示:
–使用到上面的索引
SELECT * FROM table WHREE xxxx='xxxx' AND yyyy='yyyy';
SELECT * FROM table WHREE xxxx='xxxx';
–不使用上面的索引
SELECT * FROM table WHREE yyyy='yyyy';
(1)创建表时创建全文索引
create table index_text(
id int(11) NOT NULL AUTO_INCREMENT,
content text NOT NULL,
tag varchar(255),
PRIMARY KEY (id),
indextext KEY index_content (content,tag) // 创建联合全文索引列
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
(2)在已存在的表上创建全文索引
create indextext index index_content on index_text(content,tag);
(3)修改表结构添加全文索引
alter table index_textadd indextext index content_tag_fulltext(content,tag);
使用全文索引
和常用的模糊匹配使用 like + % 不同,全文索引有自己的语法格式,使用 match 和 against 关键字,比如:
select * from fulltext_test where match(content,tag) against('xxx xxx');
注意: match() 函数中指定的列必须和全文索引中指定的列完全相同,否则就会报错,无法使用全文索引,这是因为全文索引不会记录关键字来自哪一列。如果想要对某一列使用全文索引,请单独为该列创建全文索引。
MySQL学习必须要从底层的存储引擎和索引开始学起,之后才会更好的了解如何sql调优。不管工作还是面视,都是需要学习的!