当前位置: 首页 > article >正文

SQL优化经验大全(表设计优化,索引优化,索引创建规则、索引失效场景,sql语句优化,主从复制,分库分表)面试题

目录

1.表的设计优化

2.索引优化

2.1 索引创建的规则

2.2 索引失效的场景

3.SQL语句优化

4.主从复制、读写分离

5.分库分表

5.1.怎么判断项目是需要分库还是要分表?

5.2 分库分表有哪些拆分方案?

5.2.1 垂直分库

5.2.2 垂直分表

5.2.3 水平分库

5.2.4 水平分表

5.3 分库分表带来的问题

6.面试回答


SQL可以分为以下5个方面,下面我会挨个阐述:

1.表的设计优化

2.索引优化

3.sql语句优化

4.主从复制、读写分离

5.分库分表

1.表的设计优化

参考了阿里的开发手册(嵩山版)

例如:

①比如设置合适的数值(tinyint,int,bigint),要根据实际情况选择
②比如设置合适的字符串类型(char和varchar)char定长效率高,varchar可变长度,效率稍低

2.索引优化

遵循索引创建的规则,避免索引失效的场景

2.1 索引创建的规则

1.针对于数据量较大,且查询比较频繁的表建立索引。单表超过10万数据(增加用户体验)。

2.针对于常作为查询条件(where)、排序(orderby)、分组(groupby)操作的字段建立索引。

3.数据库中大量重复的列不应该建立索引,例如性别。

4.长文本字段使用前缀索引,或者放入es中。

如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引(选取字符串前几个字符)。

5.尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率

6.索引并不是越多越好,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。

频繁更新的表不应该建立索引,对于频繁进行插入、更新和删除操作的表,索引会导致额外的维护开销,因为每次数据变更时都需要更新索引,这会影响性能。

7.如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引 最有效地用于查询

8.数据库较小的表,不要建立索引,因为可能走全表扫描

2.2 索引失效的场景

1  使用了联合索引却不符合最左前缀匹配原则

举个例子:小鱼对 user 表建立了一个联合索引为 name_age_id 的联合索引。 他使用以下 SQL 查询select * from user where age = 10 and id = 1; 这样的写法恰恰不满足最左前缀原则,索引就失效啦。

详细解释:

MySQL中,索引的“最左前缀原则”是指在使用索引进行查询时,索引会从左到右匹配列。如果查询条件中包含了索引的最左列,那么索引就可以被使用;如果没有包含最左列,那么索引可能不会被使用。

在上面例子中,小鱼建立了一个名为name_age_id的联合索引,这意味着索引的顺序是nameageid。这个索引可以支持以下几种查询条件:

  1. name列:WHERE name = '某个值'
  2. nameage列:WHERE name = '某个值' AND age = 某个值
  3. nameageid列:WHERE name = '某个值' AND age = 某个值 AND id = 某个值

但是,如果查询条件只包含ageid,而不包含name,那么索引可能不会被使用,因为name是索引的最左列。这是因为索引的最左前缀原则要求查询条件必须包含索引的最左列。

2.索引中使用了运算

例如这个 SQL select * from user where id + 3 = 8。这样会导致全表扫描计算 id 的值再进行比较,使得索引失效。

3. 索引上使用了函数也会失效

例如:select * from user where LOWER(name) like 'cong%';。这样也会导致索引失效,索引参与了函数处理,会导致去全表扫描。

4. 以%开头的Like模糊查询

如果仅仅是为有模糊匹配,索引不会失效

5. or的随意使用,必须or的两个字段,都有索引,索引才会生效

user 当前只有一个索引 name 。此时执行以下SQL :select * from user where name= 'cong' or age = 18; 这也会导致索引失效,因为 age 没有索引。

6. 隐式类型转换,会导致索引失效

例如:字符串不加' ',隐式的类型转换会导致索引失效

不小心将 varchar 类型的 name 条件匹配了 int 类型字段。

SQL 是这样的 select * from user where name = 1;

正确的应该写为select * from user where name = '1';

7.表中两个不同的字段进行比较,索引会失效

例如这样的SQL :select * from user where id > age; ,将 idage 字段做了比较,索引失效!

8.使用了 is not null

