Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面试中被问到SQL优化

面试中被问到SQL优化

作者头像
用户4283147
发布于 2022-10-27 07:25:40
发布于 2022-10-27 07:25:40
55300
代码可运行
举报
文章被收录于专栏:对线JAVA面试对线JAVA面试
运行总次数:0
代码可运行

先简单梳理下Mysql的基本概念,然后分创建时和查询时这两个阶段的优化展开。

1 基本概念简述

1.1 逻辑架构
  • 第一层:客户端通过连接服务,将要执行的sql指令传输过来
  • 第二层:服务器解析并优化sql,生成最终的执行计划并执行
  • 第三层:存储引擎,负责数据的储存和提取
1.2 锁

数据库通过锁机制来解决并发场景-共享锁(读锁)和排他锁(写锁)。读锁是不阻塞的,多个客户端可以在同一时刻读取同一个资源。写锁是排他的,并且会阻塞其他的读锁和写锁。简单提下乐观锁和悲观锁。

  • 乐观锁,通常用于数据竞争不激烈的场景,多读少写,通过版本号和时间戳实现。
  • 悲观锁,通常用于数据竞争激烈的场景,每次操作都会锁定数据。

要锁定数据需要一定的锁策略来配合。

  • 表锁,锁定整张表,开销最小,但是会加剧锁竞争。
  • 行锁,锁定行级别,开销最大,但是可以最大程度的支持并发。

但是MySql的存储引擎的真实实现不是简单的行级锁,一般都是实现了多版本并发控制(MVCC)。MVCC是行级锁的变种,多数情况下避免了加锁操作,开销更低。MVCC是通过保存数据的某个时间点快照实现的。

1.3 事务

事务保证一组原子性的操作,要么全部成功,要么全部失败。一旦失败,回滚之前的所有操作。MySql采用自动提交,如果不是显式的开启一个事务,则每个查询都作为一个事务。

隔离级别控制了一个事务中的修改,哪些在事务内和事务间是可见的。四种常见的隔离级别:

  • 未提交读(Read UnCommitted),事务中的修改,即使没提交对其他事务也是可见的。事务可能读取未提交的数据,造成脏读。
  • 提交读(Read Committed),一个事务开始时,只能看见已提交的事务所做的修改。事务未提交之前,所做的修改对其他事务是不可见的。也叫不可重复读,同一个事务多次读取同样记录可能不同。
  • 可重复读(RepeatTable Read),同一个事务中多次读取同样的记录结果时结果相同。
  • 可串行化(Serializable),最高隔离级别,强制事务串行执行。
1.4 存储引擎

InnoDB引擎,最重要,使用最广泛的存储引擎。被用来设计处理大量短期事务,具有高性能和自动崩溃恢复的特性。

MyISAM引擎,不支持事务和行级锁,崩溃后无法安全恢复。

2 创建时优化

2.1 Schema和数据类型优化

整数

TinyInt,SmallInt,MediumInt,Int,BigInt 使用的存储8,16,24,32,64位存储空间。使用Unsigned表示不允许负数,可以使正数的上线提高一倍。

实数

  • Float,Double , 支持近似的浮点运算。
  • Decimal,用于存储精确的小数。

字符串

  • VarChar,存储变长的字符串。需要1或2个额外的字节记录字符串的长度。
  • Char,定长,适合存储固定长度的字符串,如MD5值。
  • Blob,Text 为了存储很大的数据而设计的。分别采用二进制和字符的方式。

时间类型

  • DateTime,保存大范围的值,占8个字节。
  • TimeStamp,推荐,与UNIX时间戳相同,占4个字节。

优化建议点

  • 尽量使用对应的数据类型。比如,不要用字符串类型保存时间,用整型保存IP。
  • 选择更小的数据类型。能用TinyInt不用Int。
  • 标识列(identifier column),建议使用整型,不推荐字符串类型,占用更多空间,而且计算速度比整型慢。
  • 不推荐ORM系统自动生成的Schema,通常具有不注重数据类型,使用很大的VarChar类型,索引利用不合理等问题。
  • 真实场景混用范式和反范式。冗余高查询效率高,插入更新效率低;冗余低插入更新效率高,查询效率低。
  • 创建完全的独立的汇总表\缓存表,定时生成数据,用于用户耗时时间长的操作。对于精确度要求高的汇总操作,可以采用 历史结果+最新记录的结果 来达到快速查询的目的。
  • 数据迁移,表升级的过程中可以使用影子表的方式,通过修改原表的表名,达到保存历史数据,同时不影响新表使用的目的。
2.2 索引

