2.技术-mysql(二)-索引-索引优化

一.背景

    根据第一节索引的原理分析,常见一些优化建议不走索引的原因。

    通过这些案例的分析,我们可以做到自己识别是否走索引。

二. 分析常见不走索引的写法


1>.  查询条件中含有函数或表达式

   正常走索引:select * from t_user where id=2+1

条件字段中带有函数或表达式:select * from t_user where id+1=2

分析原因:

       字段经过函数或表达式处理后返回的是一个新的值,这个值与索引中的数据已经是两个东西,所以没有办法去索引中寻找。至于数据库对表达式这种未做优化,可能还是希望开发人员尽可能的表达式在值中不要在字段中。

2>.隐式转换(本质还是1)

     这个容易被忽略也是最常见的。

    正常情况:select * from t_user where age='2'   (age是字符类型普通索引)


  不走索引情况:select * from t_user where age=2  (这里mysql做了隐式转换)

分析:

      隐式转换的本质还是对字段使用了函数,select * from t_user where age=2  这个语句会被转换为:select * from t_user where to_number(age)=2  执行。

这里需要注意的是:对id值是否带引号,都走索引。

原因是:对字段未做隐式转换,这种场景是对后面的值隐式转换为浮点型。

ps:

mysql隐式转换总结如下:

不同类型全都转换为浮点型。

如果字段是字符,条件是整型,那么会把表中字段全都转换为整型。

3>.OR一个未索引的字段

分析:

   因为or了一个未索引的字段,即使条件有id,但是还是需要全表扫描。

4>.is null  &  is not null

not null字段都不走索引讨论无意义,这里只讨论可null字

分析:

   is null和is not null 根据数据量和null值的数量不同以及返回的结果是否不需要回查数据,可能会走索引。mysql会估算全表扫描和搜索引的代价来选择是否走。

5>.最左前缀匹配

    这个比较好理解,因为组合索引是按照顺序存储的。匹配不到前面的没法找。而且唯一性高的放在前面。

    分析:这一点结合索引的存储结构就可以理解,所以理论知识比一些总结的经验更实在。

6>.order by

   同4,会根据代价看是否走。

   不走的情况:


     1>.用来查找结果的索引(key2) 和 排序的索引(key1) 不一样.

     2>.排序字段在不同的索引中,无法使用索引排序.

     3>.排序字段顺序与索引中列顺序不一致,无法使用索引排序,比如索引是 key idx_kp1_kp2(key_part1,key_part2).

     4>.order by中的升降序和索引中的默认升降不一致无法使用索引排序.

     5>.ey_part1是范围查询,key_part2无法使用索引排序.

     6>.对于还有join的关联查询,排序字段并非全部来自于第一个表.

附 Mysql select执行过程.

1. 客户端发送一条查询给服务器;

2. 服务器先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;

3. 服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划;

4. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询;

5. 将结果返回给客户端。

查询处理的顺序如下:

1)FROM:对FROM子句中的左表和右表执行笛卡儿积(Cartesian product),产生虚拟表VT1。 

2)ON:对虚拟表VT1应用ON筛选,只有那些符合的行才插入虚拟表VT2中。 

3)JOIN:如果指定了OUTER JOIN(如LEFT OUTERJOIN、RIGHT OUTER JOIN),那么保留表中未匹配的行作为外部行添加到虚拟表VT2中,产生虚拟表VT3。如果FROM子句包含两个以上表,则对上一个连接生成的结果表VT3和下一个表重复执行步骤1)~步骤3),直到处理完所有的表为止。 

4)WHERE:对虚拟表VT3应用WHERE过滤条件,只有符合的记录才**入虚拟表VT4中。此时数据还没有分组,所以不能在where中出现对统计的过滤 

5)GROUP BY:根据GROUP BY子句中的列,对VT4中的记录进行分组操作,产生VT5。在该阶段会将NULL值分到同一个分组中。 

