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

news2024/11/15 22:28:02

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语句优化是一个持续的过程,需要根据具体的业务场景和数据特点进行不断调整和优化。

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

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

相关文章

蓝桥杯每日真题 - 第12天

题目:(数三角) 题目描述(14届 C&C B组E题) 解题思路: 给定 n 个点的坐标,计算其中可以组成 等腰三角形 的三点组合数量。 核心条件:等腰三角形的定义是三角形的三条边中至少有…

Linux系统下svn新建目录

Linux安装svn自行查找 新建目录 新建一个自定义库的文件夹:mkdir security 使用svnadmin命令在新创建的目录中创建一个新的SVN版本库。例如: svnadmin create security 执行完成以上命令就会生成默认配置文件 通过pwd命令查找当前目录路径 路径&…

SpringCloud基础 入门级 学习SpringCloud 超详细(简单通俗易懂)

Spring Cloud 基础入门级学习 超详细(简单通俗易懂) 一、SpringCloud核心组件第一代:SpringCloud Netflix组件第二代:SpringCloud Alibaba组件SpringCloud原生组件 二、SpringCloud体系架构图三、理解分布式与集群分布式集群 四、…

性能调优专题(9)之从JDK源码级别解析JVM类加载机制

一、类加载运行全过程 当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到JVM。 package com.tuling.jvm;public class Math {public static final int initData 666;public static User user new User();public int compute() {…

【全面系统性介绍】虚拟机VM中CentOS 7 安装和网络配置指南

一、CentOS 7下载源 华为源:https://mirrors.huaweicloud.com/centos/7/isos/x86_64/ 阿里云源:centos-vault-7.9.2009-isos-x86_64安装包下载_开源镜像站-阿里云 百度网盘源:https://pan.baidu.com/s/1MjFPWS2P2pIRMLA2ioDlVg?pwdfudi &…

「JVM详解」

JVM JVM概述 基本介绍 JVM:全称 Java Virtual Machine,即 Java 虚拟机,一种规范,本身是一个虚拟计算机,直接和操作系统进行交互,与硬件不直接交互,而操作系统可以帮我们完成和硬件进行交互的…

正点原子IMX6ULL--嵌入式Linux开发板学习中常用命令和笔记记录

学习路线图 传驱动文件 sudo cp chrdevbase.ko chrdevbaseApp /home/txj/linux/nfs/rootfs/lib/modules/4.1.15/ -f bootcmd setenv bootcmd tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000 setenv bootcmd tftp 80800000 zImag…

DVWA靶场通关——SQL Injection篇

一,Low难度下unionget字符串select注入 1,首先手工注入判断是否存在SQL注入漏洞,输入1 这是正常回显的结果,再键入1 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for…

CSS回顾-基础知识详解

一、引言 在前端开发领域,CSS 曾是构建网页视觉效果的关键,与 HTML、JavaScript 一起打造精彩的网络世界。但随着组件库的大量涌现,我们亲手书写 CSS 样式的情况越来越少,CSS 基础知识也逐渐被我们遗忘。 现在,这种遗…

SSH和NFS

文章目录 SSH和NFS1 SSH远程管理1.1 概述1.2 ssh服务端和客户端1.3 用法1.3.1 服务器命令行的远程登录方式1.3.2 scp1.3.3 sftp1.3.4 ssh的密钥登录 2 NFS2.1 概述2.2 nfs操作步骤 SSH和NFS 1 SSH远程管理 1.1 概述 SSH(Secure Shell)协议是一种用于远…

Springboot 启动端口占用如何解决

Springboot 启动端口占用如何解决 1、报错信息如下 *************************** APPLICATION FAILED TO START ***************************Description:Web server failed to start. Port 9010 was already in use.Action:Identify and stop the process thats listening o…

SpringBoot 打造图片阅后即焚功能

阅后即焚”(Snapchat-like feature)是指一种社交媒体或信息传递功能,用户在阅读某条信息或查看某张图片后,该信息或图片会自动销毁,无法再次查看。这种功能的主要目的是保护用户的隐私和信息安全,防止敏感信…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析

前提: 注意的是:我们这里是从avframe转换成avpacket 后,从avpacket中查看NALU。 在实际开发中,我们有可能是从摄像头中拿到 RGB 或者 PCM,然后将pcm打包成avframe,然后将avframe转换成avpacket&#xff0…

Vue之插槽(slot)

插槽是vue中的一个非常强大且灵活的功能,在写组件时,可以为组件的使用者预留一些可以自定义内容的占位符。通过插槽,可以极大提高组件的客服用和灵活性。 插槽大体可以分为三类:默认插槽,具名插槽和作用域插槽。 下面…

华为鸿蒙HarmonyOS NEXT升级HiCar:打造未来出行新体验

随着科技的不断进步,智能出行已成为我们生活中不可或缺的一部分。华为凭借其在智能科技领域的深厚积累,推出了全新的鸿蒙HarmonyOS NEXT系统,旨在为用户打造一个“人车家”的无缝协同出行体验。这一系统的核心亮点之一,就是其内置…

Clickhouse集群新建用户、授权以及remote权限问题

新建用户 create user if not exists user on cluster 集群名称 IDENTIFIED WITH plaintext_password BY 密码;给用户授查询、建表、删表的权限 GRANT create table,select,drop table ON 数据库实例.* TO user on cluster 集群名称 ;在其他节点下用户建本地表成功&#…

Serverless架构在实时数据处理中的应用

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 Serverless架构在实时数据处理中的应用 Serverless架构在实时数据处理中的应用 Serverless架构在实时数据处理中的应用 引言 Ser…

Scrapy爬取heima论坛所有页面内容并保存到数据库中

前期准备: Scrapy入门_win10安装scrapy-CSDN博客 新建 Scrapy项目 scrapy startproject mySpider03 # 项目名为mySpider03 进入到spiders目录 cd mySpider03/mySpider03/spiders 创建爬虫 scrapy genspider heima bbs.itheima.com # 爬虫名为heima &#…

QSS 设置bug

问题描述: 在QWidget上add 一个QLabel,但是死活不生效 原因: c 主程序如下: QWidget* LOGO new QWidget(logo_wnd);LOGO->setFixedSize(logo_width, 41);LOGO->setObjectName("TittltLogo");QVBoxLayout* tit…

TKinter实现与Dash应用的同步启停控制

使用Python集成Tkinter和Dash:创建交互式数据可视化应用 在数据可视化项目中,我们经常需要结合传统GUI和现代Web可视化框架的优势。本文将介绍如何整合Tkinter和Dash,创建一个既有桌面应用界面,又能展示交互式图表的应用程序。 …