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

问:SQL优化,七条实践总结?

SQL语句优化是数据库性能调优的重要部分,通过合理的优化可以显著提升查询速度和系统性能。文章总结几种常见SQL语句优化方法。

1. 优化Where子句的顺序

原则:表之间的连接条件应写在其他Where条件之前,能够过滤掉最大数量记录的条件应优先写。

解释:数据库在执行查询时,会按照Where子句中的条件顺序进行过滤。如果最先执行的是最能缩小结果集的条件,那么后续的处理量将会大大减少,从而提高查询效率。

示例

-- 不优化的写法
SELECT * 
FROM orders o
WHERE o.order_date > '2023-01-01' AND o.customer_id = c.id AND c.region = 'North';-- 优化的写法
SELECT * 
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE c.region = 'North'AND o.order_date > '2023-01-01';

在优化的写法中,首先通过JOIN条件连接orderscustomers表,然后通过最能缩小结果集的条件c.region = 'North'进行过滤,最后才是其他条件。

2. 用EXISTS替代IN、用NOT EXISTS替代NOT IN

原则:在处理子查询时,使用EXISTS通常比IN更高效,特别是在子查询返回大量数据时。

解释EXISTS会在找到第一条匹配记录后立即返回结果,而IN则需要构建整个结果集再进行匹配。在大数据量情况下,EXISTS的性能优势更加明显。

示例

-- 使用IN的写法
SELECT * 
FROM orders 
WHERE customer_id IN (SELECT id FROM customers WHERE region = 'North');-- 使用EXISTS的写法
SELECT * 
FROM orders o
WHERE EXISTS (SELECT 1 FROM customers c WHERE c.id = o.customer_id AND c.region = 'North');

在这个例子中,使用EXISTS避免了构建包含所有customer_id的中间结果集,从而提高了查询效率。

3. 避免在索引列上使用计算

原则:在索引列上进行计算会导致索引失效,从而引发全表扫描。

解释:索引是预先计算并存储的,如果在索引列上进行计算(如加减乘除、函数等),数据库将无法直接使用索引,而是需要对每一行数据进行计算后再比较,这会导致性能大幅下降。

示例

-- 不优化的写法
SELECT * 
FROM orders 
WHERE YEAR(order_date) = 2023;-- 优化的写法
SELECT * 
FROM orders 
WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';

在优化的写法中,通过直接使用日期范围查询,避免了在order_date列上进行YEAR函数计算,从而能够利用索引提高查询效率。

4. 避免在索引列上使用IS NULL和IS NOT NULL

原则:在索引列上使用IS NULLIS NOT NULL会导致索引失效,应尽量避免。

解释:大多数数据库对NULL值的索引处理不够高效,使用IS NULLIS NOT NULL查询时,可能会导致全表扫描,从而影响性能。

示例

-- 不优化的写法
SELECT * 
FROM customers 
WHERE email IS NULL;-- 优化的写法(假设email字段允许空字符串代替NULL)
SELECT * 
FROM customers 
WHERE email = '';

在实际业务中,可以通过设置默认值(如空字符串)来代替NULL,从而避免在索引列上使用IS NULL查询。

5. 建立索引

原则:应尽量避免全表扫描,首先考虑在whereorder by涉及的列上建立索引。

解释:索引可以显著提高查询速度,特别是在处理大量数据时。通过在where条件和order by排序涉及的列上建立索引,可以大大减少数据扫描的行数,从而提高查询效率。

示例

-- 假设没有索引
SELECT * 
FROM orders 
WHERE customer_id = 123 
ORDER BY order_date;-- 建立索引
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
CREATE INDEX idx_orders_order_date ON orders(order_date);-- 使用索引后的查询
SELECT * 
FROM orders 
WHERE customer_id = 123 
ORDER BY order_date;

在建立索引后,查询性能会显著提升,因为数据库可以直接通过索引定位到符合条件的数据行,而无需进行全表扫描。

6. 避免在where子句中对字段进行null值判断

原则:尽量避免在where子句中对字段进行null值判断,否则将导致索引失效。

解释:与在索引列上使用IS NULL类似,直接在where子句中对字段进行null值判断也会导致索引失效,从而引发全表扫描。

示例