索引包含一个或多个列的值。MySql只能高效的利用索引的最左前缀列。索引的优势:

  • 减少查询扫描的数据量
  • 避免排序和零时表
  • 将随机IO变为顺序IO (顺序IO的效率高于随机IO)

B-Tree

使用最多的索引类型。采用B-Tree数据结构来存储数据(每个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的遍历)。B-Tree索引适用于全键值,键值范围,键前缀查找,支持排序。

B-Tree索引限制:

  • 如果不是按照索引的最左列开始查询,则无法使用索引。
  • 不能跳过索引中的列。如果使用第一列和第三列索引,则只能使用第一列索引。
  • 如果查询中有个范围查询,则其右边的所有列都无法使用索引优化查询。

哈希索引

只有精确匹配索引的所有列,查询才有效。存储引擎会对所有的索引列计算一个哈希码,哈希索引将所有的哈希码存储在索引中,并保存指向每个数据行的指针。更多面试题,欢迎关注公众号 Java面试题精选

哈希索引限制:

  • 无法用于排序
  • 不支持部分匹配
  • 只支持等值查询如=,IN(),不支持 < >

优化建议点

  • 注意每种索引的适用范围和适用限制。
  • 索引的列如果是表达式的一部分或者是函数的参数,则失效。
  • 针对特别长的字符串,可以使用前缀索引,根据索引的选择性选择合适的前缀长度。
  • 使用多列索引的时候,可以通过 AND 和 OR 语法连接。
  • 重复索引没必要,如(A,B)和(A)重复。
  • 索引在where条件查询和group by语法查询的时候特别有效。
  • 将范围查询放在条件查询的最后,防止范围查询导致的右边索引失效的问题。
  • 索引最好不要选择过长的字符串,而且索引列也不宜为null。

3 查询时优化

3.1 查询质量的三个重要指标
  • 响应时间 (服务时间,排队时间)
  • 扫描的行
  • 返回的行
3.2 查询优化点
  • 避免查询无关的列,如使用Select * 返回所有的列。
  • 避免查询无关的行
  • 切分查询。将一个对服务器压力较大的任务,分解到一个较长的时间中,并分多次执行。如要删除一万条数据,可以分10次执行,每次执行完成后暂停一段时间,再继续执行。过程中可以释放服务器资源给其他任务。
  • 分解关联查询。将多表关联查询的一次查询,分解成对单表的多次查询。可以减少锁竞争,查询本身的查询效率也比较高。因为MySql的连接和断开都是轻量级的操作,不会由于查询拆分为多次,造成效率问题。
  • 注意count的操作只能统计不为null的列,所以统计总的行数使用count(*)。
  • group by 按照标识列分组效率高,分组结果不宜出行分组列之外的列。
  • 关联查询延迟关联,可以根据查询条件先缩小各自要查询的范围,再关联。
  • Limit分页优化。可以根据索引覆盖扫描,再根据索引列关联自身查询其他列。如
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT
 id,
 NAME,
 age
WHERE
 student s1
INNER JOIN (
 SELECT
     id
 FROM
     student
 ORDER BY
     age
 LIMIT 50,5
) AS s2 ON s1.id = s2.id
  • Union查询默认去重,如果不是业务必须,建议使用效率更高的Union All

补充内容

1.条件中的字段类型和表结构类型不一致,mysql会自动加转换函数,导致索引作为函数中的参数失效。

2.like查询前面部分未输入,以%开头无法命中索引。

3.补充2个5.7版本的新特性:

generated column,就是数据库中这一列由其他列计算而得

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE triangle (sidea DOUBLE, sideb DOUBLE, area DOUBLE AS (sidea * sideb / 2));
insert into triangle(sidea, sideb) values(3, 4);
select * from triangle;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+-------+-------+------+
| sidea | sideb | area |
+-------+-------+------+
|   3      |   4      |  6     |
+-------+-------+------+

支持JSON格式数据,并提供相关内置函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE json_test (name JSON);
INSERT INTO json_test VALUES('{"name1": "value1", "name2": "value2"}');
SELECT * FROM json_test WHERE JSON_CONTAINS(name, '$.name1');

