说起数据库优化,大部分人想到是索引。
什么是索引?
1)简单了解索引是一种算法,
2)根据数据之间排列规律,将具有相同特征的【数据行的位置】保存在同一个节点上然后将这些节点安排数据大小排列规律安放在同一个二叉树上
索引分类:
1.普通索引
1)单列索引
alter table 【表名】 add index 索引名(字段名);
2)多列索引
alter table 【表名】 add index 索引名(字段名1,字段名2);
2.主键索引
1) alter table [表名] add primary key (字段名)
3.唯一索引
1)alter table [表名] add unique (字段名)
4.非空索引
create table tt(
ename varchar(20) not null
)
5.外键索引
6.全文索引
create table test_1(
content varchar(255)
fulltext(content)#全文索引
);
索引管理:
1.查看某张表中拥有索引信息
show index from 表名
追加索引
alter table 表名 add 【索引名称】(子段)
2.删除表中指定的索引
drop index 【索引名称】 on 表名
explain 【查询语句】:通过【执行解释计划】判断当前查询的速度。
例子:explain selct * from 表名;
explain包含的参数的解释:
【参数 id】:MySql对于当前查询语句,所生成内部的编号
【参数 table 】:本次查询获得的数据来源
【参数 select_type】:描述查询的类型 --------------重点
【Simple】:当前查询是一个简单的查询,没有包含【子查询】和union联合查询
【subquery】:表示当前查询是一个不依靠外部条件的独立子查询
【depend subsquery】:表示当前查询是一个依靠外部条件的子查询
【union】:表示当前查询是一个联合查询
【DERIVED】:表示本次查询针对的表是一个临时表
【参数 type】: 表示本次查询的效率.----------重点
效率从低到高依次为: All,index,range,ref,const
在一次查询过程中,最低的标准应该range这个级别,最理想的级别const,避免 all级别
[ALL]:本次查询过程中,没有使用索引,进行的全表的数据扫描。此时表中的数据行越多,查询消耗的时间也越多。
[index]:本次查询过程中,没有使用索引,但是在数据展示过程中,使用了索引进行排序处理,此时节省展示数据时排序的时间,避免在排序是进行全表扫描
[range]:本次查询过程中,使用索引,根据数据大小区间进行索引操作 【>,>= <= between and in】
[ref]:本次查询过程中,使用【非主键索引】,根据索引查询的数据避免全表扫描
[const]:本次查询过程中,使用【主键索引】
【参数 possible_keys】:表示本次查询中【可能使用到的索引】,在这个属性中出现的索引名称。未必会使用
【参数 key】:表示本次查询中,实际使用的索引名称
【参数 key_len】:索引字段的内容的长度,索引字段数据长度应该越短越好
【参数 rows】:表示本次查询时,遍历了多少条数据,才定位指定数据行
在下面几种情况索引会失效:
规则1 :where 后面查询条件如果是通过 or连接的,此时索引字段将【无效】
explain select * from emp where empno=7788 and sal<=1000
[type:ref rows:1]
explain select * from emp where empno=7788 or sal<=1000
[type:all rows:14]
规则2 : 使用'!='时,也会引起索引【失效】
explain select * from emp where sal<=1000
[type:range rows:2]
explain select * from emp where sal !=1000
[type:all rows:14]
规则3:使用 not in 时导致索引失效
explain select * from emp where sal in(1000,1500)
[type:range rows:2]
explain select * from emp where sal not in (1000,1500)
[type:all rows:14]
规则4:使用模糊查询时,如果是'内容%'查询时,此时索引是生效
使用模糊查询时,如果是'%内容'或者 '%内容%',此时索引将【失效】
explain select * from emp where ename like 's%';
[type:range rows:2]
explain select * from emp where ename like '%s%';
[type:all rows:14]
explain select * from emp where ename like '%s';
[type:all rows:15]
规则5: 在使用联合索引字段时,如果当前索引关联的字段不是where后面的第一个条件此时导致索引【失效】
【在使用联合索引字段时,如果当前索引关联的字段不是where后面的第一个条件
此时如果使用联合索引中第一个字段,此时索引有效的
如果使用联合索引中第二个字段,此时索引无效】
drop index index_1 on emp;
select * from emp where ename='smith' and sal<=1000
[type:ref rows:1]
select * from emp where job='CLERK' and sal<=1000
[type:range rows:2]
explain select * from emp where sal<=1000 and ename='smith'
【type:range rows:】
select * from emp where sal<=1000 and job='CLERK'
【type:all rows:14】
规则6: 如果索引字段是字符串类型,在where进行判断时,如果赋值内容由''括起来,此时索引是有效的,反之是无效的
explain select * from emp where ename='123'
[type:ref rows:1]
explain select * from emp where ename=123
[type:all rows:14]
explain select * from emp where ename=smith---error
规则7:关于这几个(> >= < <= in between and)运算符,何时回导致索引有效,何时导致索引无效
alter table emp add index index_1(sal)
现象
explain select * from emp where sal <=1000
[type:range rows:2]
explain select * from emp where sal <=3000
[type:all rows:14]
理论:Mysql数据库服务器中,如果某次查询使用了索引,但是遍历的数据行超过表中50%以上。此时Mysql将不会使用索引,而改为全表查询。
使用中遇到的问题:
创建新的索引并不是每次都是简单的用主键,也需要看你查询这个表中数据的关系。多表连接查询的时候有一个表中的数据远比其他表中的多,导致数据在前台展示的时候会等很长时间,如果调整sql语句会改动很多功能而且工作量很大,查看其它的sql语句发现可以用索引进行优化。查看数据库发现这张表(推广人表)里也有主键索引。一个推广人可以有很多个被推广人,但是被推广人只能有一个推广人(一对多,多对一问题),这时候 追加被推广人索引,就能解决查询效率慢的问题。所以建立索引的时候要看下表中的关系。