SQL优化(一)基础概念
基数(cardinality)
表中某个列的唯一键的数量叫做基数,主键列的基数就是表中数据的总行数。
可以用select count(distinct 列名) from 表名来计算基数。
基数的高低影像列的数据分布。
例如:先用Scott账户创建一个测试表test
create table test  as select * from dba_objects 
owner列和object_id的基数如下所示
select count(distinct owner),count(distinct object_id),count(*) from test 
可以看出owner列的基数很小,再查询一下owner列的分布

可以看出owner列数据分布极不均匀,所以基数的大小代表数据分布情况。
选择性(selectivity)
选择性是某列的基数除以表数据的总行数在乘以100%计算出的值,代表该列数据分布均不均衡。
数据均衡分布是指该列基数中的值的条数大多在同一数量级上,或者最多与最少的数量级相差不大,例如主键列,各值的条数都是1。
要查看选择性,首先要对test表收集统计信息:
begindbms_stats.gather_table_stats(ownname          => 'SCOTT',tabname          => 'TEST',estimate_percent => 100,method_opt       => 'for all columns size 1',no_invalidate    => false,degree           => 1,cascade          => true);
end;
--method_opt传入for all columns size 1代表不收集直方图 
查看选择性,column_name为各列名称,num_rows为总行数,selectivity列即为选择性,cardinality为基数
select a.column_name,b.NUM_ROWS,a.num_distinct cardinality,round(a.num_distinct / b.NUM_ROWS * 100, 2) selectivity,a.HISTOGRAM,a.num_bucketsfrom dba_tab_col_statistics a, dba_tables bwhere a.owner = b.OWNERand a.table_name = b.TABLE_NAMEand a.owner = 'SCOTT'and a.table_name = 'TEST'; 

一般来说,选择性大于20,该列数据比较均衡,适合建立索引
直方图(histogram)
直方图是一种对数据分布情况进行描述的工具。它会按照某一列不同值出现数量多少,以及出现的频率高低来绘制数据的分布情况,以便能够指导基于成本的优化器(CBO)根据数据的分布做出正确的选择。如果没有对基数低的列收集直方图信息,CBO会认为该列数据均衡分布,从而会影响CBO使用索引扫描还是全表扫描的决策,也就是影响SQL的执行计划。

这个图的histogram列代表了是否收集直方图,NONE就是没有收集。执行以下程序对owner列收集直方图:
begindbms_stats.gather_table_stats(ownname          => 'SCOTT',tabname          => 'TEST',estimate_percent => 100,method_opt       => 'for columns owner size skewonly',no_invalidate    => false,degree           => 1,cascade          => true);
end;
--for columns owner size skewonly,对owner列收集,也可以对其他基数低的列收集
--method_opt传入for all columns size 1代表不收集直方图 

现在看出owner的直方图已经被收集了,对owner列收集直方图相当于执行
select owner,count(*) from test group by owner
然后将结果保存在shared_pool的数据字典中,CBO硬解析SQL时会参考数据字典的数据。
对于基数很低,选择性很低的列,强烈建议收集直方图。
数据块(data block)
数据块是oracle数据库存储的最小逻辑单元,数据块为2k、4k、8k、16k、32k等,默认块大小是8k,可以通过以下语句查询
select  bytes/blocks,f.* from dba_data_files f; 
 通过首列可以看出该数据库的块大小为8k。
逻辑读/物理读(consistent gets/physical reads)
 Oracle数据库读写的基本单位是数据块。当用户最终得到的结果可能只是某个数据块中的几行或几列。
 物理读: 当一个查询语句被执行时,Oracle服务器进程会将相关的数据块从磁盘的数据文件中加载到内存中的一块区域(buffer cache)。这个过程就叫做物理读。每读取一个数据块,即是一次物理读。物理读是真正操作磁盘IO,速度很慢。