关注explain在性能分析中的使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
EXPLAIN SELECT settleId FROM Settle WHERE settleId = "3679"
  • select_type,有几种值:simple(表示简单的select,没有union和子查询),primary(有子查询,最外面的select查询就是primary),union(union中的第二个或随后的select查询,不依赖外部查询结果),dependent union(union中的第二个或随后的select查询,依赖外部查询结果)
  • type,有几种值:system(表仅有一行(=系统表),这是const连接类型的一个特例),const(常量查询), ref(非唯一索引访问,只有普通索引),eq_ref(使用唯一索引或组件查询),all(全表查询),index(根据索引查询全表),range(范围查询)
  • possible_keys: 表中可能帮助查询的索引
  • key,选择使用的索引
  • key_len,使用的索引长度
  • rows,扫描的行数,越大越不好
  • extra,有几种值:Only index(信息从索引中检索出,比扫描表快),where used(使用where限制),Using filesort (可能在内存或磁盘排序),Using temporary(对查询结果排序时使用临时表)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 对线JAVA面试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
13000字!最常问的MySQL面试题集合
问题1:char、varchar的区别是什么? varchar是变长而char的长度是固定的。如果你的内容是固定大小的,你会得到更好的性能。
杰哥的IT之旅
2020/11/03
9410
82. 面试中被问到SQL优化,看这篇就对了
数据库通过锁机制来解决并发场景-共享锁(读锁)和排他锁(写锁)。读锁是不阻塞的,多个客户端可以在同一时刻读取同一个资源。写锁是排他的,并且会阻塞其他的读锁和写锁。简单提下乐观锁和悲观锁。
用户11332765
2024/11/01
640
82. 面试中被问到SQL优化,看这篇就对了
MySQL面试题(最全、超详细)——定位慢查询、聚簇索引、覆盖索引、深分页优化、sql优化、并发事务问题、隔离级别、undo log与redo log、主从同步
查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志如果要开启慢查询日志,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
寻求出路的程序媛
2024/06/25
1.4K0
MySQL面试题(最全、超详细)——定位慢查询、聚簇索引、覆盖索引、深分页优化、sql优化、并发事务问题、隔离级别、undo log与redo log、主从同步
MySQL 三万字精华总结 + 面试100 问,吊打面试官绰绰有余(收藏系列)
和其它数据库相比,MySQL有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。
帅地
2020/06/03
2.8K1
MySQL 三万字精华总结 + 面试100 问,吊打面试官绰绰有余(收藏系列)
《高性能 MySQL》读书笔记
1、隔离级别有四种: READ UNCOMMITTED(未提交读),同事务中某个语句的修改,即使没有提交,对其他事务也是可见的。这个也叫脏读。 READ COMMITTED(提交读),另一个事务只能读到该事务已经提交的修改,是大多数据库默认的隔离级别。但是有下列问题,一个事务中两次读取同一个数据,由于这个数据可能被另一个事务提交了两次,所以会出现两次不同的结果,所以这个级别又叫做不可重复读。这里的不一样的数据包括虚读(两次结果不同)和幻读(出现新的或者缺少了某数据)。 REPEATABLE READ(可重复读),这个级别不允许脏读和不可重复读,比如MYSQL中通过MVCC来实现解决幻读问题。 SERIALIABLE(可串行化),这儿实现了读锁,级别最高。
DannyHoo
2018/09/13
1.5K0
《高性能 MySQL》读书笔记
mysql数据库面试题目及答案_数据库面试题2021
MySQL数据库面试题(2022最新版) 🐶 程序猿周周 ⌨️ 短视频小厂BUG攻城狮 🤺 如果文章对你有帮助,记得关注、点赞、收藏,一键三连哦,你的支持将成为我最大的动力 ---- 本文是 Java 面试总结系列的第1️⃣篇文章,该专栏将整理和梳理笔者作为 Java 后端程序猿在日常工作以及面试中遇到的实际问题,通过这些问题的系统学习,也帮助笔者顺利拿到阿里、字节、华为、快手等Offer,也祝愿大家能够早日斩获自己心仪的Offer。由于笔者能力有限,其中大多答案来自巨人的肩膀并引以出处,若有
全栈程序员站长
2022/11/10
7110
mysql数据库面试题目及答案_数据库面试题2021
高性能MySQL学习笔记
完全的范式和反范式是不存在的,在实际操作中建议混用这两种策略,可能使用部分范式化的schema、缓存表、以及其他技巧。
earthchen
2020/09/24
1.4K0
MySQL灵魂拷问:36题带你面试通关!
事务特性ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
程序员大彬
2021/10/17
5420
MySQL灵魂拷问:36题带你面试通关!
面试必备!91 道 MySQL 面试题(含答案)
结构化查询语言(Structured Query Language)简称SQL,是一种数据库查询语言。
Python进击者
2020/03/26
1K0
干货!MySQL优化原理分析及优化方案总结
说起MySQL优化的话,想必大部分人都不陌生了。在我们的记忆储备里也早已记住了这些关键词:避免使用SELECT*、避免使用NULL值的判断、根据需求适当的建立索引、优化MySQL参数......但是你对于这些优化技巧是否真正的掌握了及其相应的工作原理是否吃透了呢?在我们的实际开发过程中你能充分应用到吗?我觉得还有待考察。所以,本文将详细介绍MySQL优化技巧以及其相应的技术原理,希望大家看完以后,能更清楚直接的了解这些优化方案,并应用到我们的工作岗位中。
用户1516716
2020/12/17
9250
MySQL 面试题
阿彬学java
2025/01/09
2050
MySQL学习——优化
在系统性能问题中,数据库往往是性能的瓶颈关键因素。那么如何去检测mysql的性能问题,如何构建高性能的mysql,如何编写出高性能的sql语句?为此,整理一些建议。
用户5325874
2022/05/06
7780
MySQL学习——优化
10分钟掌握数据类型、索引、查询的MySQL优化技巧
本文的内容是总结一些MySQL的常见使用技巧,以供没有DBA的团队参考。以下内容以MySQL5.5为准,如无特殊说明,存储引擎以InnoDB为准。
苏先生
2019/05/09
8340
10分钟掌握数据类型、索引、查询的MySQL优化技巧
java面试题
要在List后面添加删除元素和随机访问元素,则选择ArrayList更好,如果要在List前面或中间添加删除元素或者按顺序访问元素,则选择LinkedList更好
用户11332765
2024/10/28
1520
java面试题
搞懂这些SQL优化技巧,面试横着走
小伙伴想精准查找自己想看的MySQL文章?喏 → MySQL专栏目录 | 点击这里
陈哈哈
2021/10/13
9510
SQL优化篇:如何成为一位写优质SQL语句的绝顶高手!
写SQL语句不难,稍微系统学习过数据库相关技术的人都能做到,但想要写好SQL却也不是一件易事,在大多数编写SQL的时候,很多人都是以实现需求为原则去撰写的,当一条SQL写出来之后,只要能满足业务需求就行,不会考虑它有没有优化点,能不能让它跑的更快。
田维常
2023/08/31
1.6K0
SQL优化篇:如何成为一位写优质SQL语句的绝顶高手!
史上最全存储引擎、索引使用及SQL优化的实践
整个MySQL Server由以下组成 : Connection Pool :连接池组件 Management Services & Utilities :管理服务和工具组件 SQL Interface :SQL接口组件 Parser :查询分析器组件 Optimizer :优化器组件 Caches & Buffers :缓冲池组件 Pluggable Storage Engines :存储引擎 File System :文件系统 1)连接层 最上层是一些客户端和链接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。 2)服务层 第二层架构主要完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化,部分内置函数的执行。所有跨存储引擎的功能也在这一层实现,如过程、函数等。在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定表的查询的顺序,是否利用索引等,最后生成相应的执行操作。如果是select语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样在解决大量读操作的环境中能够很好的提升系统的性能。 3)引擎层 存储引擎层,存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能,这样我们可以根据自己的需要,来选取合适的存储引擎。 4)存储层 数据存储层,主要是将数据存储在文件系统之上,并完成与存储引擎的交互。
海仔
2019/08/05
1.4K0
史上最全存储引擎、索引使用及SQL优化的实践
SQL优化 21 连击
比如,存储字符串“101”,对于char(10),表示你存储的字符将占10个字节(包括7个空字符),在数据库中它是以空格占位的,而同样的varchar2(10)则只占用3个字节的长度,10只是最大值,当你存储的字符小于10时,按实际长度存储。
公众号: 云原生生态圈
2022/11/02
7150
SQL优化 21 连击 + 思维导图
比如,存储字符串“101”,对于char(10),表示你存储的字符将占10个字节(包括7个空字符),在数据库中它是以空格占位的,而同样的varchar2(10)则只占用3个字节的长度,10只是最大值,当你存储的字符小于10时,按实际长度存储。
Java小咖秀
2022/09/23
8330
很用心的为你写了 9 道 MySQL 面试题
MySQL 一直是本人很薄弱的部分,后面会多输出 MySQL 的文章贡献给大家,毕竟 MySQL 涉及到数据存储、锁、磁盘寻道、分页等操作系统概念,而且互联网对 MySQL 的注重程度是不言而喻的,后面要加紧对 MySQL 的研究。写的如果不好,还请大家见谅。
cxuan
2020/04/21
7240
很用心的为你写了 9 道 MySQL 面试题
推荐阅读
相关推荐
13000字!最常问的MySQL面试题集合
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验