文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

京东二面:日常工作中,你是如何优化SQL的?

2024-11-28 16:35

关注

我们去面试的时候,经常被问到,日常工作中,是如何优化SQL的。今天跟大家再聊聊哈。

这里应该如何去回答呢?可以从各种不同维度的,今天我再换个角度。

1. 加索引

很多时候,我们的慢查询,都是因为历史原因没有加索引,或者忘记加索引导致的。如果没有加索引的话,会导致全表扫描的。因此,应考虑在where的条件列,建立索引,尽量避免全表扫描。

反例:

select * from user_info where name ='捡田螺的小男孩公众号' ;

正例:

//添加索引
alter table user_info add index idx_name (name);

2. 避免常见的索引不生效场景

我之前整理了常见的十种索引不生效的场景,大家可以看看:

  1. 隐式的类型转换,索引失效
  2. 查询条件包含or,可能导致索引失效
  3. like通配符可能导致索引失效
  4. 查询条件不满足联合索引的最左匹配原则
  5. 在索引列上使用mysql的内置函数
  6. 对索引进行列运算(如,+、-、*、/)
  7. 索引字段上使用(!=或者<>),索引可能失效
  8. 索引字段上使用is null,is not null,索引可能失效
  9. 左右连接,关联的字段编码格式不一样
  10. 优化器选错了索引

3. 避免返回不必要的数据

这个点,我在昨天的文章,其实就提到一个点,包括尽量使用limit,避免不必要的返回

其实这不仅仅是一个点,而是一种思想,就是要什么查什么,而不是返回一些不必要的数据。还有:查询SQL尽量不要使用select *,而是select具体字段。也是这种思想。

反例子:

select * from employee;

正例子:

select id,name, age from employee;

4. 减少不必要的逻辑

其实,尽量用 union all 替换 union,就是这种思想。

如果我们明知道,检索结果中不会有重复的记录,推荐union all 替换 union。

因为:

如果使用union,不管检索结果有没有重复,都会尝试进行合并,然后在输出最终结果前进行排序。如果已知检索结果没有重复记录,使用union all 代替union,这样会提高效率。

5. 分批量进行思想

我们更推荐批量查询、插入、删除。

反例:

for(User u :list){
 INSERT into user(name,age) values(#name#,#age#)   
}

正例:

//一次500批量插入,分批进行
insert into user(name,age) values

    (#{item.name},#{item.age})

理由:

6. 读写分离

一般情况我们的数据库架构,都要做主从的,然后进行读写分离。主库主要负责写,和一些实时性比较高的读。而从库就负责读实时性要求不高的请求。

图片图片

这样的话,我们不用所有请求都到主库,大大降低了主库的压力。你试想一下,如果所有读请求都到主库,查询压力肯定很大,处理也会相对慢一点。

7. 优化sql结构、逻辑

有些时候,优化SQL结构,都能有一些预想不到的优化效果。

假设我们有个客户表和一个订单表。其中订单表有10万记录,客户表只有1000行记录。

现在要查询下单过的客户信息,可以这样写:

SELECT * FROM customers
WHERE id IN (
    SELECT customer_id FROM orders
);


in 查询会先执行内部查询部分 SELECT customer_id FROM orders,获得 orders 表(大表)中的所有 customer_id,然后在 customers 表(小表)中查找匹配的 id。

也可以这样实现:

SELECT * FROM customers c
WHERE EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.id
);

EXISTS 会逐行扫描 customers 表(即小表),对每一行 c.id,在 orders 表(大表)中检查是否有 customer_id = c.id 的记录。

因为orders表的数据量比较大,因此这里用exists效果会相对更好一点。其实这就是小表驱动大表的思想。我们也只是调整SQL结构,用exists去替换in,优化效果也是比较明显的。

8. 分库分表

如果单表的数据量很大,达到百万甚至千万级别,我们这种时候,就是加了索引,可能效果也不是很明显。这时候我们可以考虑分库分表啦~~

分库分表一般都是依赖客户号、用户Id、或者时间来拆分。但是需要注意一下,分库分表存在的一些一些问题:

9. 性能优化分析神器—explain

之前我写SQL习惯的时候,有提到explain,就是每次写完查询SQL,都用explain看一下它的执行计划。

有些面试官会单独问这个,我们可以走面试官的路,让面试官无路可走。在回答SQL优化的时候,就把这个回答了。

一般在使用explain的时候,我们要关注:type、rows、filtered、extra、key。

9.1 type

type表示连接类型,查看索引执行情况的一个重要指标。以下性能从好到坏依次:system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

9.2 rows

该列表示MySQL估算要找到我们所需的记录,需要读取的行数。对于InnoDB表,此数字是估计值,并非一定是个准确值。

9.3 filtered

该列是一个百分比的值,表里符合条件的记录数的百分比。简单点说,这个字段表示存储引擎返回的数据在经过过滤后,剩下满足条件的记录数量的比例。

9.4 extra

该字段包含有关MySQL如何解析查询的其他信息,它一般会出现这几个值:

9.5 key

该列表示实际用到的索引。一般配合possible_keys列一起看。

10. 慢SQL排查思路

如果大家平时有优化过生产的慢SQL,有自己的一套排查那一套最好哈。如果没有的话,可以在自己搞个深分页,或者因为数据量、或者因为没加索引等原因,导致的慢SQL,然后按照这个思路去排查一遍。

如果不熟悉的话,可以多操作几遍,尽量熟悉操作流程,在面试的时候,讲一下这个主要流程。

来源:捡田螺的小男孩内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