逻辑读:将数据从buffer cache内存读取到PGA中,之后再返回给用户的过程。
由于内存中操作较快,所以得出同等数据量,逻辑读速度明显优于物理读,在SQL优化过程中要减少物理读次数。
索引(index)
索引是一种用于提高数据检索速度的数据库对象。对一个列创建索引,索引会包含该列键值以及对应行的rowid,rowid是行的唯一标识。
索引一般有两种数据结构:B+树和位图。
按类型分为:普通索引,唯一索引,主键也是一种唯一索引。
创建一个索引用以下语句,可以支持多列创建索引,又叫组合索引:
create index 索引名 on 表名(列名1,...列名n..)
SQL执行计划(SQL plan)
执行计划是对SQL执行的过程解析,执行计划显示了数据库如何处理SQL,包括数据的检索顺序、使用的索引、连接类型以及数据的处理方式等。通过执行计划可以看出SQL语句是怎么执行的,有没有按照预计的方案执行,有没有按照最高效的方式执行。
select * from test where owner='SCOTT' 
对以上SQL解释执行计划,得到下图
 由于这个SQL比较简单,所以执行计划也很简单,只需要一步操作全表扫描(TABLE ACCESS FULL)就可以检索出数据。
现在对owner列创建索引
   create index idx_test_owner on test(owner) 
再次查看执行计划
 因为我们对owner列已经收集过统计信息,CBO知道了该列的分布情况,使用了索引范围扫描(INDEX RANGE SCAN),并且少量回表取得数据。如果没有收集过统计信息,CBO认为该列是均匀分布的,很有可能会走全表扫描。
单条回表/批量回表
通过索引中的rowid再去访问表中的数据叫做回表,回表分单条和批量:
在执行计划中分别对应
TABLE ACCESS BY INDEX ROWID;
TABLE ACCESS BY INDEX ROWID BATCHED;