注意使用了 is not null 会直接导致失效,而使用 is null 则不会。因为当使用 is not null 条件时,数据库系统需要扫描整个索引,找出所有不为 null 的值,这可能会导致索引失效。使用 is null条件不会导致索引失效,因为对于索引而言,查找 null 值的行与查找其他任何特定值的行都没有本质区别。在大多数情况下,null 值都会被索引包括在内。

9.使用了 order by,但后面不跟主键

order by 后面跟的 不是主键 或者 不是覆盖索引 会导致不走索引。

10.使用了 != 、<>,可能导致索引失效

例如这样的 SQL :select * from user where name != 'cong'

如果name列的值大多数都是'cong',那么不等于'cong'的记录可能很少,优化器可能会认为使用索引不划算,因此选择全表扫描。这种情况下,索引可能不会生效。

3.SQL语句优化

  1. SELECT语句务必指明字段名称(避免直接使用select*)
  2. SQL语句要避免造成索引失效的写法(2.2 索引失效的场景
  3. 尽量用union all代替union ,union会多一次过滤,效率低

上面两个sql使用union all连接则第二个sql重复的值也会被返回,使用union会多一次过滤,过滤掉第二个sql重复的值

        4.Join优化:能用inner join就不用left join、right oin,如必须使用一定要以小表为驱动,

内连接会对两个表进行优化,优先把小表放到外边,把大表放到里边。left join 或right join,不会重新调整顺序

4.主从复制、读写分离

主从复制、读写分离(分库)解决的是访问的压力,不能解决海量数据的存储,海量数据存储需要用到分库分表

5.分库分表

当MySQL单表数据量过大,比如数据量超过1千万条或者储存量达到20G的时候,读写性能变得很差。而且常规的优化手段已经不起作用了,比如:SQL调优、添加索引、主从复制、读写分离。这时候就需要用到MySQL终极优化方案 — 分库分表

5.1.怎么判断项目是需要分库还是要分表?

(分库解决的是访问的压力,分表解决的是海量数据存储)

1.当单表数据量过大,读写性能较差,就需要分表。

2.当数据库的QPS过高,数据库连接数不足的时候,就需要分库。

3.当两者都有的时候,就需要分库分表。

5.2 分库分表有哪些拆分方案?

分库分表有垂直拆分和水平拆分。垂直拆分又有垂直分库、垂直分表。

5.2.1 垂直分库

垂直分库,不同的业务拆分到不同的数据库。

5.2.2 垂直分表

垂直分表,把长度较大或者访问频次较低的字段,拆分到扩展表中。

5.2.3 水平分库

水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。

5.2.4 水平分表

5.3 分库分表带来的问题

更详细的可以看这篇文章第四条

Mysql分库分表 面试题(待补充完善)_mysql分库分表面试题-CSDN博客

6.面试回答


http://www.kler.cn/a/377555.html

相关文章:

  • 架构系列---高并发
  • 2024年9月电子学会青少年软件编程Python等级考试(四级)真题试卷
  • LINUX_Ubuntu终端安装tools的命令
  • 如何将钉钉新收款单数据高效集成到MySQL
  • 【基础】os模块
  • Qt中的Model与View 2
  • list(c++)
  • 基于milvus的多模态检索
  • AWS RDS Oracle hit ORA-39405
  • 第三十一章 单页与多页应用程序概念
  • 单智能体carla强化学习实战工程介绍
  • 使用Django REST framework构建RESTful API
  • 【React 轮子】文本溢出后显示展开/收起按钮
  • java jsoup解析豆瓣电影数据html实战教程
  • Linux云计算 |【第五阶段】CLOUD-DAY5
  • 2.WebSocket进阶: 深入探究实时通信的最佳实践与优化技巧
  • Rust 力扣 - 1652. 拆炸弹
  • 深入理解跨域资源共享(CORS)安全问题原理及解决思路
  • C++编程法则365天一天一条(27)std::initializer_list 轻量级初始化列表
  • OKHTTP断点续传
  • 【运输&加载码头】仓库新卸物料检测系统源码&数据集全套:改进yolo11-DRBNCSPELAN
  • 利用Docker Compose构建微服务架构
  • 90%的读者都惊呆了!一键生成的微头条,连作者都认不出来是AI作品?
  • Linux常见指令大全(必要+知识点)
  • 设计模式08-行为型模式(命令模式/迭代器模式/观察者模式/Java)
  • 免公网服务器实现DDNS功能(API动态修改DNS解析IP)