数据库索引详解
什么是索引
- 索引是对 数据库中一列或者多列的值进行排序的一中结构,使用索引可以快速访问数据库中表的特定信息。索引的一个主要的目的就是加快检索表中数据,亦即能协助信息搜索者尽快的找到符合限制条件的记录的辅助数据结构。
- 简单来说索引就是数据库的目录。
索引有什么作用
索引的最大作用就是加快数据库的查询速度。
索引为什么会加快查询速度
数据库在执行一条SQL语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。但若是遇到大数据量的查询时,直接全表匹配的方式太慢了,这时候就需要用到索引。我们对某一字段增加索引,查询的时候就会先去索引列表中一次定位到特定值得行数,大大减少遍历匹配的行数,所以可以明显的增加查询的速度。
索引的种类
- 主键索引:数据记录里面不能有null,数据内容不能重复,在一张表里面不能有多个主键索引。
- 普通索引:使用字段关键字建立的索引,主要是提高查询速度。
- 唯一索引:字段数据是唯一的,数据内容里面能否为null,在一张表里面,是可以添加多个唯一索引。
- 全文索引:在早起版本中只有myisam引擎支持全文索引,在innodb5.6后也支持全文索引,在MySQL中全文索引不支持中文。我们一般使用sphinx集合coreseek来实现中文的全文索引。
索引的创建(索引的例子)
执行Create Table语句时可以创建索引,也可以单独用Create index或者 Alter Table来为表增加索引。
1. ALTER TABLE
ALTER TABLE用来创建普通索引、unique索引或者primary key索引。
ALTER TABLE table_name ADD INDEX index_name(column_list)
ALTER TABLE table_name ADD UNIQUE(column_list)
ALTER TABLE table_name ADD PRIMARY KEY(column_list)
- table_name:是要增加索引的表名。
- column_list:指出对哪些列进行索引,多列时各列之间用逗号分隔。
- index_name:可选,缺省是,MySQL将根据第一个索引列赋一个名称。
- ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。
2. CREATE INDEX
CREATE INDEX可以创建普通索引和UNIQUE索引。
CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)
注: table_name 索引名不可选。
删除索引
可利用ALTER TABLE或DROP INDEX语句来删除索引。类似于CREATE INDEX语句,DROP INDEX可以在ALTER TABLE内部作为一条语句处理,语法如下。
DROP INDEX index_name ON talbe_name
ALTER TABLE table_name DROP INDEX index_name
ALTER TABLE table_name DROP PRIMARY KEY
- 前两条语句是等价的,删除掉table_name中的索引index_name。
- 第3条语句只在删除PRIMARY KEY索引时使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。
- 如果从表中删除了某列,则索引会受到影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。
查看索引
show index from tblname;
show keys from tblname;
查询结果各字段解释
字段名 | 解释 |
---|---|
Table | 表的名称 |
Non_unique | 如果索引不能包括重复词,则为0。如果可以,则为1 |
Key_name | 索引的名称 |
Seq_in_index | 索引中的列序列号,从1开始。 |
Column_name | 列名称。 |
Collation | 列以什么方式存储在索引中。在MySQL中,有值‘A’(升序)或NULL(无分类)。 |
Cardinality | 索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机会就越大。 |
Sub_part | 如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为NULL。 |
Packed | 指示关键字如何被压缩。如果没有被压缩,则为NULL。 |
Null | 如果列含有NULL,则含有YES。如果没有,则该列含有NO。 |
Index_type | 用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。 |
Comment | 暂无资料 ··· |
MySQL中的索引
MyISAM索引
MyISAM引擎使用B+Tree 作为索引结构,叶节点的data域存放的是数据记录的地址。
这里假设表中一共有三列,以Col1为主键则。
- MyISAM的索引文件仅仅保存数据记录的地址。
- MyISAM中,主索引和辅助索引在结构上没有任何区别,只是主索引的key要求是唯一的。而辅助索引的key值可以是重复的。
如果在Col2上建立一个辅助索引,则此索引的结构如下。
如图,此索引同样是一颗B+ 树,data域保存数据记录的地址,因此,MyISAM 中索引检索的算法为首先按照B+树搜素算法搜素索引,如果指定的Key存在,则取出其data域中的值,然后以data域中的值为地址,读取相应数据记录。
MyISAM的索引方式也叫做”非聚集“ 的,之所以这么称呼是为了与INNODB的聚集索引区分。
InnoDB索引实现
InnoDB的索引也是使用B+Tree作为索引结构,但是具体的实现方式与MyISAM截然不同。
区别:
- InnoDB的数据文件本身就是索引文件。从上文知道,MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB 中,表数据文件本身就是按B+树组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。
可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
- InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。
如图在Col3上的一个辅助索引:
聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
为什么说不建议使用过长的字段作为主键?
答:因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。
用非单调的字段作为主键在InnoDB中不是个好主意
InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。