SQL调优

一、在表中建立索引

较频繁地作为查询条件的字段,唯一性不太差的字段适合建立索引,更新不太频繁地字段适合创建索引,不会出现在where条件中的字段不该建立索引。

二、查询条件中,一定不要使用select *
1、连接查询中的冲突

当在JOIN查询中使用SELECT *时,当多个表有相同名称的列时,可能会引入并发症,例如status、active、name等。

2、不需要的列会增加数据传输时间和网络开销

select * 会需要解析更多的对象、字段、权限、属性等相关内容,会给数据库造成负担,增大网络开销。* 有时会误带上如log、IconMD5之类无用的大文本字段,数据传输size会几何增涨。

3、对于无用的大字段,如varchar、blob、text 会增加io操作

长度超过728字节的时候,会先把超出的数据序列化到另一个地方,因此读取这条记录会增加一次io操作。

4、需要查询数据字典

Oracle在解析的过程中, 会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。

5、失去mysql优化器“覆盖索引”策略优化的可能性

例如,有一个表为t(a,b,c,d,e,f),其中,a为主键,b列有索引。

那么,在磁盘上有两棵 B+ 树,即聚集索引和辅助索引(包括单列索引、联合索引),分别保存(a,b,c,d,e,f)和(a,b),如果查询条件中where条件可以通过b列的索引过滤掉一部分记录,查询就会先走辅助索引,如果用户只需要a列和b列的数据,直接通过辅助索引就可以知道用户查询的数据。

如果用户使用select *,获取了不需要的数据,则首先通过辅助索引过滤数据,然后再通过聚集索引获取所有的列,这就多了一次b+树查询,速度必然会慢很多。

三、不要在where条件中使用左右两边都是%的like模糊查询
select * from t_order where customer like '%zhang%'

这样会导致数据库引擎放弃索引进行全表扫描。优化:尽量在字段后面使用模糊查询或使用全文索引。

select * from t_order where customer like 'zhang%'

四、尽量不要使用in 和not in,会造成全表扫描

select * from t_order where id not in (2,3)
select * from t_order1 where customer in (select customer from t_order2)

可以用exists代替

五、尽量不要使用or,会造成全表扫描

select * from t_order where id = 1 or id = 3

优化:可以用union代替or

select * from t_order where id = 1
union
select * from t_order where id = 3

六、尽量不要在 where 子句中对字段进行表达式操作,这样也会造成全表扫描

select id from t_order where num/2=100

应改为

select id from t_order where num=100*2

七、where条件里尽量不要进行null值的判断,null的判断也会造成全表扫描

select * from t_order where score is null

优化:给字段添加默认值,对默认值进行判断。

select * from t_order where score = 0

八、尽量不要在where条件中等号的左侧进行表达式、函数操作,会导致全表扫描

select * from t_order2 where score/10 = 10
select * from t_order2 where substr(customer,1,5) = 'zhang'
select * from tb_order where DATE_FORMAT(dt,'%Y%m%d') ='20220207'

优化:将表达式.函数操作移动到等号右侧

select * from t_order2 where score = 10*10
select * from t_order2 where customer like 'zhang%'
select * from tb_order  where  dt=DATE_FORMAT('20220207','%Y-%m-%d')

九、尽量不要使用where 1=1的条件

有时候,在开发过程中,为了方便拼装查询条件,我们会加上该条件,这样,会造成进行全表扫描。

select * from t_order where 1=1

优化:如果用代码拼装sql,则由代码进行判断,没where加where,有where加and。如果用mybatis,请用mybatis的where语法。

十、查询条件两边数据类型不一致索引失效

例如我们在订单表tb_order建立了索引idx_order_id,order_id字段类型为varchar在查询时如果使用where order_id= 20220207123654100,这样的查询方式会直接造成索引失效。

要让索引生效,正确的用法为

where order_id=’20220207123654100’

再来看一个例子:

explain select * from tb_user  where phone = 12345678936
explain select * from tb_user  where phone = '12345678936'

从这两条SQL执行的结果我们可以看出,执行第一条SQL没有使用到索引,而执行第二条SQL时使用到了索引。这是为什么呢?我们需要先了解下mysql索引优化器工作的原理。选择索引是优化器工作,优化器工作有自己的一套规则,如果等号两边的数据类型不一致,则会发生隐式转换。基于这条规则,我们回过头看看

explain select * from tb_user where phone = 12345678936;

这条SQL语句执行时就会变为

explain select * from tb_user where cast(phone as signed int) = 12345678936;

由于对索引列进行了函数操作,所以才导致索引失效,从而全表扫描了。

十一、程序要尽量避免大事务操作,提高系统并发能力

即将事务的范围尽量缩小,可提高性能。

十二、一个表的索引数最好不要超过6个

如果索引太多的话,就需要考虑一下那些不常使用到的列上建的索引是否有必要。

十三、尽量使用多表连接(join)查询(避免子查询)

子查询效率特别低,而一般的子查询都可以由关连查询来实现相同的功能,关联查询的效率要提高很多,所以建议在数据查询时避免使用子查询(尤其是在记录很多时),而最好用关联查询来实现。

分析MySQL的SQL性能瓶颈,可借助explain来分析优化。推荐阅读一张图彻底搞懂MySQL的 explain

十四 循环里不要调用DB执行SQL

避免在循环里写调用SQL的代码,而是在循环外批量执行。

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

推荐阅读更多精彩内容