您的位置:首页 > 数据库 > MySQL

MySQL索引的类型

2016-03-07 16:33 274 查看
逻辑上:

Single columindexes单列索引

Combinedindexes,multiple-columnindex 多列索引

Unique唯一索引

Nonunique非唯一索引

 

物理上:

Clusteredindex 聚集索引

Not-clusterindex 非聚集索引

Innodb会把显示定义的索引 定义为聚集索引  聚集索引和数据列的行存储顺序是一样的

所有innodb表都要有一个聚集索引 产生锁等待的概率减少  对整个数据库的并发是有帮助的 不管是精确还是范围 效率都是非常高的 不会导致大量额外的物理io产生 不应该找频繁修改的列作为聚集索引 有可能删除之后产生大量的碎片

索引结构

Btree

适合于大量的增,删,改(oltp)

不能用or操作符的查询

适合高基数的列(唯一值多)

典型的树状结构

每个节点都是数据块

大多都是物理上一层,两层,三层不定,逻辑上三层

叶子块数据是排序的,从左向右递增

在分支块和根块中放的是索引的范围

Hash

适合小规模数据集快速定位

适合管理内存结构体,LRU链表等

不支持范围查询

不支持模糊查询

不支持排序 

Primary key,主键索引

主键特点:

1)  一个表中只能有一个主键,如果在其它字段上建立主键,则原来的主键就会取消

2)  主键的值不可重复,也不可为空(null)

在innodb中,clustered index选择原则

1)  显示声明的主键

2)  第一个不包含null列的唯一索引

3)  内置rowid

Innodb,主键特点

1)  如果索引最后没有主键,则会在索引内部存储时加上主键

2)  如果索引最后已有主键,则会显示加上主键

3)  因此只要用户定义的索引字段中包含了主键中的字段,那么这个字段就不会再被innodb自动加到索引中了,如果用户的索引字段中没有完全包含主键字段,innodb就会把剩下的主键字段加到索引的末尾

 

看个案例:

Create tablet( a char(32) not null,b char(32) not null,c char(32) not null,d char(32) not null,primary key(a,b),key idx(c,a) key idex(d,b))engine=innodb;

这个表innodb 在物理存储中,会自动补全主键字典,idx1实际上内部存储为(c,a,b),idx2实际上内部存储为(d,b,a)。

但是这个自动添加的字段的工作是server层所不知道的,因此mysql优化器并不知道索引中有这个字段的存在,所以如果你有一个查询 select * from t where d=x1 and b=x2 orderby a

其实内部存储的idx2(d,b,a)可以让这个查询完全走索引,但是由于server 层不知道所以最终mysql优化器可能选择idx2(d,b)做过滤然后排序a字段,或者直接用pk扫描避免排序

如果我们定义表结构的时候就定义为key idx2(d,b,a),那么mysql就知道(d,b,a)三个字段索引中都有,并且innodb发现用户定义的索引中包含了所有的主键字段,也不会再添加了

唯一索引(约束)(unique key,UNIQUE Index Constraints)

唯一索引和主键索引的区别

相同:它们都属于实体完成性约束

不同点

1)  唯一约束所在的列允许空值,但主键约束所在列不允许空值

2)  可以把唯一性约束放在一个或者多个列上,这些列会列的组合必须有唯一索引,但是,唯一性约束所在的列并不是表的主键索引

3)  唯一性约束强制在指定的列上创建一个唯一性索引,在默人的情况下,创建唯一性的非聚集索引,但是也可以指定锁创建的索引是聚集索引

4)  建立主键的目的是让外键来引用

5)  一个表最多有一个主键,但是可以有很多唯一键

root@localhost:mysql.sock  01:34:31 [wwb]>select * from t6;

+----+-----+--------+-------------+-------+

| id | vid |name   | other       | phone |

+----+-----+--------+-------------+-------+

|  7 |   8| lanlan | am is a dba |     7 |

|  9 |  10| c      | asd         |    7 |

root@localhost:mysql.sock  01:34:26 [wwb]>desc t6;

+-------+------------------+------+-----+---------+----------------+

| Field | Type             | Null | Key | Default |Extra          |

+-------+------------------+------+-----+---------+----------------+

| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |

| vid   | int(10) unsigned | NO   | UNI | NULL    |                |

| name  | varchar(10)      | NO  | MUL | NULL    |                |

| other |varchar(20)      | NO   |    | NULL    |                |

| phone |int(11)          | YES  |     |NULL    |                |

关闭唯一性效验插入(10,10)会报错

root@localhost:mysql.sock  01:36:41 [wwb]>set unique_checks=0;

Query OK, 0 rowsaffected (0.00 sec) 

root@localhost:mysql.sock  01:37:25 [wwb]>insert into t6values(10,10,'wwb','am is a dba',10);

ERROR 1062 (23000):Duplicate entry '10' for key 'vid'

2 rows in set(0.00 sec)

Id是主键 uid是唯一索引   插入重复值会报错 不对每行记录做唯一性检测

但是也是要检查的

如果非得要写的情况下 可使用使用ignore参数

root@localhost:mysql.sock  01:38:27 [wwb]>insert ignore into t6 values(10,10,'wwb','am is a dba',10);

Query OK, 0rows affected (0.00 sec)

root@localhost:mysql.sock  20:58:23 [wwb]>insert into t6values(10,11,'laoyan','dba',0)
onduplicate key update vid=3;

Query OK, 1row affected (0.01 sec)

Replcae不管怎样,总是至少2rowsaffected,因为是先删除,后insert,replace以主键或是唯一索引为依据

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: