Mysql索引与键

0.主键与索引的不同

主键在物理层面上只有两个用途: 惟一地标识一行;作为一个可以被外键有效引用的对象。

索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。下面是主键和索引的一些区别与联系。

1. 主键一定是唯一性索引,唯一性索引并不一定就是主键。

2. 一个表中可以有多个唯一性索引,但只能有一个主键。

3. 主键列不允许空值,而唯一性索引列允许空值。

4. 索引可以提高查询的速度,不会约束字段的唯一非空性;而键主要约束记录的唯一非空性。

5. 不管是主键还是外键都必须建立在索引字段上

一、索引

http://blog.csdn.net/xluren/article/details/32746183

索引是对整张表的统计,可以提高查询效率;但可能降低增删改的效率;索引是用来查找记录的,而键是用来约束记录的。当然unique也对记录有一定的约束作用。

1.索引带来的查询效率

如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢。还是以WordPress来说,其多个数据表都会对经常被查询的字段添加索引。建立了索引的表只能在where后使用了该索引才能提高效率。

2.索引定义

索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。数据库查索引远比直接查数据表(遍历整个表)快。

索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。

3.索引的种类

a.普通索引INDEX

这是最基本的索引,它没有任何限制,比如上文中为title字段创建的索引就是一个普通索引,MyIASM中默认的BTREE类型的索引,也是我们大多数情况下用到的索引。

CREATE INDEX index_name ON table(column(length))

DROP INDEX index_name ON table

b.唯一索引UNIQUE

与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一,创建方法和普通索引类似。

CREATE UNIQUE INDEX indexName ON table(column(length))

c.全文索引(FULLTEXT)

MySQL从3.23.23版开始支持全文索引和全文检索,FULLTEXT索引仅可用于 MyISAM 表;不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。

4.在列上构造索引

在需要经常使用在where子句后的字段上创建索引

a.单列索引、多列索引

多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。

b.组合索引(最左前缀)(聚集索引)

平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引.

例如上表中针对title和time建立一个组合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))。

建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:

–title,time

–title

为什么没有time这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引,如下面的几个SQL所示:

–使用到上面的索引

SELECT * FROM article WHREE title=‘测试‘ AND time=1234567890;

SELECT * FROM article WHREE title=‘测试‘;

–不使用上面的索引(这就是组合索引的特点)

SELECT * FROM article WHREE time=1234567890;

5.如何合理的创建索引

a. 何时使用聚集索引或非聚集索引?

动作描述 使用聚集索引 使用非聚集索引

列经常被分组排序 使用 使用

返回某范围内的数据 使用 不使用

一个或极少不同值 不使用 不使用

小数目的不同值 使用 不使用

大数目的不同值 不使用 使用

频繁更新的列 不使用 使用

外键列 使用 使用

主键列 使用 使用

频繁修改索引列 不使用 使用

b.索引不会包含有NULL值的列

只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

c.使用短索引

对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

d.索引列排序

MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

e.like语句操作

一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

f.不要在列上进行运算

例如:select * from users where YEAR(adddate)<2007,将在每个行上进行运算, 这将导致索引失效而进行全表 扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′。关于这一点可以围观: 一个单引号引发的MYSQL性能损失。

g.索引的适用条件

MySQL只对一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的like(不以通配符%或_开头的情形)。而理论上每张表里面最多可创建16个索引,不过除非是数据量真的很多,否则过多的使用索引也不是那么好玩的,比如我刚才针对text类型的字段创建索引的时候,系统差点就卡死了。

二、键

键是比索引更高一个层次的约束,通过创建key时,数据库会自动在该字段上创建索引。所以可以说键是在索引的基础上实现的。键有2种:主键和外键。

1.主键PRIMARY KEY

a.主键的作用:(唯一非空约束)

主键是对该字段上的记录的约束:使得该字段不能重复也不能为空,所以主键被认为是NOT NULL和UNIQUE约束最好的结合。如果这些列没有被明确地定义为NOT NULL,MySQL会隐含地定义这些列。

(插入记录时,自动检查该字段是否唯一非空)

b.声明主键的方法:

CREATE TABLE tbl_name ([字段描述省略...], PRIMARY KEY(index_col_name));

LTER TABLE tbl_name ADD PRIMARY KEY (index_col_name,…);

c.组合主键

键生于索引而高于索引。主键其实也是索引,甚至在MySQL的术语里面“键”就等于“索引”,所以“外键”一定要先设为“索引”,这个咱们下篇日志再来讨论。所以主键也应该和索引一样,既可以作用于单独的字段,又可以作用于多个字段。组合的主键,每个列都会隐含定义NOT NULL约束,且其二者加在一起被定义了UNIQUE 惟一约束。将会把多字段的组合约束为唯一非空。

create table firewall(

host varchar(11) not null,

port smallint(4),

access enum(‘deny‘, ‘allow‘) not null,

primary key (host,port)

)

INSERT INTO firewall (host ,port ,access)

VALUES (‘202.65.3.87‘, ‘21‘, ‘deny‘);

/*插入一条新的记录,没有啥问题1 row(s) inserted.*/

INSERT INTO firewall (host ,port ,access)

VALUES (‘202.65.3.87‘, ‘21‘, ‘deny‘);

/*插入失败,因为host 加port的主键值202.65.3.87-21已经存在了

#1062 - Duplicate entry ‘202.65.3.87-21‘ for key ‘PRIMARY‘

*/

INSERT INTO firewall( host, port, access )

VALUES (‘192.168.0.1‘, NULL , ‘deny‘)

/*

没声明NOT NULl port也不能为NULL

#1048 - Column ‘port‘ cannot be null

*/

组合主键约束:组合后的字段不能为空,也不能重复。

2.外键foreign key

只有InnoDB类型的表才可以使用外键,mysql默认是MyISAM,这种类型不支持外键约束.

建立外键的表,被称为子表;被引用的表叫做主表或外表。

a.外键的作用:(子集约束:对主表和子表都有一定的约束)

若B表字段有以A表字段作为参照的外键,则B表中的此字段的取值只能是A表中存在的值(该字段上,子表是主表的子集),从表B会实时受到主表A的约束,同时若关联on delete on update等操作则当A中的被参照的字段发生delete或update时,B中的对应的记录也会发生 delete 或 update操作,完整性;如果没有设置delete或者update联动,则当删除A表中的记录时,如果如果B表中存 在对应的记录是不能删除成功的(因为那样将不满足子集约束)。(总结为:以某一个表A的某一个或组合字段约束另一个表B的某一个或组合字段,要求B表该字段的记录是A表该字段记录的子集,只要满足子集约束的操作都可以,反正则不可以)

b.创建的步骤

指定主键关键字: foreign key(列名)

引用外键关键字: references <外键表名>(外键列名)

c.外键关联事件触发限制:on delete和on update , 可设参数cascade(跟随外键改动), restrict(限制外表中的外键改动),set Null(设空值),set Default(设默认值),[默认]no action

create table temp(

id int,

name char(20),

foreign key(id) references outTable(id) on delete cascade on update cascade);

把id列设为外键,参照外表outTable的id列,当外表中外键的值删除,本表中对应的id记录删除,当外键的值改变 本表中对应的列值改变。

d.组合外键

只能有一个外键,但可以使用多表的字段组合成一个复合外键。不推荐

e.完全允许多对对的关系

主表中的一记录可以对应子表中的多个记录;而主表中的多个记录也可以对应子表中的一个记录

mysql> show create table  parent;   //主表

CREATE TABLE `parent` (

`id` int(11) NOT NULL,

`name` char(4) DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

mysql> show create table  child;    //子表

CREATE TABLE `child` (

`id` int(11) NOT NULL,

`parent_id` int(11) NOT NULL,

KEY `parent_id` (`parent_id`),

CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`) ON DELETE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=utf8

mysql> select * from child;

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

| id | parent_id |

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

|  1 |         1 |   //多个子表的id对应同一主表的parent_id,

|  3 |         1 |

|  1 |         2 |  //同时同一子表的id对应多个主表的parent_id

|  1 |         3 |

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

4 rows in set (0.00 sec)

mysql> select * from parent;

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

| id | name |

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

|  1 | a    |

|  2 | b    |

|  3 | c    |

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

3 rows in set (0.00 sec)

时间: 2024-10-04 15:07:55

Mysql索引与键的相关文章

五、MySQL索引和键

MySQL索引和键   (不同的索引有不同功能 ,不同的约束方式,不同的使用规则)优点:对一张表来说,索引就像一本书的目录,能够加快查询速度缺点:占用物理存储空间 (索引信息存储在表对应的文件里)     会降低插入.更新表记录的速度(insert   delete   update)1.索引的类型普通索引:index        唯一索引:unique全文索引:fulltext 2.各个索引的说明(1).index 普通索引一个表中可以有多个INDEX字段把经常做查询条件的字段设置为INDE

Mysql索引介绍及常见索引(主键索引、唯一索引、普通索引、全文索引、组合索引)的区别

Mysql各种索引区别:普通索引:最基本的索引,没有任何限制唯一索引:与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值.主键索引:它 是一种特殊的唯一索引,不允许有空值. 全文索引:仅可用于 MyISAM 表,针对较大的数据,生成全文索引很耗时好空间.组合索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则. Mysql索引概念:说说Mysql索引,看到一个很少比如:索引就好比一本书的目录,它会让你更快的找到内容,显然目录(索引)并不是越多越好,假如这

关于MySql数据库主键及索引的区别

一.什么是索引?索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的记录数量越多,这个操作的代价就越高.如果作为搜索条件的列上已经创建了索引,MySQL无需扫描任何记录即可迅速得到目标记录所在的位置.如果表有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍.  二.索引的类型MySQL提供多种索引类型供选择: 普通索引这是最基本的索引类型,而且它没

Mysql数据库主键,外键,索引概述

主键: 主键是数据表的唯一索引,比如学生表里有学号和姓名,姓名可能有重名的,但学号确是唯一的,你要从学生表中搜索一条纪录如查找一个人,就只能根据学号去查找,这才能找出唯一的一个,这就是主键;如:id int(10) not null primary key auto_increment :自增长的类型 : 外键: 定义数据表 假如某个电脑生产商,它的数据库中保存着整机和配件的产品信息.用来保存整机产品信息的表叫做 Pc:用来保存配件供货信息的表叫做Parts. 在Pc表中有一个字段,用来描述这款

【mysql】主键、普通索引、唯一索引和全文索引的比较

MYSQL索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录 开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的记录数量越多,这个操作的代价就越高.如果作为搜索条件的列上已经创建了索引,MySQL无 需扫描任何记录即可迅速得到目标记录所在的位置.如果表有1000个记录,通过索引查找记录至少要比顺序扫描记录快100倍.  mysql在使用like查询中,能不能用到索引?在什么地方使用索引呢? 在使用like的时

MySQL索引基本应用[转]

原文地址:http://www.php100.com/html/webkaifa/database/Mysql/2010/0409/4279.html 索引是快速搜索的关键.MySQL索引的建立对于MySQL的高效运行是很重要的.下面介绍几种常见的MySQL索引类型. 在数据库表中,对字段建立索引可以大大提高查询速度.假如我们创建了一个 mytable表: CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT N

深入浅出分析MySQL索引设计背后的数据结构

在我们公司的DB规范中,明确规定: 1.建表语句必须明确指定主键 2.无特殊情况,主键必须单调递增 对于这项规定,很多研发小伙伴不理解.本文就来深入简出地分析MySQL索引设计背后的数据结构和算法,从而可以帮你释疑如下问题: 1.为什么innodb表需要主键? 2.为什么建议innodb表主键是单调递增? 3.为什么不建议innodb表主键设置过长? B-tree(多路搜索树,并不是二叉的)是一种常见的数据结构.使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.B通常

mysql索引介绍

在数据表中对字段建立索引将大大提高查询的速度: 例如:select * from mytable where username='admin' 如果在列username上建立了索引,只需要一次就可以找到该记录 一.mysql索引的类型: 1.普通索引 创建:create index indexname on mytable(username) 删除:drop index [indexname] on mytable 2.唯一索引 特点:索引列值必须唯一,但允许有null值 创建:create u

mysql索引总结----mysql 索引类型以及创建

关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车.对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢.还是以WordPress来说,其多个数据表都会对经常被查询的字段添加索引,比如wp_comments表中针对5个字段设计了BTREE索引. 一个简单的对比测试 以我去年测试的数据作为一个简单示例,20多条数据源随机生成200万条