-- 不优化的写法
SELECT * 
FROM employees 
WHERE manager_id IS NULL;-- 优化的写法(通过业务逻辑避免NULL值)
SELECT * 
FROM employees 
WHERE manager_id = 0; -- 假设0表示没有经理

在实际业务设计中,可以通过特殊值(如0或-1)来代替NULL,从而避免在where子句中进行null值判断。

7. 避免在where子句中对字段进行表达式操作

原则:避免在where子句中对字段进行表达式操作,这将导致索引失效。

解释:在索引列上进行表达式操作(如加减乘除、字符串操作等)会导致索引失效,因为数据库需要对每一行数据进行计算后才能进行比较。

示例

-- 不优化的写法
SELECT * 
FROM products 
WHERE price * 1.1 > 100;-- 优化的写法
SELECT * 
FROM products 
WHERE price > 100 / 1.1;

在优化的写法中,通过将表达式移到比较值的右侧,避免了在price列上进行计算,从而能够利用索引提高查询效率。

综合实践

结合以上优化方法,我们可以对一个复杂的查询进行综合优化。假设我们有以下两个表:orders(订单表)和customers(客户表),我们需要查询2023年北区客户的所有订单,并按照订单日期排序。

未优化的查询

SELECT o.* 
FROM orders o
WHERE o.customer_id IN (SELECT c.id FROM customers c WHERE c.region = 'North')AND YEAR(o.order_date) = 2023
ORDER BY o.order_date;

优化后的查询

-- 首先建立索引
CREATE INDEX idx_customers_region ON customers(region);
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
CREATE INDEX idx_orders_order_date ON orders(order_date);-- 优化后的查询
SELECT o.* 
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE c.region = 'North'AND o.order_date BETWEEN '2023-01-01' AND '2023-12-31'
ORDER BY o.order_date;

在优化后的查询中,我们做了以下改进:

  1. 通过JOIN代替子查询,提高了连接效率。
  2. YEAR(o.order_date) = 2023替换为日期范围查询,避免了在索引列上进行计算。
  3. customers表的region列、orders表的customer_id列和order_date列上建立了索引,提高了查询速度。

通过这些优化措施,我们可以显著提升查询性能,特别是在处理大量数据时。SQL语句优化是一个持续的过程,需要根据具体的业务场景和数据特点进行不断调整和优化。

相关文章:

问:SQL优化,七条实践总结?

SQL语句优化是数据库性能调优的重要部分,通过合理的优化可以显著提升查询速度和系统性能。文章总结几种常见SQL语句优化方法。 1. 优化Where子句的顺序 原则:表之间的连接条件应写在其他Where条件之前,能够过滤掉最大数量记录的条件应优先写…...

