目录
前言
正文
1.表结构优化●
1.1拆分字段
1.2字段类型的选择
1.3字段类型大小的限制
1.4合理的增加冗余字段
1.5新建字段一定要有默认值
2.索引方面●
2.1索引字段的选择
2.2利用好mysql支持的索引下推,覆盖索引等功能
2.3唯一索引和普通索引的选择
3.查询语句方面●
3.1避免索引失效
3.2合理的书写where条件字段顺序
3.3小表驱动大表
3.4可以使用force index()防止优化器选错索引
4.分库分表●
结语
mysql的优化是我们经常都会提到的一个话题,也是重中之重,在很多大厂中会有专门的DBA来做这件事情,甚至更过分的是连应届生的招聘岗位要求上都写了需要懂一点sql优化,最近moon一直在写关于mysql的文章,包括之前写的索引相关,其实也都是为了这篇文章做个铺垫,所以你懂了吗,今天我将从表结构、索引、查询语句、分库分表这四个维度来和大家聊聊,在工作中,怎么进行sql优化?
优化sql最基本的条件时要有一张表,那么我们怎么通过一张表来达到sql语句优化的目的呢?
我们给出一个场景,想象自己是一家包子铺老板,每天都要结账,于是肯定会有一张账户余额表,来记录包子铺的总资产
CREATE TABLE `accout_balance` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`account` varchar(64) NOT NULL DEFAULT '' COMMENT '账户',
`balance` decimal(16,2) DEFAULT NULL COMMENT '余额',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
可是后来包子铺的生意做的越来越好,老板陆陆续续开了几百家店,后来居然做成了全国连锁店。
老板很开心,但是他发现了一个问题,由于生意太火爆,所以每时每刻都会有人结账,而且他们的系统越来越卡了,这是为什么?
我们来分析下:
每时每刻都会有人结账,结账后会修改accout_balance(账户余额表)的balance(余额)字段,所以这张表是一张热表,而每一次修改都会开启一个事务(update语句就相当于一个事务),所以在高并发的情况下,问题显而易见,针对同一行数据,一个事务必须要等上另一个事务执行完成之后才能执行自己的更新语句,所以越来越慢。(行锁)
那么我们怎么针对这种情况来优化呢?moon的思路是控制并发度。
我们目前的情况是几百家分店都会操作这同一行记录,那么我们就可以把这一行记录分成多行,也就是说,把账户的余额分成N份,这样每次增加的时候选择其中的一条记录增加,冲突的概率也变成了之前的N分之一。
这种优化应该是比较常见的,我们就长话短说。
比如针对UUID这种数据我们可以直接使用char(36)来作为该字段的类型,或者说在表示boolean这种数据格式的时候,我们就可以直接使用tinyint(2)作为我们的字段类型,在我们提前可预知字段的大小的时候,最好在类型上直接限制,避免浪费存储空间占用。
这点在我们公司的sql建表规范上就会明确写到。
我这里简单的举个例子,比如varchar,要使用varchar(255),这里会有几点考量:
一.255刚好会消耗一个字节的存储单元,但是256会导致消耗两个字节的存储单元。(这个针对UTF-8编码)
二.如果你要在varchar上建立索引,255会是一个完全索引,而266以上只能用到最左前缀(MySQL的每个单表中所创建的索引长度是有限制的,且对不同存储引擎下的表有不同的限制。myisam表,单列索引,最大长度不能超过1000 bytes,否则会报警,但是创建成功,最终创建的是前缀索引。innodb表,单列索引,超过 767 bytes的,给出warning,最终索引创建成功,取前缀索引(取前 255 字符)),最左前缀的弊端就是无法用到mysql提供的覆盖索引的加速功能了。
三.此外在onlineddl的时候,255以下可以用inplace的方式,256需要rebuild。(Inplace方式:这是原生MySQL 5.5,以及innodb_plugin中提供的创建索引的方式。所谓Inplace,也就是索引创建在原表上直接进行,不会拷贝临时表。相对于Copy Table方式,这是一个进步。Inplace方式创建索引,创建过程中,原表同样可读的,但是不可写。)
在我们刚开始学习mysql的时候,就会了解到数据库的三范式,而在实际的使用过程中,为了性能,我们也可以抛弃数据库的三范式。
moon在之前的公司就有这样的问题,一条sql语句要连5张表,正常一个查询下来可能要1分多钟,所以这条sql太重了,而在moon的细心观察下发现,其中两张表都只用到了其中一个字段,然后我就和DBA商量下将这两个字段冗余到了其它的两个表中(业务有关联),结果这条sql语句的执行时间就变成了十几秒。
好处如下:
1.节省空间。
大体看上去,好像设置可以为空的时候更节省空间,但实际上,他比NOT NULL要多占用一个bit的空间,用来判断该字段是否为空。
2.索引失效索引分裂
引用到null,索引会失效。还看到一个说法:空更新到非空时,如果空间不足,有可能会引起索引分裂。
3.减少因空值出现的计算错误等
count()在遇到null值时,这条记录不会计算在内。
一般情况下,可以通过慢查询日志选择出一些热sql语句,给select条件后以及where条件后的字段加索引。
select a from user where b = 5;
此时给a和b字段增加索引,这样可以利用mysql的覆盖索引加速的功能,省去了回表的过程。
select a from user where c = 5 and d > 5;
此时给c和d字段增加索引,也可以在判断的时候也能利用到索引下推的功能,也就是说mysql在判断c=5后,发现d也是索引,会直接找到d判断d>5,如果不给d增加索引此时也是需要回表的。
其次对于组合索引: (a,b)这种索引一旦建立,就不需要再给a建立索引了,mysql的最左前缀原则支持组合索引或者字符串类型的索引最左N个单位的索引建立。反之,如果你此刻建立的是(a,b)索引,但是你的业务却还需要一个b的单独索引,那么就可以考虑给b单独新建索引了。如果现在你的表中只有a索引,但是业务需求需要(a,b)索引,一定要记得,先增加索引,然后再建立索引,不然可能会导致服务挂掉。moon有个朋友的同事,在新增索引的时候,选择了先删除,后增加,这样就导致的在删除后到新增前的这段空白期,出现了很多慢查询sql,同时请求量有很大,业务无法在短时间内处理完,只能慢慢等待,最后导致服务挂掉。
如果我们能在业务意义上保证某个字段是唯一的,并且这张表又是一个经常写入数据的表,那么这里moon推荐你用普通索引,而不是唯一索引,原因如下:
一.在读取数据的时候,普通索引在查到满足第一个条件的记录后,会继续查找下一个记录,直到第一个不满足条件的记录。而唯一索引,查找到第一个满足条件的记录时,就直接停止了。这样看来其实唯一索引更好,但是实际观察来看,这种性能的差异微乎其微,况且我们还可以在查询语句上用limit 1来限制。重点是第二点。
二.在更新过程中,普通索引的更新因为不用考虑唯一性,会将这次更新操作直接写入change buffer中,之后会定期或者再次访问到这个数据页的时候持久化到磁盘当中。而唯一索引的更新不能用change bufer,原因是要在表中判断是否已经有该条记录,所以会有一个将数据页读入内存的IO操作,而IO操作又是很消耗资源的。
一.最佳左前缀法则(带头索引不能死,中间索引不能断
二.不要在索引上做任何操作(计算、函数、自动/手动类型转换),不然会导致索引失效而转向全表扫描
三.不能继续使用索引中范围条件(bettween、<、>、in等)右边的列,如:
select a from user where c > 5 and b = 4;
四.索引字段上使用(!= 或者 < >)判断时,会导致索引失效而转向全表扫描
五.索引字段上使用 is null / is not null 判断时,会导致索引失效而转向全表扫描。
六.索引字段使用like以通配符开头(‘%字符串’)时,会导致索引失效而转向全表扫描,也是最左前缀原则。
七.索引字段是字符串,但查询时不加单引号,会导致索引失效而转向全表扫描
八.索引字段使用 or 时,会导致索引失效而转向全表扫描
这里其实也是最左前缀原则。在一些后需维护开发工作中,可以观察表中的联合索引,当你新写的sql有where条件时,尽量在where条件的书写顺序按照联合索引的顺序。
join查询在有索引条件下,驱动表有索引不会使用到索引,被驱动表建立索引会使用到索引。
MySQL 表关联的算法是 Nest Loop Join,是通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复。所以,小表驱动大表所建立的连接次数也远比大表驱动小表所建立的连接次数要小的多。
可以通过EXPLAIN分析来判断在sql中谁是驱动表,EXPLAIN语句分析出来的第一行的表即是驱动表。
在我们确定要使用某个索引的时候可以使用force index()强制只用某个索引,避免在某些情况下优化器选择错误导致查询效率降低。
优化器选择索引的目的,是找到一个最优的执行方案,并用最小的代价去执行语句。
优化器会结合是否使用临时表、是否排序、扫描行数等因素进行综合判断。
当然是用force index 也是有弊端的,如果你的索引发生了变化,而你的sql语句没有即使更改,那么这里就会报错。
在以上你能做到优化的极致条件下,由于数据量很大,可能还是会面临着慢查询的情况出现,那么这时候我们就要考虑分库分表了。
moon这里简单的和大家举个例子:
一家做客服系统的公司,业务量很大,客户很多,每天可能有上千万的数据量,如果你将这些数据都放在一张表里面,毫无疑问,会死的很惨。这时候我们可以考虑和业务相关的方式来进行分表,比如说你有10000家客户,你可以每一百家客户放在一张表上,这样平均下来一天该表可能只能几十万条数据,这样是可以接受的。但是时间久了,你会发现之前的数据都是没有用的,客户关心的都是最新产生的数据,那么我们就可以分库,将这些客户不关心的数据放在这个冷库中,以提高线上热数据的查询效率。
mysql优化的路还很长,当然以上这也不是全部的优化方案,但是会基本覆盖所有你在日常开发中能用到的优化小技巧,对于一般的面试官来说,足以吊打他了,但是我要提醒你的是,面对DBA,还是可以尽量乖一点,嗯,言至于此~
下期见,老铁们~
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/VTHwgMAiKqYljO_CdIxcTA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。