SQL最佳实践:避免使用COUNT=0
如果你遇到类似下面的 SQL 查询:
SELECT *
FROM customer c
WHERE 0 = (SELECT COUNT(*)FROM orders oWHERE o.customer_id = c.customer_id);
意味着有人没有遵循 SQL 最佳实践。该语句的作用是查找没有下过订单的客户,其中子查询使用了 COUNT 函数统计客户的订单数量,如果结果等于零,代表没有订单。
从逻辑上来讲,以上查询没有问题;但是它可能存在性能问题。原因在于 COUNT 函数需要统计订单数量,如果某个客户有大量订单,数据库需要计算出一个总数;即使客户的订单数量不多,仍然需要进行统计。
以下是 MySQL 中的执行计划:
EXPLAIN ANALYZE
SELECT *
FROM customer c
WHERE 0 = (SELECT COUNT(*)FROM orders oWHERE o.customer_id = c.customer_id);-> Filter: (0 = (select #2)) (cost=111563.21 rows=1040858) (actual time=8.305..7043.840 rows=231117 loops=1)-> Table scan on c (cost=111563.21 rows=1040858) (actual time=6.968..1104.438 rows=1048577 loops=1)-> Select #2 (subquery in condition; dependent)-> Aggregate: count(0) (cost=1.30 rows=2) (actual time=0.005..0.005 rows=1 loops=1048577)-> Index lookup on o using customer_id (customer_id=c.customer_id) (cost=1.15 rows=2) (actual time=0.004..0.005 rows=2 loops=1048577)
其中Aggregate表示子查询中执行了聚合操作,查询的执行时间大概是 7 秒。
实际上这个 COUNT 函数结果对于我们并不重要,我们只需要知道客户是否存在订单。这种情况下,最简单的方法就是使用 EXISTS 运算符:
SELECT *
FROM customer c
WHERE NOT EXISTS (SELECT 1FROM orders oWHERE o.customer_id = c.customer_id);
如果客户存在任何订单,子查询就会获得结果,NOT EXISTS 运算符就会排除对应的客户,从而避免统计全部订单数据。新的执行计划如下:
EXPLAIN ANALYZE
SELECT *
FROM customer c
WHERE NOT EXISTS (SELECT 1FROM orders oWHERE o.customer_id = c.customer_id);-> Nested loop antijoin (cost=217780392498.61 rows=2177801765412) (actual time=2273.676..3746.089 rows=231117 loops=1)-> Table scan on c (cost=111871.61 rows=1040858) (actual time=2.191..804.896 rows=1048577 loops=1)-> Single-row index lookup on <subquery2> using <auto_distinct_key> (customer_id=c.customer_id) (actual time=0.000..0.000 rows=1 loops=1048577)-> Materialize with deduplication (cost=423621.04..423621.04 rows=2092314) (actual time=2797.545..2797.545 rows=1021689 loops=1)-> Filter: (o.customer_id is not null) (cost=214389.64 rows=2092314) (actual time=0.811..1372.007 rows=2097157 loops=1)-> Index scan on o using customer_id (cost=214389.64 rows=2092314) (actual time=0.809..1164.613 rows=2097157 loops=1)
新的查询计划使用了 antijoin 连接和物化(Materialize),执行时间不到 4 秒。
无论用户订单数量多还是少,NOT EXISTS 的性能都不会差于 COUNT 函数,而且绝大部分情况下它的性能会更好。
相关文章:
SQL最佳实践:避免使用COUNT=0
如果你遇到类似下面的 SQL 查询: SELECT * FROM customer c WHERE 0 (SELECT COUNT(*)FROM orders oWHERE o.customer_id c.customer_id);意味着有人没有遵循 SQL 最佳实践。该语句的作用是查找没有下过订单的客户,其中子查询使用了 COUNT 函数统计客…...
PG与ORACLE的差距
首先必须是XID 64,一个在极端环境下会FREEZE的数据库无论如何都无法承担关键业务系统的重任的,我们可以通过各种配置,提升硬件的性能,通过各种IT管控措施来尽可能避免在核心系统上面临FREEZE的风险,不过并不是每个企业…...
树莓派3B+驱动开发(2)- LED驱动(传统模式)
github主页:https://github.com/snqx-lqh 本项目github地址:https://github.com/snqx-lqh/RaspberryPiDriver 本项目硬件地址:https://oshwhub.com/from_zero/shu-mei-pai-kuo-zhan-ban 欢迎交流 笔记说明 如我在驱动开发总览中说的那样&…...
超详细搭建PhpStorm+PhpStudy开发环境
刚开始接触PHP开发,搭建开发环境是第一步,网上下载PhpStorm和PhpStudy软件,怎样安装和激活就不详细说了,我们重点来看一看怎样搭配这两个开发环境。 前提:现在假设你已经安装完PhpStorm和PhpStudy软件。 我的PhpStor…...
分析比对vuex和store模式
在 Vue 中,Vuex 和 store 模式 是两个不同的概念,它们紧密相关,主要用于管理应用的状态。下面我会详细介绍这两个概念,并通过例子帮助你更好地理解。 1. Vuex 是什么? Vuex 是 Vue.js 的一个状态管理库,用…...
C# 网络编程--基础核心内容
在现今软件开发中,网络编程是非常重要的一部分,本文简要介绍下网络编程的概念和实践。 C#网络编程的主要内容包括以下几个方面: : 上图引用大佬的图,大家也关注一下,有技术有品质,有国有家,情…...
【C++游戏程序】easyX图形库还原游戏《贪吃蛇大作战》(三)
承接上一篇文章:【C游戏程序】easyX图形库还原游戏《贪吃蛇大作战》(二),我们这次来补充一些游戏细节,以及增加吃食物加长角色长度等设定玩法,也是本游戏的最后一篇文章。 一.玩家边界检测 首先是用来检测…...
uni-app H5端使用注意事项 【跨端开发系列】
🔗 uniapp 跨端开发系列文章:🎀🎀🎀 uni-app 组成和跨端原理 【跨端开发系列】 uni-app 各端差异注意事项 【跨端开发系列】uni-app 离线本地存储方案 【跨端开发系列】uni-app UI库、框架、组件选型指南 【跨端开…...
SpringBoot中的@Configuration注解
在Spring Boot中,Configuration注解扮演着非常重要的角色,它是Spring框架中用于定义配置类的一个核心注解。以下是Configuration注解的主要作用: 定义配置类: 使用Configuration注解的类表示这是一个配置类,Spring容器…...
十二、路由、生命周期函数
router路由 页面路由指的是在应用程序中实现不同页面之间的跳转,以及数据传递。通过 Router 模块就可以实现这个功能 2.1创建页面 之前是创建的文件,使用路由的时候需要创建页面,步骤略有不同 方法 1:直接右键新建Page(常用)方法 2:单独添加页面并配置2.1.1直接右键新建…...
【蓝桥杯每日一题】X 进制减法
X 进制减法 2024-12-6 蓝桥杯每日一题 X 进制减法 贪心 进制转换 题目大意 进制规定了数字在数位上逢几进一。 XX 进制是一种很神奇的进制, 因为其每一数位的进制并不固定!例如说某 种 XX 进制数, 最低数位为二进制, 第二数位为十进制, 第三数位为八进制, 则 XX 进制…...
《蓝桥杯比赛规划》
大家好啊!我是NiJiMingCheng 我的博客:NiJiMingCheng 这节课我们来分享蓝桥杯比赛规划,好的规划会给我们的学习带来良好的收益,废话少说接下来就让我们进入学习规划吧,加油哦!!! 一、…...
C++算法练习day70——53.最大子序和
题目来源:. - 力扣(LeetCode) 题目思路分析 题目:寻找最大子数组和(也称为最大子序和)。 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素&#x…...
import是如何“占领满屏“
import是如何“占领满屏“的? 《拒绝使用模块重导(Re-export)》 模块重导是一种通用的技术。在腾讯、字节、阿里等各大厂的组件库中都有大量使用。 如:字节的arco-design组件库中的组件:github.com/arco-design… …...
ceph /etc/ceph-csi-config/config.json: no such file or directory
环境 rook-ceph 部署的 ceph。 问题 kubectl describe pod dragonfly-redis-master-0Warning FailedMount 7m59s (x20 over 46m) kubelet MountVolume.MountDevice failed for volume "pvc-c63e159a-c940-4001-bf0d-e6141634cc55" : rpc error: cod…...
C语言——验证“哥德巴赫猜想”
问题描述: 验证"哥德巴赫猜想" 任何一个大于2的偶数都可以表示为两个质数之和。例如,4可以表示为22,6可以表示为33,8可以表示为35等 //验证"哥德巴赫猜想" //任何一个大于2的偶数都可以表示为两个质数之和…...
Flourish笔记:柱状图(Column chart (grouped))
文章目录 样式设定Chart Type:图表类型Controls & Filters:展示方式Colors:颜色bars:柱子的调整labels:柱子数字标注X axis:横坐标标签Y axis:纵坐标标签Plot BackgroundNumber FormatingLe…...
深度学习案例:DenseNet + SE-Net
本文为为🔗365天深度学习训练营内部文章 原作者:K同学啊 一 回顾DenseNet算法 DenseNet(Densely Connected Convolutional Networks)是一种深度卷积神经网络架构,提出的核心思想是通过在每一层与前面所有层进行直接连接…...
excel文件合并,每个excel名称插入excel列
import pandas as pd import os # 设置文件夹路径 folder_path rC:\test # 替换为您的下载文件夹路径 output_file os.path.join(folder_path, BOM材料.xlsx) # 创建一个空的 DataFrame 用于存储合并的数据 combined_data pd.DataFrame() # 遍历文件夹中的所有文件 for …...
Linux 如何设置特殊权限?
简介 通过使用 setuid、setgid 、sticky,它们是 Linux 中的特殊权限,可以对文件和目录的访问和执行方式提供额外的控制。 命令八进制数字功能setuid4当执行文件时,它以文件所有者的权限运行,而不是执行它的用户的权限运行。setg…...
三行六列16车位立体车库mcgs6.2仿真程序
三行六列16车位立体车库mcgs6.2仿真程序立体车库仿真程序最让人上头的就是运动逻辑设计。今天拆解一个三行六列布局的MCGS6.2项目,看看如何用脚本驱动16个车位的升降动画。注意这里的车位排布有点特殊——虽然看起来是3*6的矩阵,但实际有两处隐藏车位被改…...
基于ATP的10kV并联电容暂态过程仿真
基于ATP的10kV并联电容暂态过程仿真在电力系统中,10kV并联电容装置起着至关重要的作用,比如提高功率因数、改善电压质量等。然而,其暂态过程却较为复杂,需要深入研究。ATP(Alternative Transients Program)…...
别再只用M法了!手把手教你用Arduino和旋转编码器实现M/T法测速(附代码)
别再只用M法了!手把手教你用Arduino和旋转编码器实现M/T法测速(附代码) 在电机控制项目中,精确的速度测量往往是实现闭环控制的第一步。许多初学者会直接采用简单的M法(频率测量法),但在实际测试…...
Ubuntu20.04安全重启后WiFi图标消失?MT7922网卡驱动修复全攻略
Ubuntu 20.04安全重启后MT7922网卡驱动失效的深度修复指南 问题现象与初步诊断 当你使用REISUB组合键对Ubuntu 20.04进行安全重启后,可能会发现桌面右上角的WiFi图标神秘消失。这不是简单的界面显示问题,而是MT7922无线网卡驱动未能正常加载导致的深层…...
10BASE-T1S PLCA参数配置避坑指南:从Node ID重复到Burst Timer设置,这些坑你踩过几个?
10BASE-T1S PLCA参数配置避坑指南:从Node ID重复到Burst Timer设置,这些坑你踩过几个? 在车载以太网的实际部署中,10BASE-T1S因其单对线缆实现多节点通信的特性,正逐渐成为智能座舱和传感器网络的热门选择。但当我们真…...
M3U8 开发调试神器!m3u8live.cn轻量在线播放器高效解决流媒体开发痛点
在音视频开发、直播推流、点播平台搭建的日常工作中,M3U8 链接有效性验证、HLS 流播放调试是高频刚需。传统方案要么需要安装 VLC 等本地播放器进行繁琐的网络串流配置,要么第三方工具广告泛滥、兼容性差,甚至需要编写测试代码才能完成简单的…...
单片机Shell开发避坑指南:从Putty特殊字符处理到内存安全的7个实战经验
单片机Shell开发避坑指南:从Putty特殊字符处理到内存安全的7个实战经验 当你在深夜调试单片机Shell时,突然发现退格键会导致整个系统崩溃,或者用户输入超长字符串后设备莫名其妙重启——这些看似简单的交互问题,往往成为项目交付前…...
炉石传说脚本Hearthstone-Script:三步从零到精通的自动化游戏指南 [特殊字符]
炉石传说脚本Hearthstone-Script:三步从零到精通的自动化游戏指南 🎮 【免费下载链接】Hearthstone-Script Hearthstone script(炉石传说脚本)(2024.01.25停更至国服回归) 项目地址: https://gitcode.com…...
从QEMU仿真到真机烧录:用Yocto为ArmSoM-Sige7开发板定制RK3588镜像的完整流程
从QEMU仿真到真机烧录:用Yocto为ArmSoM-Sige7开发板定制RK3588镜像的完整流程 在嵌入式开发领域,能够快速验证软件栈的可行性并最终部署到真实硬件是每个开发者的核心诉求。本文将带你完整走通从虚拟仿真到实体部署的全链路,使用Yocto项目为搭…...
Thermal Control Center:Dell G15散热管理的开源替代方案实战指南
Thermal Control Center:Dell G15散热管理的开源替代方案实战指南 【免费下载链接】tcc-g15 Thermal Control Center for Dell G15 - open source alternative to AWCC 项目地址: https://gitcode.com/gh_mirrors/tc/tcc-g15 在追求极致性能的游戏本领域&…...
