SQL性能优化

SQL性能优化

SQL性能优化

一、SQL的执行顺序

顺序:FROM——ON——JOIN——WHERE——GROUP BY——SUM、COUNT——HAVING——SELECT——DISTINCT——ORDER BY——LIMIT

与写SQL的顺序不同,SQL的执行顺序并不是从select开始,而是从from开始

1、FROM:先去获取from里面的表,拿到对应的数据,生成虚拟表1。

2、ON:对虚拟表1应用ON筛选,符合条件的数据生成虚拟表2。

3、JOIN:根据JOIN的类型去执行相对应的操作,获取对应的数据,生成虚拟表3。

4、WHERE:对虚拟表3的数据进行条件过滤,符合记录的数据生成虚拟表4。

5、GROUP BY:根据group by中的列,对虚拟表4进行数据分组操作,生成虚拟表5。

6、CUBE|ROLLUP(聚合函数使用):主要是使用相关的聚合函数,生成虚拟表6。

7、HAVING:对虚拟表6的数据过滤,生成虚拟表7,这个过滤是在where中无法完成的,同时count(expr)返回不为NULL的行数,而count(1)和count(*)是会返回包括NULL在内的行数。

8、SELECT:选择指定的列,生成虚拟表8。

9、DISTINCT:数据去重,生成虚拟表9。

10、ORDER BY:对虚拟表9中的数据进行指定列的排序,生成虚拟表10。

11、LIMIT:取出指定行的记录,生成虚拟表11,返回给查询用户。

以上是SQL各关键词的执行顺序,如果在一条SQL语句里面你没有用到某个关键词那就不会被执行了。理解SQL的逻辑执行顺序对我们在实际写SQL的过程中也会有帮助的。

二、执行计划——EXPLAIN

执行计划,是SQL在数据库中执行时的表现情况,通常用于SQL性能分析,优化等场景。在MySQL使用 explain 关键字来查看SQL的执行计划。

基本的语法:EXPLAIN(select * from table)

在常规SQL语句前面加上EXPLAIN即可

运行结果:

image

参数解释:

1、id:数字越大越先执行,一样大则从上往下执行,如果为NULL则表示是结果集,不需要用来查询。

2、select_type:

simple:不需要union的操作或者是不包含子查询的简单select语句。

primary:需要union操作或者含有子查询的select语句。

union:连接两个select查询,第一个查询是dervied派生表,第二个及后面的表select_type都是union。

dependent union:与union一样,出现在union 或union all语句中,但是这个查询要受到外部查询的影响。

union result:包含union的结果集。

subquery:除了from字句中包含的子查询外,其他地方出现的子查询都可能是subquery。

dependent subquery:与dependent union类似,表示这个subquery的查询要受到外部表查询的影响。

derived:from字句中出现的子查询,也叫做派生表,其他数据库中可能叫做内联视图或嵌套select。

3、table

表名,如果是用了别名,则显示别名

4、type

依次从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引。

system:表中只有一行数据或者是空表。

const:使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。

eq_ref:出现在要连接过个表的查询计划中,驱动表只返回一行数据,且这行数据是第二个表的主键或者唯一索引,且必须为not null,唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref。

ref:不像eq_ref那样要求连接顺序,也没有主键和唯一索引的要求,只要使用相等条件检索时就可能出现,常见与辅助索引的等值查找。

fulltext:全文索引检索,要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引。

ref_or_null:与ref方法类似,只是增加了null值的比较。实际用的不多。

unique_subquery:用于where中的in形式子查询,子查询返回不重复值唯一值。

index_subquery:用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。

range:索引范围扫描,常见于使用>,<,is null,between ,in ,like等运算符的查询中。

index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and ,or的条件使用了不同的索引。

index:索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询、可以使用索引排序或者分组的查询。

all:这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。

5、possible_keys:查询可能使用到的索引。

6、key:查询真正使用到的索引。

7、key_len:用于处理查询的索引长度。

8、ref:常数等值查询显示const,连接查询则显示表的关联字段。

9、rows:执行计划中估算的扫描行数,不是精确值。

10、filtered:表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例。

11、extra:该字段信息较多,这里就不一一叙述了。

在实际的使用过程中我们需要重点去关注type、key、key_len、rows、extra这几个参数,type要努力优化到range级别,all要尽量少的出现,在查询的过程中要尽量使用索引,提高效率,在extra里面出现Using filesort, Using temporary是不太好的,要去优化提高性能。

三、优化TIPS

1、尽量少用select *

因为会增加不必要的消耗,select 后面直接加上需要的字段名。

2、IN 包含的值不应过多

IN本身这个操作消耗就比较高,如果IN里面是连续的数值,则可以用between代替,IN里面的字段如果是添加了索引,效率还是可以的,目前测试一万以内还是可以,但是超过了结果可能会有点爆炸,不要问我为什么

3、in和exists、not in 和 not exists

exists以外层表为驱动表,先被访问,适合于外表小而内表大的情况。

in则是先执行子查询,适合外表大而内表小的情况,

一般情况是不推荐使用not in,因为效率非常低,

eg:

1)select * from table_a where table_a.id not in (select table_b.id from table_b)

2)select * from table_a left join table_b on table_a.id = table_b.id where table_b.id is null

语句2的效率是要高于语句1的,SQL的结果是获取到在table_a中存在但是table_b中不存在的数据,如果直接用not in是不走索引的,而且在table_b比较大的时候效率会非常低,实际工作中我试了一下直接not in,然后数据达到一万条的时候大概需要150S左右才能查出数据(感谢DBA和运维不杀之恩),我采取的方法是,先查出两个表的交集,这样得到的表会小很多,而且是用的in,效率会高很多,然后再用not in,最终的效果也是一样,但是时间只要2.56S,然后采取语句2的关联表来处理,时间缩短到了1.42S,基本上效率是比较高的,当然理想的是在1S内。

4、尽量少用or,同时尽量用union all 代替union

or两边的字段如果有不走索引的会导致整个的查询不走索引,从而导致效率低下,这时可以使用union all或者union,而两者的区别是union是将两个结果合并之后再进行唯一性的过滤操作,效率会比union all低很多,但是union all需要两个数据集没有重复的数据。

5、分段和分页查询

在扫描行数较多的情况下可以采取分段查询,循环遍历,结果合并处理,

使用合理的分页方式,在数据表量级逐渐增加的时候,limit分页查询的效率会降低。

1)select id,col from table limit 888888,1000

2)select id,col from table where id > 888887 limit 1000

取前一页的最大行数的id,然后根据这个id来限制下一页的起点。

6、不建议使用%前缀模糊查询

like "%abc"和like "%abc%"会导致索引失效而进行全文搜索。

如果你还有什么比较好的优化tips欢迎分享!

</article>

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

推荐阅读更多精彩内容