索引用于快速找出在某个列中有一特定值的行。不使用索引,MySQL必须从第1条记录开始而后读完整个表直到找出相关的行,还须要考虑每次读入数据页的IO开销。而若是采起索引,则能够根据索引指向的页以及记录在页中的位置,迅速地读取目标页进而获取目标记录。mysql
大多数状况下都(默认)采用B树来构建索引。只是空间列类型的索引使用R-树,而且MEMORY表还支持hash索引。B树是平衡多叉树,每一个节点存放多少个值取决于值所占的空间,这与每一张数据页存放多少条记录与记录信息量有关同理。节点中的值是以非降序进行排列的,节点中的值老是小于等于指向它的结点中的值。sql
MySQL使用B树构造索引的状况下,是由叶子指向具体的页和记录的。而且一个叶子有一个指针指向下一个叶子。函数
使用索引须要注意:优化
⑴只对WHERE和ORDER BY须要查询的字段设置索引,避免无心义的硬盘开销;google
⑵组合索引支持前缀索引;spa
⑶更新表的时候,如增删记录,MySQL会自动更新索引,保持树的平衡;所以更多的索引意味着更多的维护成本设计
索引的字段类型问题指针
索引分四类:htm
index ----普通的索引,数据能够重复排序
fulltext----全文索引,用来对大表的文本域(char,varchar,text)进行索引。语法和普通索引同样。
unique ----惟一索引,惟一索引,要求全部记录都惟一
primary key ----主键索引,也就是在惟一索引的基础上相应的列必须为主键
like 不能用索引?
想象一下,你在看一本成语词典,目录是按成语拼音顺序创建,查询需求是,你想找以 “一”字开头的成语(”一%“),和你想找包含一字的成语(“%一%”)
<,<=,=,>,>=,BETWEEN,IN
<>,not in ,!=则不行
原则
1,单表数据太少,索引反而会影响速度;更新很是频繁的数据不适宜建索引
2,where后的条件,order by ,group by 等这样过滤时,后面的字段最好加上索引。根据实际状况,选择PRIMARY KEY、UNIQUE、INDEX等索引,可是不是越多越好,要适度
3,联合查询,子查询等多表操做时关连字段要加索引
ps:数据量特别大的时候,最好不要用联合查询,即便你作了索引
一次查询只能用到一个索引,因此 首先枪毙 a,b各建索引方案
a仍是b? 谁的区分度更高(同值的最少),建谁!
固然,联合索引也是个不错的方案,ab,仍是ba,则同上,区分度高者,在前
where a = “xxx” 可使用 AB 联合索引
where b = “xxx” 则不可 (再想象一下,这是书的目录?)
因此,大多数状况下,有AB索引了,就能够不用在去建一个A索引了
详解:
联合索引又叫复合索引。对于复合索引:Mysql从左到右的使用索引中的字段,一个查询能够只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c). 能够支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。
两个或更多个列上的索引被称做复合索引。
利用索引中的附加列,您能够缩小搜索的范围,但使用一个具备两列的索引 不一样于使用两个单独的索引。复合索引的结构与电话簿相似,人名由姓和名构成,电话簿首先按姓氏对进行排序,而后按名字对有相同姓氏的人进行排序。若是您知 道姓,电话簿将很是有用;若是您知道姓和名,电话簿则更为有用,但若是您只知道名不姓,电话簿将没有用处。
因此说建立复合索引时,应该仔细考虑列的顺序。对索引中的全部列执行搜索或仅对前几列执行搜索时,复合索引很是有用;仅对后面的任意列执行搜索时,复合索引则没有用处。
如:创建 姓名、年龄、性别的复合索引。
create table test(
a int,
b int,
c int,
KEY a(a,b,c)
);
优: select * from test where a=10 and b>50
差: select * from test where a50
优: select * from test order by a
差: select * from test order by b
差: select * from test order by c
优: select * from test where a=10 order by a
优: select * from test where a=10 order by b
差: select * from test where a=10 order by c
优: select * from test where a>10 order by a
差: select * from test where a>10 order by b
差: select * from test where a>10 order by c
优: select * from test where a=10 and b=10 order by a
优: select * from test where a=10 and b=10 order by b
优: select * from test where a=10 and b=10 order by c
优: select * from test where a=10 and b=10 order by a
优: select * from test where a=10 and b>10 order by b
差: select * from test where a=10 and b>10 order by c
也即
select * from test where mobile = 13711112222;
但是没法用到mobile字段的索引的哦(若是mobile是char 或 varchar类型的话)
btw,千万不要尝试用int来存手机号(为何?本身想!要不本身试试)
索引包含了所需的所有值的话,就只select 他们,换言之,只select 须要用到的字段,如无必要,可尽可能避免select *
NULL会致使索引形同虚设,因此在设计表结构时应避免NULL 的存在(用其余方式表达你想表达的NULL,好比 -1?)
show index from tablename;
explain select ……;
关于explain,改天能够找个时间专门写一篇入门帖,在此以前,能够尝试 google
过早优化,一直是个很是讨厌而又时刻存在的问题,大多数时候就是由于不了解本身的系统,不知道本身系统真正的承载能力
好比:几千条数据的新闻表,天天几百几千次的正文搜索,大多数时候咱们能够放心的去like,而不要又去建一套全文搜索什么的,毕竟cpu仍是比人脑厉害太多