来看!这才是久经沙场得 SQL 优化经验

news2024/11/28 20:42:22

跟着 SQL 优化得经验之谈,面试真的可以侃侃而谈。

那么面对复杂的关系数据,我们如何来优化,SQL如何玩转更优?

先抛出了4个关于优化方面的问题:

1.返回表中0.014%的数据应不应该走索引?

2.什么样的列必须建立索引呢?

3.嵌套查询、HASH连接、排序合并连接、笛卡尔连接等怎样玩能达到最优?

4.IN 与EXISTS 谁快谁慢?

整个优化内容篇幅过长,查询优化内容并非一篇文章就能讲明白,更多是需要自己的消化并通过实践运用来得出自己的一套优化体系。

文本也是分篇幅进行讲解,还需慢慢消化其中的内容,目前只针对上述的两个问题进行了解释,其余两个问题是关于连表查询的优化内容,将在下篇的sql连接查询优化进行细谈。

相关的优化知识和经验,也是本人通过自身的学习并通过实践运用,不免存在一定的偏差和错误,如有大佬指正以及其他方面的分享,不甚感激。

SQL简单查询

SQL简单查询

简单查询格式如下:

SELECT * FROM 表名 WHERE 条件 SELECT 字段原名 AS 字段别名

选择条件的构成: =(等于)、<>(不等于)、<(小于)、>(大于)、<=(不大于)和>=(不小于)

优先级:

NOT优先级高于AND,AND的优先级高于OR。注意使用圆括号的使用。

涉及空值的查询: 空值用NULL表示,表明空值或者不为空值可以用“IS NULL”或 “IS NOT NULL”

字符串的比较:

SQL的习惯用法是在 % 和 _ 之前加上转义符号“\”表示这里的 % 和 _ 是一个普通的字符,而不是匹配使用。 如果不把 \ 作为转义符号,只把它当作一个普通字符,可以连续两个 \ 表示一个真正的反斜线 \。

输出的排序:

ORDER BY <字段名> ,提示:默认排序是升序(ASC),可用倒叙(DESC)

聚合运算符:

SUM:求某列中所有值的和;

AVG:求某列中所有值的平均值;

MIN:求某列中的最小值;

MAX:求某列中的最大值;

COUNT:求某列中值的个数。

分组:

在WHERE子句加上GROUP BY ,关键字GROUP BY 后面给出分组属性列表。

注:如果只希望查询满足一定条件的分组情况,可以使用关键字HAVING来选择具有给定条件的分组。

sql优化

在谈及sql查询优化,优化性能是每个优秀的工程师必备的思想之一,无论是面对复杂还是简单的工程不仅仅满足于表现层的结果,哪怕你优化的速度提高了百分之一,都是经历过自己思考的过程,以及走向成熟的过程。

再谈优化之前,先掌握几个重要的概念:基数,选择性,直方图,回表,集群因子,表关系。

基数: 某个列唯一键(Distinct_Keys)的数量叫作基数。比如性别列,该列只有男女之分,所以这一列基数是2。主键列的基数等于表的总行数。

例如:select count(distinct name), count(distinct age), count(*) from student 语句查询如下:

count(distinct name)

count(distinct age)

count(*)

76

34

86

学生当中不重复的名字有76,年龄34,学生人数为86。

基数的高低影响列的数据分布,往往基数高的列通常用作索引,获取数据的命中率高。

那么,回到上面的第一个问题:返回表中0.014%的数据应不应该走索引?

在数据足够多,达到百万千万级的数据时,当查询结果是返回表中5%以内的数据时,应该走索引;当查询结果返回的是超过表中5%的数据时,应该走全表扫描。

也就是说,如果某个列基数很低,该列数据分布就会非常不均衡,由于该列数据分布不均衡,会导致SQL查询可能走索引,也可能走全表扫描。在做 SQL优化的时候,如果怀疑列数据分布不均衡,我们可以使用select列,count(*) from 表 group by 列 order by desc来查看列的数据分布。

选择性: 一个操作过滤的记录的比例, 是一个介于 0 和 1 之间的数值。通常工程师在使用查表时,往往会筛选掉不必要的数据列来提高查询速率,这也是一种很直观的优化方式。那么在数据重量级的情况下,我们要怎么来直观的查看选择性呢?通常,基数与总行数的比值再乘以100%就是某个列的选择性。

那么,我们可以回到上述的第二个问题:什么样的列必须建立索引呢?

