索引
什么是索引?
索引是帮助Mysql提高获取数据的数据结构,换一句话讲就是“排好序的快速查找的数据结构”。
一.索引的分类
MySQL主要的几种索引类型:1.普通索引、2.唯一索引、3.主键索引、4.组合索引、5.全文索引。
1.普通索引
是最基本的索引,它没有任何限制。
2.唯一索引
与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一
3.主键索引
是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。
主键索引和唯一索引的区别:
主键必唯一,但是唯一索引不一定是主键;
一张表上只能有一个主键,但是可以有一个或多个唯一索引。
4.组合索引
一个索引包含多个列,实际开发中推荐使用复合索引。
复合索引主要特点:
如果我们创建了(name, age,xb)的复合索引,那么其实相当于创建了(name, age,xb)、(name, age)、(name)三个索引,这被称为最佳左前缀
特性。因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。
MySQL INNodb建立复合索引 a,b,c;那么 查询条件 where a =xxx and c= xxx 能用到索引嘛?
回答:可以。
注意事项:
1、对于复合索引,在查询使用时,最好将条件顺序按找索引的顺序,这样效率最高;
select * from table1 where col1=A AND col2=B AND col3=D
2、如果使用 where col2=B AND col1=A 或者 where col2=B 将不会使用索引
5.全文索引
全文搜索的索引。
FULLTEXT 用于搜索很长一篇文章的时候,效果最好。用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。
综合小案例理解:
比如你在为某商场做一个会员卡的系统。
这个系统有一个会员表
有下列字段:
会员编号 INT
会员姓名 VARCHAR(10)
会员身份证号码 VARCHAR(18)
会员电话 VARCHAR(10)
会员住址 VARCHAR(50)
会员备注信息 TEXT
那么这个 会员编号,作为主键,使用 PRIMARY
会员姓名 如果要建索引的话,那么就是普通的 INDEX
会员身份证号码 如果要建索引的话,那么可以选择 UNIQUE (唯一的,不允许重复)
会员备注信息 , 如果需要建索引的话,可以选择 FULLTEXT,全文搜索。
不过 FULLTEXT 用于搜索很长一篇文章的时候,效果最好。
用在比较短的文本,如果就一两行字的,普通的 INDEX 也可以。
二.索引的优点缺点
优点:
(1)提高数据检索的效率,降低数据库IO成本。
(2)通过索引对数据进行排序,降低数据的排序成本,降低CPU的消耗。
缺点:
(1)当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
(2)索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大
三、是否需要创建索引
1:什么时候需要创建索引
(1.主键自动创建唯一索引
(2. 较频繁的作为查询条件的字段。
(3.查询中排序的字段,查询中统计或者分组的字段。
2:什么时候不需要创建索引
(1.表记录太少的字段
(2.经常增删改的字段
(3.唯一性太差的字段,不适合单独创建所以。即使频繁作为查询条件 比如性别,民族,政治面貌(可能总共就是那么几个或几十个值重复使用的字段)
四、索引的注意事项(优化)
1.尽量少使用模糊查询,如果要使用那么,通配符%可以出现在结尾,不能在开头。
如:name like ‘张%’ ,索引有效
而:name like ‘%张’ ,索引无效,全表查询
2:or 会引起全表扫描
3:不要使用NOT、!=、NOT IN、NOT LIKE等
4.尽量少使用select*,而是根据需求来选择需要显示的字段
5.索引不会包含有null值的列
只要列中包含有null值都将不会被包含在索引中,复合索引中只要有一列含有null值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为null。
6.不要在列上进行运算,这将导致索引失效而进行全表扫描
7.使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作.
8、union并不绝对比or的执行效率高
我们前面已经谈到了在where子句中使用or会引起全表扫描,一般的,我所见过的资料都是推荐这里用union来代替or。事实证明,这种说法对于大部分都是适用的。
有一点不适用:如果or两边的查询列是一样的话,那么用union则反倒和用or的执行速度差很多,虽然这里union扫描的是索引,而or扫描的是全表。
1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' or fariqi=''2004-2-5''
用时:6423毫秒。扫描计数 2,逻辑读 14726 次,物理读 1 次,预读 7176 次。
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''
union
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-2-5''
用时:11640毫秒。扫描计数 8,逻辑读 14806 次,物理读 108 次,预读 1144 次。
五、索引方式(结构)
mysql有两种所以方式:Hash和BTree。
Hash索引
所谓Hash索引,当我们要给某张表某列增加索引时,将这张表的这一列进行哈希算法计算,得到哈希值,排序在哈希数组上。所以Hash索引可以一次定位,其效率很高,而Btree索引需要经过多次的磁盘IO。
因为Hash索引比较的是经过Hash计算的值,所以在= in <=>(安全等于的时候)塔的效率是非常,但我们开发一般会选择Btree,Hash会存在如下一些缺点。
(1)Hash索引仅仅能满足"=","IN"和"<=>"查询,不能使用范围查询。
由于 Hash 索引比较的是进行 Hash 运算之后的 Hash值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样。
(2)Hash 索引无法被用来避免数据的排序操作。
由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash值,而且Hash值的大小关系并不一定和 Hash运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;
(3)Hash索引不能利用部分索引键查询。
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
(4)Hash索引在任何时候都不能避免表扫描。
前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。
(5)Hash索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。
BTREE
B-Tree 索引是 MySQL 数据库中使用最为频繁的索引类型。简单理解,塔就像一棵树,B-Tree索引需要从根节点到枝节点,就能才能访问到页节点的具体数据。
btree索引能够加快访问数据的速度,因为存储引擎不再需要进行全表扫描来获取需要的数据,取而代之的是从索引的根节点开始进行搜索,根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针向下层查找,通过比较节点页的值和要查找的值可以找到合适的指针进入下一层子节点,这些指针实际上定义了子节点页中值的上限和下限,最终存储引擎要么是找到对应的值,要么是该记录不存在。
B-tree 索引可以用于使用 =, >, >=, <, <= 或者 BETWEEN 运算符的列比较。如果 LIKE 的参数是一个没有以通配符起始的常量字符串的话也可以使用这种索引。
另外有关聚集索引和非聚集索引,这里收藏两篇文章:
想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。上尉【14】