前言
该文章所用到的表结构:
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for svip -- ---------------------------- DROP TABLE IF EXISTS `svip`; CREATE TABLE `svip` ( `vip_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '会员编号', `vip_name` varchar(10) NOT NULL DEFAULT '' COMMENT '会员姓名', `vip_cardID` varchar(18) NOT NULL COMMENT '会员身份证号码', `vip_iphone` varchar(10) NOT NULL COMMENT '会员电话', `vip_address` varchar(50) NOT NULL COMMENT '会员住址', `vip_mark` text NOT NULL COMMENT '会员备注信息', PRIMARY KEY (`vip_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
来源
MySQL索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存,如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录。表里面的记录数量越多,这个操作的代价就越大,如果作为搜索条件的列上已经创建了索引,M y S Q L 无 需 扫 描 任 何 记 录 即 可 迅 速 得 到 目 标 记 录 所 在 的 位 置 \color{#FF0000}{MySQL无需扫描任何记录即可迅速得到目标记录所在的位置}MySQL无需扫描任何记录即可迅速得到目标记录所在的位置。如果表中有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍。
在使用like的时候,如果使用‘%%’,会不会用到索引呢?
EXPLAIN SELECT * FROM svip WHERE vip_id LIKE '%1%'
查询结果possible_key为空,表示没有用到索引:
使用到了主键索引:
综上,MySQL在使用like查询的时候只使用后面的%时,才会使用到索引。
索引分类:
PRIMARY 主键:唯一且不能为空。
INDEX:普通的索引。
UNIQUE 唯一索引:不允许有重复。
FULLTEXT 全文索引:用于在一篇文章中,检索文本信息的。
各有什么区别?各适用于什么场合?
举个例子来说,比如你在为某商场做一个会员卡的系统,这个系统有一张会员表,表结构如上前言,各字段含义:
会员编号 INT
会员姓名 VARCHAR(10)
会员身份证号码 VARCHAR(18)
会员电话 VARCHAR(10)
会员住址 VARCHAR(50)
会员备注信息 TEXT
那么这个会员编号,作为主键,使用 PRIMARY
会员姓名如果要建索引的话,那么就是普通的 INDEX
会员身份证号码如果要建索引的话,那么可以选择 UNIQUE (唯一的,不允许重复)
会员备注信息如果要建索引的话,可以选择 FULLTEXT,全文搜索。
不过 FULLTEXT 用于搜索很长一篇文章的时候,效果最好,用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。MySQL从3.23.23版开始支持全文索引和全文检索,在MySQL中,全文索引的索引类型为FULLTEXT。全文索引可以在CHAR、VARCHAR或者TEXT类型的列上创建。它可以通过CREATE TABLE命令创建,也可以通过ALTER TABLE或CREATE INDEX命令创建。对于大规模的数据集,通过ALTER TABLE(或者CREATE INDEX)命令创建,全文索引要比把记录插入带有全文索引的空表更快。
MySQL添加索引方法
索引算法:
我们在MySQL中常用两种索引算法BTree和Hash,两种算法检索方式不一样,对查询的作用也不一样。
BTree索引是MySQL数据库中最常用的索引算法,因为它不仅可以被用在=,>,>=,<,<=和between这些比较操作符上,而且还可以用于like操作符,只要它的查询条件是一个不以通配符开头的常量。
Hash索引只能用于对等比较,例如“=”,“IN”,“<=>”(等价于=)操作符。由于是一次定位数据,不像BTree索引需要从根节点到枝节点,最后才能访问到页节点这种多次访问,所以检索效率远高于BTree索引,但Hash索引仅仅能满足“=”,“IN”,“<=>”查询,不能使用范围查询。
B t r e e 索 引 效 率 远 小 于 H a s h 索 引 , 但 作 用 范 围 广 , 只 要 不 是 前 置 通 配 符 即 可 使 用 。 \color{#FF0000}{Btree索引效率远小于Hash索引,但作用范围广,只要不是前置通配符即可使用。}Btree索引效率远小于Hash索引,但作用范围广,只要不是前置通配符即可使用。
例如这样也使用了索引:
Hash索引的几个缺点以至于工作中不经常使用:
Hash索引仅仅能满足“=”,“IN”,“<=>”查询,不能使用范围查询
联合索引中,Hash索引不能利用部分索引键查询
Hash索引无法避免数据的排序操作
Hash索引任何时候都不能避免表扫描
Hash索引遇到大量Hash值相等的情况后性能并不一定会比BTree高
小知识:
"<=>"符号其实在数学中叫做“等价于”,代表”推理中左边可以推出右边,右边也可推出左边”的意思,P=>Q:若P则Q,P<=Q:若Q则P,P<=>Q:若P则Q且若Q则P。接下来看一下我的测试,在库中建一张test表,建一个hash索引num1_hash。
表结构跟数据:
SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for test -- ---------------------------- DROP TABLE IF EXISTS `test`; CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `num1` int(11) DEFAULT NULL, `num2` int(11) DEFAULT NULL, `num3` decimal(14,2) DEFAULT NULL, PRIMARY KEY (`id`), KEY `num1_hash` (`num1`) USING HASH ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; -- ---------------------------- -- Records of test -- ---------------------------- INSERT INTO `test` VALUES ('1', '1', '1', '1.00'); INSERT INTO `test` VALUES ('2', '2', '2', '2.00'); INSERT INTO `test` VALUES ('3', '3', '3', '3.00'); INSERT INTO `test` VALUES ('4', '4', '4', '4.00'); INSERT INTO `test` VALUES ('5', '5', '5', '5.00');
查询结果:
接下来再看看hash索引对<,<=,>,>=符号是否支持:
可以看出在<=2与<3是能命中索引的,在<=3与<4是全表扫描,所以<,>等符号也不是完全不能命中索引,跟btree测试结果一样,但是对查询的优化有没有用还没有研究过,后续会继续研究一下进行补充。