在我的之前建立索引的经验中,往往基数高的列,where条件中常用的列来建立索引,但是这样往往还不够,我们无法单一的看基数高的列,where常用条件就来建立索引,此时我们无法确定命中率的高低,所以,通过基数与总行数的比值再乘以100%,就能直观的看出哪些列占比就可以建立索引。当一个列选择性大于20%,说明该列的数据分布就比较均衡了。

直方图: 如果没有对基数低的列收集直方图统计信息,基于成本的优化器(CBO)会认为该列数据分布是均衡的。

1.如果没有对基数低的列收集直方图统计信息,基于成本的优化器(CBO)会认 为该列数据分布是均衡的。

2.直方图信息就是以上SQL的查询结果,这些查询结果会保存在数据字典中。这样 当我们查询owner为任意值的时候,CBO总会算出正确的Rows,因为直方图已经知道 每个值有多少行数据。

以pgsql 为例:

​也就是说,你所执行的sql查询之后,你所查询的结果会保存在数据字典中,这里也涉及到了数更新之后所统计的数据没有更新的话会存在一定的误差,这也是后话了。

如果SQL使用了绑定变量,绑定变量的列收集了直方图,那么该SQL就会引起绑定变量窥探。关于绑定变量窥探的问题,这里也不过多讲诉。

那,什么样的列需要收集直方图呢?

当列出现在where条件中,列的选择性小于1%并 且该列没有收集过直方图,这样的列就应该收集直方图。注意:千万不能对没有出现 在where条件中的列收集直方图。对没有出现在where条件中的列收集直方图完全是做无用功,浪费数据库资源。

回表: 当对一个列创建索引之后,索引会包含该列的键值以及键值对应行所在的rowid。通过索引中记录的rowid访问表中的数据就叫回表。回表一般是单块读,回表次数太多 会严重影响SQL性能,如果回表次数太多,就不应该走索引扫描了,应该直接走全表 扫描。

为什么返回表中5%以内的数据走索引、超过表中5% 的数据走全表扫描?

根本原因就在于回表。在无法避免回表的情况下,走索引如果返回数据量太多,必然会导致回表次数太 多,从而导致性能严重下降。

什么样的SQL必须回表?什么样的不需要回表呢?

select *from tablename where ......

这样的sql是必须回表的,所以工程师们在编写sql的时候通常严禁 select * 的出现。

select count(*) from tablename .

这样的sql就不走回表,当查询的列也包含在索引中时,也不需要走回表,所以通常建立索引时,往往会建立组合索引来消除回表,来提升性能。

​集群因子: 集群因子用于判断索引回表需要消耗的物理I/O次数。上面我们提到,回表是走单块读取,每一条数据的回表它都是一次IO消耗。

1.集群因子的算法,在这我们暂且先不提,但是我们知道集群因子介于表的块数和表行数之间。

2.如果集群因子与块数接近,说明表的数据基本上是有序的,而且其顺序基本与 索引顺序一样。这样在进行索引范围或者索引全扫描的时候,回表只需要读取少量 的数据块就能完成。

3.如果集群因子与表记录数接近,说明表的数据和索引顺序差异很大,在进行索引范围扫描或者索引全扫描的时候,回表会读取更多的数据块。

集群因子只会影响索引范围扫描(INDEX RANGE SCAN)以及索引全扫描 (INDEX FULL SCAN),因为只有这两种索引扫描方式会有大量数据回表。集群因子不会影响索引唯一扫描(INDEX UNIQUE SCAN),因为索引唯一扫描 只返回一条数据。集群因子更不会影响索引快速全扫描(INDEX FAST FULL SCAN),因为索引快速全扫描不回表。

​集群因子究竟影响的是什么性能呢?

集群因子影响的是索引回表的物理I/O次 数。我们假设索引范围扫描返回了1 000行数据,如果buffer cache(缓存)中没有缓存表的数据块,假设这1000行数据都在同一个数据块中,那么回表需要耗费的物理I/O就只需要 一个;假设这1000行数据都在不同的数据块中,那么回表就需要耗费1000个物理 I/O。因此,集群因子影响索引回表的物理I/O次数。

请注意,不要尝试重建索引来降低集群因子,这根本没用,因为表中的数据顺序 始终没变。 唯一能降低集群因子的办法就是根据索引列排序对表进行重建(create table new_table as select * from old_table order by 索引列),但是这在实际操作中 是不可取的,因为我们无法照顾到每一个索引。

怎么才能避免集群因子对SQL查询性能产生影响呢?

集群因子只影响索引范围扫描和索引全扫描。当索引范围扫描,索引全扫描不回表或者 返回数据量很少的时候,不管集群因子多大,对SQL查询性能几乎没有任何影响。

