1、MySQL的主键。
2、MySQL的唯一约束。
3、MySQL的索引。
4、主键、唯一约束和唯一索引的区别。
"主键" 的完整称呼是 "主键约束" 。MySQL 主键约束是一个列或者列的组合(其中由多列组合的主键称为复合主键),其值能唯一地标识表中的每一行。这样的一列或多列称为表的主键,通过它可以强制表的实体完整性。。
(1)一个表可以没有主键,而且最多只能有一个主键。
(2)主键值必须唯一标识表中的每一行,且不能为 NULL,即同一个表中不可能存在两行数据有相同的主键值。
MySQL唯一约束(Unique Key)是指所有记录中字段的值不能重复出现。例如,为 id 字段加上唯一性约束后,每条记录的 id 值都是唯一的,不能出现重复的情况。如果其中一条记录的 id 值为 "0001" ,那么该表中就不能出现另一条记录的 id 值也为 "0001" 。
唯一约束可以确保一列或者几列不出现重复值。
唯一约束与主键约束相似的是它们都可以确保列的唯一性。不同的是,唯一约束在一个表中可有多个,并且设置唯一约束的列允许有空值,但是最多只能有一个空值。而主键约束在一个表中只能有一个,且不允许有空值。比如,在用户信息表中,为了避免表中用户名重名,可以把用户名设置为唯一约束。
唯一约束可以在创建表时直接设置,通常设置在除了主键以外的其它列上。
在定义列的尾部直接使用 UNIQUE 关键字指定唯一约束,语法格式如:<字段名> <数据类型> UNIQUE 。( 或者 UNIQUE KEY `unique_name` (`first_name`, `last_name`) )
在修改表时添加唯一约束的语法格式为:ALTER TABLE <数据表名> ADD CONSTRAINT <唯一约束名> UNIQUE(<列名>); 。
在 MySQL 中删除唯一约束的语法格式如下:ALTER TABLE <表名> DROP INDEX <唯一约束名>; 。
如果业务中要求两个字段联合起了是唯一的,比如 "地址" + "名称" 是唯一的,这就需要对两列甚至多列添加联合唯一约束。
为什么要使用索引?
索引是 MySQL 中一种十分重要的数据库对象。它是数据库性能调优技术的基础,常用于实现数据的快速检索。
索引是什么?
首先我们可以举个例子,字典大家应该都使用过,我们可以使用目录快速定位到所要查找的内容,那么索引跟目录的作用类似,在数据库表记录中,利用索引,可以快速过滤查找到数据记录。
索引就是根据表中的一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表,实质上是一张描述索引列的列值与原表中记录行之间一一对应关系的有序表。
例如,若对表中name字段建立索引,则按照表中name字段进行索引排序,并为其建立指向数据表中记录所在位置的 "指针" 。
查询方式有两种,其中一种是全表扫描;另一种是利用数据表上建立的索引进行扫描。
在 MySQL 中,通常有以下两种方式访问数据库表的行数据:
(1) 顺序访问
顺序访问是在表中实行全表扫描,从头到尾逐行遍历,直到在无序的行数据中找到符合条件的目标数据。这种方式实现比较简单,但是当表中有大量数据的时候,效率非常低下。例如,在几千万条数据中查找少量的数据时,使用顺序访问方式将会遍历所有的数据,花费大量的时间,显然会影响数据库的处理性能。
(2) 索引访问
索引访问是通过遍历索引来直接访问表中记录行的方式。使用这种方式的前提是对表建立一个索引,在列上创建了索引之后,查找数据时可以直接根据该列上的索引找到对应记录行的位置,从而快捷地查找到数据。索引存储了指定列数据值的指针,根据指定的排序顺序对这些指针排序。
例如,在学生基本信息表 students 中,如果基于 student_id 建立了索引,系统就建立了一张索引列到实际记录的映射表,当用户需要查找 student_id 为 12022 的数据的时候,系统先在 student_id 索引上找到该记录,然后通过映射表直接找到数据行,并且返回该行数据。因为扫描索引的速度一般远远大于扫描实际数据行的速度,所以采用索引的方式可以大大提高数据库的工作效率。
索引根据用途分为:
(1)普通索引:是最基本的索引类型,它的目的是加快对数据的访问速度,没有任何限制。索引列值可以取空值或重复值。创建使用关键字 "INDEX" 或 "KEY" 。
(2)唯一索引:是不允许具有相同索引值的索引。创建唯一索引的目的往往不是为了提高访问速度,而是为了避免数据出现重复。其中索引列值不能重复,即索引列值必须是唯一的。创建使用关键字 "UNIQUE" 。
(3)主键索引:是唯一索引的特定类型。索引值不能为空值。主键是用来唯一标识表中一条记录的。主键不允许为空值,主键是唯一的。一个表只能有一个主键,不可能有多个主键。创建使用关键字 "PRIMARY KEY" 。
注意:唯一索引和主键索引不是互斥关系;唯一索引包含了主键索引;主键索引是一种特殊的唯一索引。
索引根据列数分为:
(1)单列索引:即一个索引只包含单个列,一个表可以有多个单列索引,但这些单列索引不是组合索引。比如,创建一个学号ID的索引;以name再创建一个姓名的单列索引。
(2)组合索引(复合索引或多列索引):即一个索引包含多个列。比如,以用户ID、用户名Name、用户年龄Age来创建的索引就是组合索引。此时,排序规则是左前缀原则,即先按照用户ID进行排序;当第一列值相同的情况下,则按照用户名Name第二列进行排序;依次类推。
索引根据存储方式分为:
(1)B-树索引;(2)哈希索引。
虽然索引可以加快查询速度,提高 MySQL 的处理性能,但是过多地使用索引也会造成以下弊端:
(1)创建索引和维护索引要耗费时间,这种时间会随着数据量的增加而增加。
(2)除了数据表占数据空间之外,每一个索引还要占一定的物理空间。如果要建立聚簇索引,那么需要的空间就会更大。
(3)当对表中的数据进行增加、删除和修改的时候,索引也要动态地维护,这样就降低了数据的维护速度。
注意:索引可以在一些情况下加速查询,但是在某些情况下,会降低效率。
索引只是提高效率的一个因素,因此在建立索引的时候应该遵循以下原则:
(1)在经常需要搜索的列上建立索引,可以加快搜索的速度。
(2)在作为主键的列上创建索引,强制该列的唯一性,并组织表中数据的排列结构。
(3)在经常使用表连接的列上创建索引,这些列主要是一些外键,可以加快表连接的速度。
(4)在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,所以其指定的范围是连续的。
(5)在经常需要排序的列上创建索引,因为索引已经排序,所以查询时可以利用索引的排序,加快排序查询。
(6)在经常使用 WHERE 子句的列上创建索引,加快条件的判断速度。
与此对应,在某些应用场合下建立索引不能提高 MySQL 的工作效率,甚至在一定程度上还带来负面效应,降低了数据库的工作效率,一般来说不适合创建索引的环境如下:
(1)对于那些在查询中很少使用或参考的列不应该创建索引。因为这些列很少使用到,所以有索引或者无索引并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度,并增大了空间要求。
(2)对于那些只有很少数据值的列也不应该创建索引。因为这些列的取值很少,例如人事表的性别列。查询结果集的数据行占了表中数据行的很大比例,增加索引并不能明显加快检索速度。
(3)对于那些定义为 TEXT、IMAGE 和 BIT 数据类型的列不应该创建索引。因为这些列的数据量要么相当大,要么取值很少。
(4)当修改性能远远大于检索性能时,不应该创建索引。因为修改性能和检索性能是互相矛盾的。当创建索引时,会提高检索性能,降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
主键和唯一索引的区别是:
(1) 主键一定是唯一索引,唯一索引并不一定就是主键。
(2) 一个表中可以有多个唯一索引,但最多只能有一个主键。
(3) 主键的列值不允许为空值,而唯一索引的列值最多有一个空值。
通俗举例来说:主键相当于一本书的页码,索引相当于该书的目录。
当创建或设置主键的时候,MySql会自动添加一个与主键对应的唯一索引,因此不需要再额外地添加把主键作为唯一索引的语句。数据库管理系统对于主键会自动生成一个唯一索引,所以主键是一个特殊的索引。可以通过SQL语句( "SHOW INDEX FROM tablename;" 或 "SHOW KEYS FROM tablename;" )查看已建表的索引。
# SQL创建语句示例。
CREATE TABLE `ik_admin`
(
`user_id` bigint NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`user_name` varchar(50) NOT NULL,
`password` varchar(128) NOT NULL,
`role_id` bigint NOT NULL,
`last_ip` varchar(20) NOT NULL DEFAULT '',
`last_time` datetime NULL,
`email` varchar(32) NOT NULL DEFAULT '',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0-禁用 1-启用)',
PRIMARY KEY (`user_id`), # 主键:默认自动生成索引, 列值不能重复 而且不允许为空值。
UNIQUE INDEX `userName` (`user_name`) # 唯一索引:列不能重复 但可以有空值(最多只有一个空值)。
) ENGINE = MyISAM AUTO_INCREMENT = 1001 DEFAULT CHARSET = utf8 COMMENT ='管理员表';
唯一约束和唯一索引的区别:
(1)唯一约束和唯一索引,都可以实现列数据的唯一,列值可以有空值。
(2)创建唯一约束的时候,会自动创建一个同名的唯一索引,该索引不能单独删除,删除约束会自动删除索引。唯一约束是通过唯一索引来实现数据的唯一。
(3)创建一个唯一索引,这个索引就是独立,可以单独删除。
(4)如果一个列上想有约束和索引,且两者可以单独的删除。可以先建唯一索引,再建同名的唯一约束。
(5)如果表的一个字段,要作为另外一个表的外键,那么这个字段必须有唯一约束(或是主键),如果只是有唯一索引,就会报错。
索引的键不一定要和唯一约束的完全匹配,唯一约束可以只用索引的前导列。请看下面的例子:
create table t (n1 number, n2 number);
create index t_idx on t(n1, n2);
上面只是创建了两个列的复合索引,并不要求是唯一索引。
alter table t add constraint t_uk unique (n1) using index t_idx;
可以使用这个索引来创建唯一约束,而且它只在第一个列上唯一,也就是说唯一约束比索引更加严格。
那么这个索引的第二个列有什么意义?有些时候,带一些冗余列可以使得你直接从索引中取到所有SELECT的数据而无需回表。