数据库操作之——索引

一 索引的概念

MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。

打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

建立索引会占用磁盘空间的索引文件。

 

二 B-tree

  B-Tree 索引是 MySQL 数据库中使用最为频繁的索引类型,除了 Archive 存储引擎之外的其他所有的存储引擎都支持 B-Tree 索引。不仅仅在 MySQL 中是如此,实际上在其他的很多数据库管理系统中B-Tree 索引也同样是作为最主要的索引类型,这主要是因为 B-Tree 索引的存储结构在数据库的数据检 索中有非常优异的表现。 
      一般来说, MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的结构来存储的,也就是所有实际需要的数据都存放于 Tree 的 Leaf Node ,而且到任何一个 Leaf Node 的最短路径的长度都是完全相同的,所以我们大家都称之为 B-Tree 索引当然,可能各种数据库(或 MySQL 的各种存储引擎)在存放自己的 B-Tree 索引的时候会对存储结构稍作改造。如 Innodb 存储引擎的 B-Tree 索引实际使用的存储结构实际上是 B+Tree ,也就是在 B-Tree 数据结构的基础上做了很小的改造,在每一个 
Leaf Node 上面出了存放索引键的相关信息之外,还存储了指向与该 Leaf Node 相邻的后一个 LeafNode 的指针信息,这主要是为了加快检索多个相邻 Leaf Node 的效率考虑。 

 

三  索引的具体介绍

  mysql的索引分为单列索引(主键索引,唯索引,普通索引)和组合索引.

  单列索引:一个索引只包含一个列,一个表可以有多个单列索引.

  组合索引:一个组合索引包含两个或两个以上的列。

  1 索引的创建

  1)单列索引

  1-1 普通索引,这是最基本的索引

  方法一

mysql> create index in_id on s1(id);
Query OK, 0 rows affected (0.82 sec)

  方法二

mysql> alter table s1 add index in_id (id);
Query OK, 0 rows affected (0.79 sec)

  1-2 唯一索引

  创建方法与普通索引类似

  方法一

mysql> create unique index uni_id on s1(id);
Query OK, 0 rows affected (0.77 sec)
Records: 0  Duplicates: 0  Warnings: 0

  方法二

mysql> alter table s1 add unique index uni_id (id);
Query OK, 0 rows affected (0.77 sec)
Records: 0  Duplicates: 0  Warnings: 0

  1-3 主键索引

  主键索引,不允许有空值,(在B+TREE中的InnoDB引擎中,主键索引起到了至关重要的地位)

  主键索引建立的规则是 int优于varchar,一般在建表的时候创建,最好是与表的其他字段不相关的列或者是业务不相关的列.一般会设为 int 而且是 AUTO_INCREMENT自增类型的。

 

  2)组合索引

  一个表中含有多个单列索引不代表是组合索引,通俗一点讲 组合索引是:包含多个字段但是只有索引名称,期格式是CREATE INDEX IndexName On `TableName`(`字段名`(length),`字段名`(length),...)。  

 

  使用多列所需需要按照最左索引列查找;不能跳过中间列(跳过就会将遍历被跳过的索引字段,会浪费大量时间);如果某一列是范围查询,那么其右边所有列无法使用索引。

 

  列的顺序非常重要,MySQL仅能对索引最左边的前缀进行有效的查找。例如:假设存在组合索引it1c1c2(c1,c2),查询语句select * from t1 where c1=1 and c2=2能够使用该索引。查询语句select * from t1 where c1=1也能够使用该索引。但是,查询语句select * from t1 where c2=2不能够使用该索引,因为没有组合索引的引导列,即,要想使用c2列进行查找,必需出现c1等于某值。

  示例:

mysql> create  index mul_index on s1(id,name,email);
Query OK, 0 rows affected (0.59 sec)
Records: 0  Duplicates: 0  Warnings: 0
mysql> desc s1;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id     | int(11)     | YES  | MUL | NULL    |       |
| name   | varchar(20) | YES  |     | NULL    |       |
| gender | char(6)     | YES  |     | NULL    |       |
| email  | varchar(50) | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)

  如示例所示创建了一个组合索引(id,name,email),实际上是创建了一下这几种索引。

  (id),(id,name,),(id,email),(id,name,email)。

mysql> select count(1) from s1 where name='egon' and email = 'egon160000@oldboy';
+----------+
| count(1) |
+----------+
|        1 |
+----------+
1 row in set (0.08 sec)

mysql> select count(1) from s1 where id =830 and email = 'egon160000@oldboy';
+----------+
| count(1) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

  演示结果,带有id的查询命令会快很多。

 

  重点:最左前缀原则。

  所谓最左前缀原则就是先要看第一列,在第一列满足的条件下再看左边第二列,以此类推。有位网友描述得很形象: 你可以认为联合索引是闯关游戏的设计例如你这个联合索引是state/city/zipCode那么state就是第一关 city是第二关, zipCode就是第三关你必须匹配了第一关,才能匹配第二关,匹配了第一关和第二关,才能匹配第三关你不能直接到第二关的索引的格式就是第一层是state,第二层才是city索引是因为B+树结构 所以查找快 如果单看第三列 是非排序的。 

  多列索引是先按照第一列进行排序,然后在第一列排好序的基础上再对第二列排序,如果没有第一列的话,直接访问第二列,那第二列肯定是无序的,直接访问后面的列就用不到索引了。 
  所以如果不是在前面列的基础上而是但看后面某一列,索引是失效的。

  示例:

    

 

  

 

二 索引的删除

  不管是普通索引还是唯一索引,固定格式

  DORP INDEX IndexName ON `TableName`

mysql> drop index mul_index on s1;
Query OK, 0 rows affected (0.41 sec)
Records: 0  Duplicates: 0  Warnings: 0

 

posted @ 2017-10-30 17:27  骑者赶路  阅读(266)  评论(0编辑  收藏  举报