sql执行顺序

了解索引优化需要首先知道搜吸引的执行顺序。

书写顺序如下:



select[distinct]  
from  
join(如left join)  
on  
where  
group by  
having  
union  
order by  
limit



实际执行顺序如下:



from  
on  
join  
where  
group by  
having  
select  
distinct  
union  
order by





mysql 索引顺序ASC DESC mysql索引执行顺序_mysql 索引顺序ASC DESC


sql执行顺序


七种JOIN


mysql 索引顺序ASC DESC mysql索引执行顺序_数据_02

left /right/inner join


mysql 索引顺序ASC DESC mysql索引执行顺序_mysql 索引顺序ASC DESC_03


mysql 索引顺序ASC DESC mysql索引执行顺序_执行顺序_04

mysql不支持full outer join语法,使用union连接


索引

概念:

数据库内存储着数据本身之外,还存储着特定查找算法的数据结构,该数据结构以某种方式指向数据。

索引本质就是高效获取数据的数据结构。该数据结构两大功能:排序和查找(where后面的查找和order by后面的排序)。


mysql 索引顺序ASC DESC mysql索引执行顺序_mysql 索引顺序ASC DESC_05

左边为数据(包含物理地址和存储的数据),右边为索引

索引为二叉查找树,每个节点包含索引键值和指向对应数据的物理地址的指针。MySQL中的索引的存储类型有两种:BTREE、HASH

优缺点:

  • 优点:
  • 加快数据的查询速度
  • 降低排序CPU消耗
  • 缺点:
  • 创建索引和维护索引要耗费时间,并且随着数据量的增加所耗费的时间也会增加
  • 索引也需要占空间,如果有大量的索引,索引文件可能会比数据文件更快达到上限值
  • 当对表中的数据进行增加、删除、修改时,索引也需要动态的维护,降低了数据的维护速度

使用原则

  • 对经常更新的表就避免对其进行过多的索引,对经常用于查询的字段应该创建索引,
  • 数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果
  • 在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可以建立索引

索引分类


mysql 索引顺序ASC DESC mysql索引执行顺序_mysql 索引顺序ASC DESC_06


  • 单值索引(普通索引,唯一索引,主键索引)

一个索引只包含单个列,但一个表中可以有多个单列索引。

唯一索引:索引列中的值必须是唯一的,但是允许为空值。
主键索引:是一种特殊的唯一索引,不允许有空值。

  • 复合索引

在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。


create index id_name_subject on teacher(name, subject);
//mysql会先比较name,如果name一样,再比较subject。


  • 唯一索引
  • 全文索引

全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用。

在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有"你是个靓仔,靓女 ..." 通过靓仔,可能就可以找到该条记录

  • 空间索引

空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在创建空间索引时,使用SPATIAL关键字。要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL聚集索引(clustered index):聚集索引决定数据在磁盘上的物理排序,一个表只能有一个聚集索引,一般用primary key来约束(t_user场景中,uid上的索引)。

非聚集索引(non-clustered index):它并不决定数据在磁盘上的物理排序,索引上只包含被建立索引的数据,以及一个行定位符row-locator,这个行定位符,可以理解为一个聚集索引物理排序的指针,通过这个指针,可以找到行数据(查找年轻MM的业务需求):

select uid from t_user where age > 18 and age < 26;

age上建立的索引,就是非聚集索引。


其他概念

最左前缀匹配(leftmost prefix)

一个表的a,b,c三个字段建了索引:


create index id_a_b_c on foo(a, b, c);


那么当你where条件是a或者a、b或者a、b、c时,都可以命中索引,除此之外,都不能命中索引,比如a、c,或者b、c等(带头大哥不能死,中间兄弟不能断)

聚簇索引和二级索引:

覆盖索引:

当要select的字段,已经在索引树里面存储,那就不需要再去检索数据库。


//a、b、c三个字段建了复合索引,下面就可以覆盖索引
select b,c from foo where a = "xxx";



索引失效场景

  1. WHERE字句的查询条件里有不等于号/大于小于(WHERE column!=…)造成失效;
  2. 对索引进行运算,类型转换等,将造成失效;
  3. JOIN操作中(需要从多个数据表提取数据时),MYSQL只有在主键和外键的数据类型相同时才能使用索引,否则即使建立了索引也不会使用;
  4. 范围之后全失效;
  5. isnull/isnotnull也无法使用索引;
  6. 如果WHERE子句的查询条件里使用了比较操作符LIKEREGEXPMYSQL只有在搜索模板的第一个字符不是通配符的情况下才能使用索引(如果查询条件是LIKE 'abc%',MYSQL将使用索引;如果条件是LIKE '%abc',MYSQL将不使用索引)使用索引覆盖会避免两边%引起的索引失效。
  7. 如果某个数据列里包含着许多重复的值,就算为它建立了索引也不会有很好的效果。比如说,如果某个数据列里包含了净是些诸如“0/1”“Y/N”等值,就没有必要为它创建一个索引。
  8. 如果条件中有or(并且其中有or的条件是不带索引的),即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)。注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
  9. 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

练习

分组之前必排序


mysql 索引顺序ASC DESC mysql索引执行顺序_mysql 索引顺序ASC DESC_07

建立顺序c1,c2,c3,c4

mysql 索引顺序ASC DESC mysql索引执行顺序_执行顺序_08


mysql 索引顺序ASC DESC mysql索引执行顺序_执行顺序_09


mysql 索引顺序ASC DESC mysql索引执行顺序_mysql 索引顺序ASC DESC_10


mysql 索引顺序ASC DESC mysql索引执行顺序_字段_11


mysql 索引顺序ASC DESC mysql索引执行顺序_字段_12