unity单例模式的不同声明(待完善

总结: 这段代码实现了一个泛型单例模式(Singleton Pattern),用于确保某个类(由泛型参数 T 指定)在整个应用程序中只有一个实例,并且在第一次访问时才创建该实例。该模式保证了该实例的全局唯一…...

大模型在蓝鲸运维体系应用——蓝鲸运维开发智能助手

本文来自腾讯蓝鲸智云社区用户: CanWay 背景 1、运维转型背景 蓝鲸平台从诞生之初,就一直在不遗余力地推动运维转型,让运维团队可以通过一体化PaaS平台,快速编写脚本,编排流程,开发运维工具,从被动地提供…...

vue2,vue3响应式的理解

vue2的话主要使用的是defineProperty对已有属性添加get,set,从而完成对数据的响应式控制,但每次需要for循环对属性进行遍历 function DefineReactive(target, key, value) {//存在多层嵌套的objectObserver(value);Object.defineReactive(target, key, {get() {retu…...

群控系统服务端开发模式-应用开发-前端退出功能

我们从未登录一直到退出,现在已经登录到操作,现在完成退出。退出有两种情况下会退出:第一种情况下是手动点击退出按钮,第二种情况下是登录过期时间到了自动退出的。 一、手动退出 因退出及个人信息页面都在公有页面,所…...

Web入门

Spring 官网:Spring | Home Spring是一个开源的Java企业级应用开发框架。Spring的主要目的是使Java EE(Java Platform, Enterprise Edition)开发更容易,并且通过提供一系列丰富的库和接口来促进良好编程实践,是…...

基于SpringBoot网上超市的设计与实现录像

基于SpringBoot网上超市的设计与实现录像 SpringBoot网上超市的设计与实现录像...

python爬虫(二)爬取国家博物馆的信息

import requests from bs4 import BeautifulSoup# 起始网址 url https://www.chnmuseum.cn/zx/xingnew/index_1.shtml # 用于存储所有数据 all_data [] page 1 global_index 1 # 定义全局序号变量并初始化为1 while True:html_url requests.get(url).textif requests.get…...

【mysql的当前读和快照读】

在MySQL中,尤其是InnoDB存储引擎中,读操作主要分为两种:当前读(Current Read)和快照读(Snapshot Read) 当前读 当前读每次读取的都是当前最新的数据。这种读操作在读取数据时不允许其他事务对这…...

[CKS] Audit Log Policy

最近准备花一周的时间准备CKS考试,在准备考试中发现有一个题目关于audit policy的题目。 ​ 专栏其他文章: [CKS] Create/Read/Mount a Secret in K8S-CSDN博客[CKS] Audit Log Policy-CSDN博客 -[CKS] 利用falco进行容器日志捕捉和安全监控-CSDN博客[CKS] K8S Netw…...

【Linux】-学习笔记03

第十一章-管理Linux软件包和进程 1.源码下载安装软件 1.1概念 源码文件:程序编写者使用C或C等语言编写的原始代码文本文件 源码文件使用.tar.gz或.tar.bz2打包成压缩文件 1.2特点 源码包可移植性好,与待安装软件的工作环境依赖性不大 由于有编译过程…...

Leetcode热题100-32 最长有效括号

Leetcode热题100-32 最长有效括号 1. 题目描述2. 解题思路动态规划栈解法 3. 代码实现动态规划栈解法 1. 题目描述 32 最长有效括号 2. 解题思路 动态规划 定义状态: 设 dp[i] 表示以位置 i 结尾的最长有效括号子串的长度。 状态转移方程: 遍历字符…...

【大数据学习 | HBASE】hbase的读数据流程与hbase读取数据

1. hbase的读数据流程 在解析读取流程之前我们还需要知道两个功能性的组件和HFIle的格式信息 HFILE 存储在hdfs中的hbase文件,这个文件中会存在hbase中的数据以kv类型显示,同时还会存在hbase的元数据信息,包括整个hfile文件的索引大小&…...

A027-基于Spring Boot的农事管理系统

🙊作者简介:在校研究生,拥有计算机专业的研究生开发团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 赠送计算机毕业设计600…...

Redisson的可重入锁

初始状态: 表示系统或资源在没有线程持有锁的情况下的状态,任何线程都可以尝试获取锁。 线程 1 获得锁: 线程 1 首次获取了锁并进入受保护的代码区域。 线程 1 再次请求锁: 在持有锁的情况下,线程 1 再次请求锁&a…...

SQL Server Service Broker完整示例

目录 准备 创建Message,Contract,Queue和Service 创建调用存储过程 启用SQL Agent并创建Job执行存储过程 调用demo 常见故障排除 准备 判断你的数据库YourDatabaseName是否启用了Service Broker SELECT is_broker_enabled FROM sys.databases WH…...

CentOS7 升级OpenSSH9.0全过程和坑

近日,漏洞肆虐,需要升级新版本,才能解决漏洞。故有此文: 0 查看当前版本 [root@host-testsvc openssh-9.0p1]# ssh -V OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 20171、在data下新建一个独立目录openssh目录,用来存放软件 [root@host-testsvc data]# mkdir openssh…...

RSTP的配置

RSTP相对于STP在端口角色、端口状态、配置BPDU格式、配置BPDU的处理方式、快速收敛机制、拓扑变更机制和4种保护特性方面的详细改进说明: 端口角色: STP中定义了三种端口角色:根端口(Root Port)、指定端口&#xff0…...

力扣257:二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1: 输入:root [1,2,3,null,5] 输出:["1->2->5","1->3"]示例…...

Tcl 和 Python 在二次开发研究

引言 Tcl(Tool Command Language)和 Python 都是广泛应用于各种领域的编程语言,特别是在二次开发和自动化开发方面,两者有着独特的特性。Tcl 是一种动态的脚本语言,早期主要用于集成和控制其他程序,因此它经常出现在嵌入式应用和图形用户界面(GUI)开发中。而 Python 是…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...