索引(Index)是帮助MySQL高效获取数据的数据结构。
在MySQL中,索引属于存储引擎级别的概念,不一样存储引擎对索引的实现方式是不一样的。MyISAM和InnoDB存储引擎只支持BTREE索引,MEMORY/HEAP存储引擎支持HASH和BTREE索引。 数据库
A、提升数据检索效率,下降数据库的IO成本。
B、经过索引对数据进行排序,下降数据排序的成本,下降了CPU的消耗。
C、大大加快数据的查询速度。网络
A、建立索引和维护索引要耗费时间,而且随着数据量的增长所耗费的时间也会增长
B、索引也须要占空间,咱们知道数据表中的数据也会有最大上线设置的,若是咱们有大量的索引,索引文件可能会比数据文件更快达到上线值
C、当对表中的数据进行增长、删除、修改时,索引也须要动态的维护,下降了数据的维护速度。数据结构
A、主键自动创建惟一索引
B、频繁做为查询条件的字段应该建立索引
C、查询中与其余表关联的字段,外键关系创建索引
D、频繁更新的字段不适合创建索引,由于每次更新不仅仅是更新了记录还会更新索引
E、WHERE条件里用不到的字段不建立索引
F、单键/组合索引的选择问题,who?(在高并发下倾向建立组合索引)
G、查询中排序的字段,排序的字段若经过索引去访问将大大提升排序速度
H、查询中统计或者分组字段
不适合使用索引的场合:
A、对常常更新的表就避免对其进行过多的索引,对常常用于查询的字段应该建立索引。
B、数据量小的表最好不要使用索引,因为数据较少,可能查询所有数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
C、在不一样值少的列上不要创建索引,好比在学生表的"性别"字段上只有男,女两个不一样值。在一个不一样值较多的列能够创建索引。并发
单列索引只包含单个列,但一个表中能够有多个单列索引。
A、普通索引
普通索引容许在定义索引的列中插入重复值和空值。
B、惟一索引
索引列中的值必须是惟一的,可是容许为空值。
C、主键索引
主键索引是一种特殊的惟一索引,不容许有空值。数据库设计
在表中的多个字段组合上建立的索引,只有在查询条件中使用了组合的多个字段的左边字段时,索引才会被使用,使用复合索引时遵循最左前缀集合。ide
全文索引,只有MyISAM存储引擎支持,只能在CHAR、VARCHAR、TEXT类型字段上使用全文索引。
全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较。在数据量较大时候,先将数据放入一个没有全文索引的表中,而后再用CREATE index建立fulltext索引,要比先为一张表创建fulltext而后再将数据写入的速度快不少。高并发
空间索引是对空间数据类型的字段创建的索引,MySQL中的空间数据类型有四种:GEOMETRY、POINT、LINESTRING、POLYGON。
在建立空间索引时,使用SPATIAL关键字。
空间索引必须使用MyISAM存储引擎, 而且空间索引的字段必须为非空。优化
建立表时建立索引的语法:网站
CREATE TABLE table_name[col_name data type] [UNIQUE|FULLTEXT|SPATIAL][INDEX|KEY][index_name](col_name[length])[asc|desc]
在表上建立索引的语法:设计
ALTER TABLE tablename ADD[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [indexname] (col_name)[ASC|DESC]; CREATE [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] indexname ON tablename(col_name[length])[ASC|DESC];
unique|fulltext为可选参数,分别表示惟一索引、全文索引
index和key为同义词,二者做用相同,用来指定建立索引
col_name为须要建立索引的字段列,该列必须从数据表中该定义的多个列中选择
index_name指定索引的名称,为可选参数,若是不指定,默认col_name为索引值
length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度
asc或desc指定升序或降序的索引值存储
在建立索引时若是不指定索引名,默认使用字段名做为索引名。
直接建立索引CREATE INDEX index_name ON tablename(column(length))
修改表结构ALTER TABLE table_name ADD INDEX index_name ON (column(length))
建立表时指定索引
CREATE TABLE tablename ( col_name1 type, col_name2 type, INDEX index_name(col_name) );
索引列的值必须惟一,但容许有空值。若是是组合索引,则列值的组合必须惟一。
直接建立惟一索引CREATE UNIQUE INDEX indexName ON tablename(column(length))
修改表结构ALTER TABLE table_name ADD UNIQUE indexName ON (column(length))
建立表时直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, UNIQUE INDEX index_name(col_name) );
修改表结构ALTER TABLE table_name ADD PRIMARY KEY(col_name)
建立表时直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, PRIMARY KEY(col_name) );
直接建立复合索引CREATE INDEX indexName ON tablename(col_name1,col_name2)
修改表结构ALTER TABLE table_name ADD INDEX indexName(col_name1,col_name2)
建立表时直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, INDEX index_name(col_name1,col_name2) );
直接建立全文索引CREATE FULLTEXT INDEX indexName ON tablename(col_name)
修改表结构ALTER TABLE table_name ADD FULLTEXT INDEX indexName(col_name)
建立表时直接指定
CREATE TABLE tablename ( col_name1 type, col_name2 type, FULLTEXT INDEX index_name(col_name) );
在使用全文索引时,须要借助MATCH AGAINST操做,而不是通常的WHERE语句加LIKE。全文索引的限制比较多,好比只能使用MyISAM存储引擎,好比只能在CHAR、VARCHAR、TEXT上设置全文索引。好比搜索的关键字默认至少要4个字符,好比搜索的关键字过短就会被忽略掉。SELECT * FROM tablename WHERE MATCH(col_name) AGAINST('pattern');
col_name为全文索引列,'pattern'为匹配的字符串
DROP INDEX [indexName] ON tablename; ALTER TABLE tablename DROP INDEX indexname;
SHOW INDEX FROM table_name;
A、索引不会包含有null值的列
在数据库设计时不要让字段的默认值为null。
B、使用短索引
C、索引列排序
所以数据库默认排序能够符合要求的状况下不要使用排序操做;尽可能不要包含多个列的排序,若是须要最好给这些列建立复合索引。
D、like语句操做
通常状况下不推荐使用like操做,若是非使用不可。like “%aaa%”不会使用索引而like “aaa%”可使用索引。
E、不要在列上进行运算
在索引列上进行运算将致使索引失效而进行全表扫描,例如SELECT * FROM table_name WHERE YEAR(column_name)<2017;
F、不使用not in和<>操做
create procedure addStudent(in num int) begin declare i int; set i=1; delete from TStudent; while num>=i do insert TStudent values ( LPAD(convert(i,char(10)),10,'0'), CreateName(), if(ceil(rand()*10)%2=0,'男','女'), RPAD(convert(ceil(rand()*1000000000000000000),char(18)),18,'0'), Concat(convert(ceil(rand()*10)+1980,char(4)),'-',LPAD(convert(ceil(rand()*12),char(2)),2,'0'),'-',LPAD(convert(ceil(rand()*28),char(2)),2,'0')), Concat(PINYIN(sname),'@hotmail.com'), case ceil(rand()*3) when 1 then '网络与网站开发' when 2 then 'JAVA' ELSE 'NET' END, NOW() ); set i=i+1; end while; select * from TStudent; end
修改addStudent存储过程,插入500000条记录call addStudent(500000);
SQL语句查询×××号cardID以12345开头的学生。select * from TStudent where cardID like '12345%'
花费时间为1.27秒
alter table TStudent add index cardidIndex(cardID);
SQL语句查询×××号cardID以12345开头的学生。select * from TStudent where cardID like '12345%'
花费时间31毫秒。
schoolDB数据库索引占用的磁盘空间。
SELECT CONCAT(ROUND(SUM(index_length)/(1024*1024), 2), ' MB') AS 'Total Index Size' FROM information_schema.TABLES WHERE table_schema LIKE 'schoolDB';
查看schoolDB数据库数据占用的磁盘空间。
SELECT CONCAT(ROUND(SUM(data_length)/(1024*1024), 2), ' MB') AS 'Total Data Size' FROM information_schema.TABLES WHERE table_schema LIKE 'schoolDB';
EXPLAIN能够查看SQL查询语句的查询计划,使用索引仍是全表扫描,key显示使用的索引。explain select * from TStudent where cardid like '12345%' \G;
id: SELECT识别符,即SELECT的查询序列号,一条语句中,select是第几回出现。
select_type:所使用的SELECT查询类型,SIMPLE表示为简单的SELECT,不实用UNION或子查询。其余取值,PRIMARY:最外面的SELECT在拥有子查询时,就会出现两个以上的SELECT。UNION:union(两张表链接)中的第二个或后面的select语句 SUBQUERY:在子查询中,第二SELECT。
table:数据表的名字。按被读取的前后顺序排列。
type:指定本数据表和其余数据表之间的关联关系,表中全部符合检索值的记录都会被取出来和从上一个表中取出来的记录做联合。ref用于链接程序使用键的最左前缀或者键不是primary key或unique索引的状况。取值有system、const、eq_ref、index和All。
possible_keys:MySQL在搜索数据记录时能够选用的各个索引
key:实际选用的索引
key_len:显示MySQL使用索引的长度(使用的索引个数),当key字段的值为 null时,索引的长度就是null。
ref:给出关联关系中另外一个数据表中数据列的名字。
rows:MySQL在执行查询时预计会从数据表里读出的数据行的个数。
extra:提供与关联操做有关的信息。
一个包含查询所需的字段的索引称为覆盖索引(covering index)。MySQL只须要经过索引就能够返回查询所须要的数据,而没必要在查到索引以后进行回表操做,减小IO,提供效率。
经过EXPLAIN查看SQL语句的执行计划时,在EXPLAIN的Extra列出现Using Index提示时,说明SQL查询使用覆盖索引。
Tstudent表cardID列建立了索引,SQL语句查找的列是cardID,查找条件也是cardID,就会使用cardID索引进行查找,不须要扫描表的页。explain select sname from TStudent where sname like '刘%';
执行结果Extra 出现using index,说明是使用覆盖索引查找。
在MySQL中的ORDER BY有两种排序实现方式:
A、利用有序索引获取有序数据
B、文件排序
使用EXPLAIN分析SQL查询时,利用有序索引获取有序数据显示Using index。而文件排序显示Using filesort。explain select email from TStudent order by email;
email列没有索引,SQL语句的查询计划能够看到Extra是using filesort,说明是将结果在内存中排序,须要额外时间开销。
给Email列添加索引后,
alter table TStudent add index emailIndex(email); explain select email from TStudent order by email;
再次执行,能够看到Extra列是Using index,说明使用索引排序,没有额外时间开销。