这个图中就存在单条回表,不过这里回表次数很少,性能影响比较小。
如果是大量单条回表,并且数据没有被缓存在buffer cache里,将会产生大量的物理读,会有严重的性能问题。在SQL优化中要尽量消除单条回表。
批量回表改善了单条回表的性能问题,但出现次数仍不宜过多。
总结
SQL优化涉及概念较多,需要不懂的概念及时查阅理解。
相关文章:
SQL优化(一)基础概念
基数(cardinality) 表中某个列的唯一键的数量叫做基数,主键列的基数就是表中数据的总行数。 可以用select count(distinct 列名) from 表名来计算基数。 基数的高低影像列的数据分布。 例如:先用Scott账户创建一个测试表test …...
【C++高阶】哈希:全面剖析与深度学习
目录 🚀 前言一: 🔥 unordered系列关联式容器1.1 unordered_map1.2 unordered_set 二: 🔥 哈希的底层结构 ⭐ 2.1 哈希概念⭐ 2.2 哈希冲突⭐ 2.3 哈希函数⭐ 2.4 哈希冲突解决2.4.1 🌄闭散列2.4.2 &#x…...
PHP西陆招聘求职系统小程序源码
🔥【职场新宠】西陆招聘求职系统,你的职场加速器🚀 🎉【开篇安利:一站式求职新体验】🎉 还在为找工作焦头烂额吗?是时候告别传统招聘网站的繁琐与低效了!今天给大家种草一个超赞的…...
系统移植(十一)根文件系统(未整理)
文章目录 一、根文件系统中各个目录文件功能解析:二、对busybox进行配置和编译(一)执行make help命令获取make的帮助信息(二)对busybox源码进行配置,配置交叉编译器(三)执行make men…...
mac中docker常用命令总结
在Mac中,Docker的常用命令可以总结如下表格: 命令用途docker run运行一个新的容器实例。可以指定镜像名来启动容器,并支持多种参数来调整容器的运行方式。docker ps列出当前正在运行的容器。可以通过添加-a参数来列出所有容器(包…...
Python 【机器学习】 进阶 之 【实战案例】房价数据中位数分析 [ 项目介绍 ] [ 获取数据 ] [ 创建测试集 ]| 1/3(含分析过程)
Python 【机器学习】 进阶 之 【实战案例】房价数据中位数分析 [ 项目介绍 ] [ 获取数据 ] [ 创建测试集 ]| 1/3(含分析过程) 目录 Python 【机器学习】 进阶 之 【实战案例】房价数据中位数分析 [ 项目介绍 ] [ 获取数据 ] [ 创建测试集 ]| 1/3&#x…...
Linux 4: Bash
1 Bash环境 1 命令执行的顺序 1 绝对路径、相对路径 2 alias 3 内置的builtin 4 $PATH找到的第一个命令 2 bash的登录信息,保存在哪里? 保存在/etc/issue. 3 bash的环境配置文件 1 如果是login shell,读以下,有优先级:如果…...
第十四天学习笔记2024.7.25
Git安装 1.安装git 2.创建git仓库 3.创建文件并且提交文件 (git add . 将文件提交到缓存)(git commit -m 说明)(git log 查看历史) 4.分支创建与解决分支冲突问题 创建主机(git 192.1…...
花几千上万学习Java,真没必要!(三十七)
IO 流: 读取数据到内存的过程:可以包括从硬盘、网络或其他存储设备中将数据加载到内存中,以便程序能够访问和处理这些数据。 写入数据到硬盘的过程:通常是将内存中的数据保存到硬盘或其他持久性存储设备中,以便长期存…...
SSA-GRU(自适应平滑自回归门控循环单元)预测模型及其Python和MATLAB实现
SSA-GRU(自适应平滑自回归门控循环单元)预测模型是结合了SSA(Singular Spectrum Analysis,奇异谱分析)和GRU(Gated Recurrent Unit,门控循环单元)模型的一种时间序列预测方法。以下是…...
【ROS】让你的回调函数并行起来
【前言】 众所周知,ROS中的所有回调函数,都由 ros::spin() 这个家伙来统一管理和唤醒。这里说的是所有通过ROS方式创建出来的回调函数,比如ros::Subscriber、ros::Timer等等的回调函数。 【举例】 我们先来看一个示例节点: #i…...
M12电连接器的编码分类及应用领域分析
12电连接器的编码主要包括A、B、C、D、X、S、T、K、L等类型,每种编码都有其特定的应用场景和功能: A编码:适用于传感器、直流电、1G以太网。 B编码:主要用于PROFIBUS总线系统。 C编码:适用于交流电。 D编码&#x…...
基于YOLOv8的道路裂缝坑洼检测系统
基于YOLOv8的道路裂缝坑洼检测系统 (价格88) 包含 【“裂缝”,“凹坑”】 2个类 通过PYQT构建UI界面,包含图片检测,视频检测,摄像头实时检测。 (该系统可以根据数据训练出的yolov8的权重文件,运用在其他检测系…...
蓝鹏测径仪非标定制订制流程
测径仪通常属于非标定制设备,非标定制意味着这些设备不是按照标准规格批量生产的,而是根据特定的客户需求和应用场景设计和制造的。例如,某些测径仪可能需要特殊的测量范围、精度、传感器或软件来满足特定的工业检测要求。 测径仪非标定制的…...
vue基础3
1.推荐好用的第三方框架 BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务 1.moment.js 2.dayjs 2.收集表达数据 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Document</title><…...
LINUX -exec函数族
1、功能: *让父子进程来执行不相干的操作 *能够替换进程地址空间的代码.text段 *执行另外的程序,不需要创建额外的的地址空间 *当前程序中调用另外一个应用程序 2、执行目录下的程序: *指定执行目录下的程序 int execl(const char *path,…...
c++ 智能指针shared_ptr与make_shared
shared_ptr是C11引入的一种智能指针,它允许多个shared_ptr实例共享同一个对象,通过引用计数来管理对象的生命周期。当最后一个持有对象的shared_ptr被销毁时,它会自动删除所指向的对象。这种智能指针主要用于解决资源管理问题&…...
2024-HW最新漏洞整理及相应解决方案(二)
目录 前言: 漏洞 1.用友NC系统电采complainjudge接口的sql注入漏洞 2.用友U8 CRM产品存在SQL注入漏洞 3.WordPress LMS 插件任意文件上传漏洞 4.Oracle Fusion Middleware 安全漏洞CVE-2024-21181 5.WordPress plugin LearnPress 安全漏洞CVE-2024-6589 6.W…...
spring boot整合JPA兼容MySQL8和达梦数据库8
前言 Spring Boot是一个基于Spring框架的快速开发框架,它可以简化Spring应用的配置和部署过程。JPA(Java Persistence API)是Java持久化规范的一种实现,它提供了一种统一的方式来访问和管理数据库。MySQL和达梦数据库都是常用的关…...
规划决策算法(四)---Frenet坐标系
知乎:坐标系转换 1.Frenet 坐标系 什么是 Frenet 坐标系: 为什么使用 Frenet 坐标系: 通常情况,我们只会关注车辆当前距离左右车道线的距离,来判断是否偏离车道,是否需要打方向盘进行方向微调。而不是基于…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