6)CUBE|ROLLUP:对表VT5进行CUBE或ROLLUP操作,产生表VT6。 

7)HAVING:对虚拟表VT6应用HAVING过滤器,只有符合的记录才插入虚拟表VT7中。

8)SELECT:第二次执行SELECT操作,选择指定的列,插入到虚拟表VT8中。 

9)DISTINCT:去除重复数据,产生虚拟表VT9。 

10)ORDER BY:将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10。如果不指定排序,数据并非总是按照主键顺序进行排序的。NULL被视为最小值 

11)LIMIT:取出指定行的记录,产生虚拟表VT11,并返回给查询用户。LIMIT n, m的效率是十分低的,一般可以通过在where条件中指定范围来优化 where id> ? limit 10

附:Explain命令解释

explain命令是查看查询优化器(Optimizer)是如何执行查询语句的。

explain输出字段

id select_type table type possible_keys key key_len ref rows Extra

id :来体现执行顺序。单张表该值为1,多张表会出现多条记录,id值越大越先被执行,id相同时执行顺序由上至下。

select_type :

simple:查询中不包含子查询或者union 

SUBQUERY:包含在SELECT列表中的子查询中的SELECT(不在From字句中) 

UNION:中的第二个或后面的SELECT语句,UNOIN中的第一个SELECT显示为PRIMARY。 

PRIMARY:查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY 

DERIVED:包含在FROM子句的子查询中的SELECT,MySQL会递归执行并将结果放到一个临时表中。 

UNION RESULT:用来从UNION的匿名临时表检索结果的SELECT被标记为UNION SELECT。

table :显示这一行数据正在访问哪张表,若在查询中为select起了别名,则显示别名,如果为(x是个数字,可以理解为第几步执行的结果)

type:访问类型

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

system:这是const类型的特例,很少出现,可以忽略不计

const:表示通过索引一次就找到了(唯一索引或只有一条数据的索引)。

eq_ref:通过唯一索引扫描整个表。

ref:非唯一性索引扫描

range:where语句中出现了bettween、<、>、in等的查询

index:index与ALL区别为index类型只遍历索引树。

ALL: 全表扫描。 

possible_keys 

查询可以使用哪些索引。

keys 

MySQL实际采用哪个索引。

key_len 

使用的索引的长度,越短越好

key_len的长度计算公式:

varchr(10)变长字段且允许NULL    =  10 * ( character set:utf8=3,gbk=2,latin1=1)+1(NULL)+2(变长字段)

varchr(10)变长字段且不允许NULL =  10 *( character set:utf8=3,gbk=2,latin1=1)+2(变长字段)

ref 

如果索引的那一列被使用了,如果可能,是一个常量const

rows 

大致估算出找到所需的记录所需要读取的行数

Extra 

Using index: 从索引中就可以查询到最终需要的信息,不需要再读取表。 

Using where :表示优化器需要通过索引回表查询数据

Using temporary: 对查询结果排序时使用了临时表,常见于order by 和 group by

Using filesort: MySQL中无法利用索引完成的排序操作称为”文件排序”

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容

  • MYSQL 基础知识 1 MySQL数据库概要 2 简单MySQL环境 3 数据的存储和获取 4 MySQL基本操...
    Kingtester阅读 7,797评论 5 116
  • 转 # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    吕品㗊阅读 9,717评论 0 44
  • 观其大纲 page 01 基础知识 1 MySQL数据库概要 2 简单MySQL环境 3 数据的存储和获取 4 M...
    周少言阅读 3,156评论 0 33
  • 已是残颜容,奈何流水细消磨。总也不思度。该与谁,契阔成说? 俯首看蹉跎,流年岁月再婆娑。梦里失阡陌。别驻足,相识而...
    观心魄阅读 478评论 2 5
  • 搬来出租屋的第三天,我和达总就开始办网,可是不知道什么原因,当天晚上都网就开始不能用了,于是我们不得不叫维修员过来...
    苏两柒阅读 190评论 0 0