提高数据库性能,索引是最物美价廉,不加内存,不改程序,不用调sql,只要执行个正确的‘create index’,查询速度就可能提高百倍千倍,诱惑力极大。但没免费的晚餐,查询速度的提高是以插入、更新、删除的速度为代价的,这些写操作,增加了大量的I/O。 以空间换时间。
索引(Index)是帮助DBMS(数据库)高效获取数据的数据结构,索引是为了加速对表中数据行的检索而创建的一种分散的存储结构。如同:字典的目录。
比如:根据id查找数据,如果没有使用索引,就会从第一行记录开始扫表,直到找到想要的ID为止,当数据量比较大,恰好想要的数据在最后一条,那么查询速度就会非常慢:如: where id = 9
使用索引:Id列使用索引后,Mysql会为id列维护一个索引结构,数据检索的时候就从索引中进行检索,能大大提高检索速度。举例:
mysql中索引的分类:
索引方式分为:BTREE 和 Hash
Hash方式底层使用的是Hash表算法,时间复杂度是n(1) ,一次IO就能查询到结果,打算Hash的场次是无序的,有如下缺点:
对于主键默认会创建主键索引,其他列创建的索引就叫辅助索引,也叫二级索引,辅助索引的叶子节点存储的是主键索引的键值,这就意味着辅助索引需要查询两个B+Tree.
这里有2个概念:
查看隐藏rowId:Select _rowid from t_user
为什么用B+Tree,为什么不使用其他数据结构,比如数组?链表?AVL-Tree,B-Tree 而要使用B+Tree:
有序数组:在查询的时候性能很高,可以二分查找,但是修改删除数据的时候会移动数组下标,性能比较差,这种结构只适合静态数据
链表:链表的删除,修改性能高,打算查询性能极差
综合上面的优势,有没有支持二分查找的链表结构呢?有:就是二叉查找树。
二叉查找树:它的查询性能和树高有关系,二叉树树高越高,查询越慢,而且在子树极端不平衡的情况下二叉树可能会变成链表,性能比较差。
AVL-Tree 平衡二叉树结构:平衡二叉查找树,如果每个节点放一个键值,数据地址,子树的引用 ,InnoDB节点默认最大存储为16KB,那AVL-Tree平衡二叉树的节点存储数据是远远达不到16K的,浪费了大量的存储空间。如果数据量大,就意味着树高非常高,查找一个KEY就需要遍历很多的节点,时间复杂度大,I/O次数非常高,所以查询是比较慢的。
B-Tree : B-Tree:多路平衡查找树:多叉树意味着每个节点可以存储更多的KEY,多叉树可以解决每个节点空间浪费问题,也可以解决树高问题从而达到较少IO次数提高效率。
但是Btree性能已经不错了,但是还不够优化,InnoDB没有使用BTree,而是使用一个更优化的树:B+树
B+Tree : 子节点存储数据,而且是有些了,相比BTree来说有如下优势:
myisam的数据和索引是分开的,所以树的节点指向的是数据的地址。数据存储在 course.MYD文件,索引存储在course.MYI文件中,coursr.frm是表结构定义文件,所以Myiasm的索引不存储数据,而是存储数据的磁盘地址。
下面是MyIsam索引结构,由于数据和索引是分开存放的,所以叶子节点存储的是数据的磁盘地址,而不是数据。
索引分类:普通索引/唯一索引/主键索引/全文索引,普通索引:允许重复的值出现,一般来说,普通索引的创建,是先创建表,然后在创建普通索引
create index 索引名 on 表 (列1,列名2,...);
alter table 表名add index 索引名(列1,列名2,..);
案例:
create table aaa(id int unsigned,name varchar(32));
create index nameIndex on aaa(name);
alter table aaa add index index1(name);
除了不能有重复的记录外,其它和普通索引一样 ,当表的某列被指定为unique约束时,这列就是一个唯一索引
create table bbb(id int primary key auto_increment , name varchar(32) unique);
这时, name 列就是一个唯一索引,也可以在创建表后,再去创建唯一索引
create unique index 索引名 on 表名 (列1,列2,..);
alter table 表名add unique index 索引名 (列1,列2,..);
create table ccc(id int primary key auto_increment, name varchar(32));
注意:unique字段可以为NULL,并可以有多NULL, 但是如果是具体内容,则不能重复.主键字段,不能为NULL,也不能重复.
是随着设定主键而创建的,也就是把某个列设为主键的时候,数据库就会給改列创建索引。这就是主键索引.唯一且没有null值
create table ddd(id int unsigned primary key auto_increment ,name varchar(32) not null defaul ‘’);
这时id 列就是主键索引. 如果你创建表时,没有指定主键,
alter table 表名 add primary key (列名);
举例:
create table eee(id int , name varchar(32) not null default ‘’);
alter table eee add primary key (id);
用来对表中的文本域(char,varchar,text)进行索引, 全文索引针对MyISAM有用
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body)
)engine=myisam charset utf8;
create fulltext index 索引名 on 表名(列1,列2);
alter table 表名add fulltext index 索引名 (列1,列2);
比如:
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT
)engine=myisam charset utf8;
Alter table article add fulltext index title_body_fulltext_index(title,body);
show index from 表名
alter table 表名 drop index 索引名;
alter table 表名 drop primary key 删除主键。 [主键定义为auto_increment时不能删除]
先删除后添加=修改
根据索引列的多少分为复合索引(联合索引/组合索引)和普通索引
alter table dept add index my_indx (dname,loc);
dname 左边的列,loc就是 右边的列
测试案例:
explain select * from dept where dname='aaa' 会使用到索引
测试案例:
explain select * from dept where loc='aaa' 就不会使用到索引
对于使用like的查询,查询如果是%aaa’不会使用到索引而‘aaa%’会使用到索引
explain select * from dept where dname like '%aaa' 不能使用索引
explain select * from dept where dname like 'aaa%' 使用索引.
所以在like查询时,‘关键字’的最前面不能使用 % 或者 _这样的字符.,如果一定要前面有变化的值,则考虑使用 全文索引->lucene或Es
如果条件中有or,有条件没有使用索引,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须单独使用时能使用索引. 全部能够单独使用才能使用
explain select * from dept where dname = 'aaa'; //如果使用索引
explain select * from dept where loc = 'aaa'; //如果不能使用索引
select * from dept where dname=’xxx’ or loc=’xx’; //不能使用索引,它没办法从两个索引树种去检索
如果列类型是字符串,那一定要在条件中将数据使用引号引用起来。否则不使用索引。
expain select * from dept where dname=’111’;
expain select * from dept where dname=111;(数值自动转字符串)
expain select * from dept where dname=qqq; 报错
也就是,如果列是字符串类型,无论是不是字符串数字就一定要用 ‘’ 把它包括起来.
select xx,oo from table force index(索引名) where xxx = xxxx;(强制使用主键)