​再次强调一遍,在进行SQL优化的时候,往往会建立合适的组合索引消除回表, 或者建立组合索引尽量减少回表次数。

如果无法避免回表,怎么做才能消除回表对SQL查询性能产生影响呢?

当我们把 表中所有的数据块缓存在buffer cache中,这个时候不管集群因子多大,对SQL查询性 能也没有多大影响,因为这时不需要物理I/O,数据块全在内存中访问速度是非常快 的。

表与表之间的关系:要理清楚表与表之间的关系。

表与表之间存在3种关系。一种是1∶1关系, 一种是1∶N关系,最后一种是N∶N关系。搞懂表与表之间关系,对于SQL优化、SQL等价改写、表设计优化以及分表分库都有巨大帮助。

两表在进行关联的时候,如果两表属于1∶1关系,关联之后返回的结果也是属于1的关系,数据不会重复。如果两表属于1∶N关系,关联之后返回的结果集属于N的关系。如果两表属于N∶N关系,关联之后返回的结果集会产生局部范围的笛卡儿积,N∶N关系一般不存在内/外连接中,只能存在于半 连接或者反连接中。

好了,以上咱们细谈了SQL的简单查询,相关SQL优化的思想,里面内容其实包括了很多,也省略了部分细节没有展开来讲解,有兴趣的伙伴可以多去了解了解,也可以和我分享。最重要的核心优化思想之一,关于优化方面最主要的核心就是 :只有大表才会产生性能问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/88106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

股票买卖接口如何实现委托下单的功能?

股票买卖接口如何实现委托下单的功能&#xff1f;一般来说&#xff0c;股票买卖接口都是相关的人士已经设计好&#xff0c;并且是程序形式呈现出来的&#xff0c;和券商系统链接起来&#xff0c;这样就可以实现交易了&#xff0c;下面给分享关于股票买卖接口是如何执行委托下单…

计算机系统实验-DataLab

一.实验题目及要求 在给定规则限制下完成bits.c中的函数。其中最主要的规则如下&#xff1a; 整数规则 不能使用for while if等只能使用! ˜ & ˆ | << >>运算符只能使用int只能使用0-0xFF的常数使用运算符数不超过限制(Max ops)不能使用全局变量或调用函数…

将简单工厂模式改造应用到项目中,而不是纸上谈兵

10月26日晚补充&#xff1a;经过掘友的提醒&#xff0c;我才发现之前我这篇所写的策略模式&#xff0c;其本身更偏向于工厂模式&#xff0c;我起初以为是掘友分不清工厂模式和策略模式&#xff0c;实际上是我自己把自己绕进去&#xff0c;看不清工厂模式和策略模式的区别。 因…

网闸的工作原理

网闸GAP由固态读写开关和存储人质系统组成&#xff0c;其中固态开关的转换效率达到了纳秒级&#xff0c;存储介质通常采用scsi硬盘&#xff0c;因此GAP的性能得到了保证。 GAP连接在两个独立的网络系统中间&#xff0c;内网与外网永远不同时连接&#xff0c;在同一时刻只有一个…

鱼传科技:函数计算,只要用上就会觉得香

深圳鱼传科技有限公司是专注以精准营销和互联网生态产品运营为核心的综合互联网营销推广服务商。通过整合全网优质媒体资源&#xff0c;并结合智能数据模型和 AI 标签算法&#xff0c;向企业提供包括流量矩阵搭建运营、媒介流量采买、投放模型设计、产品营销策划、数据监控分析…

面试官:如何解决 Redis 数据倾斜、热点等问题

Redis 作为一门主流技术&#xff0c;应用场景非常多&#xff0c;很多大中小厂面试都列为重点考察内容 前几天有小伙伴学习时&#xff0c;遇到下面几个问题&#xff0c;来咨询小编 考虑到这些问题比较高频&#xff0c;工作中经常会遇到&#xff0c;这里写篇文章系统讲解下 问…

健身房头戴式耳机好吗、最优秀的健身房耳机推荐

作为一名运动爱好者&#xff0c;无论是在户外跑步、骑行&#xff0c;还是在室内健身&#xff0c;耳机都是平日运动时不可或缺的装备。即使在日常通勤中&#xff0c;很多人也不能缺少它的陪伴。普通的耳机很好选择&#xff0c;只需要看音质好不好就可&#xff0c;运动耳机就比较…

win10系统下安装JDK1.8及配置环境变量的方法

1&#xff1a;下载安装包 地址&#xff1a;https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 选择与自己环境相匹配的安装包 后续过程需要登录Oracle账号&#xff0c;如果你网络环境不好或者没有Oracle账号&#xff0c;请按照文末默认获取方式获…

ssm+Vue计算机毕业设计校园闲置物品交易系统(程序+LW文档)

ssmVue计算机毕业设计校园闲置物品交易系统&#xff08;程序LW文档&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项…

GCSE英语语言考试-叙述视角

What is narrative voice? Narrative voice is the perspective the story is told from. The writer chooses a narrative voice carefully, as it can have an important effect on the story and the reader’s response. 什么是叙述视角&#xff1f; 叙述视角是讲述故事的…

机器人逆向运动学(IK)入门:问题分析

在游戏开发和机器人开发中进场需要用到的一个场景是&#xff0c;给机器人或者游戏角色末位置的位置和姿态&#xff0c;求解可到达给定位置和姿态的各关节的角度值&#xff0c;这里就需要逆向运动学去求解这个问题&#xff0c;在场景中有着很多的应用&#xff0c;比如说六轴机械…

电脑重装系统蓝屏详细解决方法分享

我们在使用电脑时我们经常会遇到各种问题&#xff0c;比如卡顿&#xff0c;死机&#xff0c;蓝屏&#xff0c;黑屏等等。今天这里小编为大家介绍的是电脑蓝屏的问题&#xff0c;电脑蓝屏会导致数据丢失、未保存的文件丢失、游戏关键时刻坑队友等情况。接下来&#xff0c;小编就…

使用Github Actions自动部署vue项目到nginx服务器

解决的问题&#xff1a;妈妈再也不担心我deploy时候手滑了 1. 避免手动执行重复的前端发布流程&#xff0c;节约开发时间和耐心 2. 减少了使用Jenkins类似的工具来做这种简单的发布流程&#xff0c;减少了第三方系统&#xff08;Jenkins&#xff09;的维护成本 前置条件 1.…

MySQL数据库学习(7)

一、简介 MySQL是最流行的关系型数据库管理系统&#xff0c;在这里我使用 PyMySQL 连接数据库&#xff0c;并实现简单的增删改查。 PyMySQL是在 Python3.x版本中用于连接 MySQL服务器的一个库&#xff0c;Python2中则使用 mysqldb。 PyMySQL遵循 Python数据库 API v2.0规范&…

保命小诀窍:IDEA远程Debug技巧,你了解吗?

前言 昨天看到一个问题&#xff0c;“疫情结束后你最想吃什么&#xff1f;” 仔细想了一下&#xff0c;火锅&#xff1f;烤肉&#xff1f; 看了一下体重秤&#xff0c;怕是只能报个健身房了。 你以为你胖N斤的时间复杂度是O(2^N)&#xff0c; 事实上它是O(1)&#xff0c;嗖…

MySQL——MySQL的flush

有时候会出现这么一种情况&#xff1a;一条 SQL 语句&#xff0c;正常执行的时候特别快&#xff0c;但是有时也不知道怎么回事&#xff0c;它就会变得特别慢&#xff0c;并且这样的场景很难复现&#xff0c;它不只随机&#xff0c;而且持续时间还很短。 SQL语句为何变慢了 根…

Oracle单机部署:数据库安装

Oracle单机部署&#xff1a;数据库安装安装前须知数据库字符集自动内存管理数据库安装配置图形化安装安装后检查&#x1f42c; 使用oracle用户来安装数据库。 安装前须知 数据库字符集 在创建数据库之后&#xff0c;更改字符集在时间和资源上的代价都是非常昂贵的。可能需要…

全球银行最大分布式核心系统全面上线,邮储银行做到了!

摘要&#xff1a;近年来&#xff0c;国家陆续出台金融科技相关政策&#xff0c;提出创新驱动发展战略&#xff0c;强调以新一代信息和网络技术为支撑&#xff0c;拓展互联网金融&#xff0c;促进技术创新和商业模式创新的融合。本文分享自华为云社区《全球银行最大分布式核心系…

算法设计 - 01背包问题

学习来源 【自制】01背包问题算法动画讲解_哔哩哔哩_bilibili 问题描述 有N件物品&#xff0c;第i件物品的重量是w[i]&#xff0c;价值是p[i]。 有一个背包&#xff0c;背包的承重是W。 求解&#xff1a;将哪些物品装入背包可获得最大价值。 实例说明 有如下物品&#xff…

尚医通-MyBatis-Plus:条件查询Wapper(五)

&#xff08;1&#xff09;MyBatis-Plus&#xff1a;条件查询 实现对数据库复杂的条件操作&#xff1a; Wrapper &#xff1a; 条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper &#xff1a; 用于查询条件封装&#xff0c;生成 sql 的 where 条件 QueryWrapper &…