SQL Server查询优化

news2025/3/17 23:12:52

最常用,最有效的数据库优化方式

查询语句层面

避免全表扫描
  • 使用索引:确保查询条件中的字段有索引。例如,查询语句 SELECT * FROM users WHERE age > 20,若 age 字段有索引,数据库会利用索引快速定位符合条件的记录,而不是全表扫描。
  • 优化查询条件:避免在 WHERE 子句中使用函数,因为这可能导致索引失效。如 SELECT * FROM users WHERE YEAR(created_at) = 2024,可改写为 SELECT * FROM users WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'
优化查询逻辑
  • 减少子查询:尽量用连接查询替代子查询。例如,原查询 SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE country = 'China') 可改写为 SELECT o.* FROM orders o JOIN customers c ON o.customer_id = c.id WHERE c.country = 'China'
  • 避免 SELECT *:只选择需要的列,减少数据传输量和数据库处理时间。

事务层面

减少事务持有时间
  • 优化事务逻辑:事务中包含的操作应尽量少,避免在事务中进行耗时的操作,如大量的数据计算或文件读写。
合理设置事务隔离级别
  • 选择合适级别:根据业务需求选择合适的事务隔离级别,避免使用过高的隔离级别导致并发性能下降。例如,对于一些对数据一致性要求不是特别高的场景,可使用 READ COMMITTED 隔离级别。

设计层面

表结构优化
  • 合理选择字段类型
    选择与数据匹配的最小数据类型,以节省存储空间并提高查询速度。例如,对于仅存储 0 - 255 范围内整数的字段,使用 TINYINT 而不是 INT。对于存储少量字符的字段,使用 VARCHAR 而非 TEXT
  • 主键和索引设计
    • 主键:使用自增整数作为主键,在 MySQL 中,自增主键能让数据在磁盘上顺序存储,提高插入和查询效率。
    • 索引:在经常用于查询条件(如 WHERE 子句)、排序(ORDER BY)和连接(JOIN)的字段上创建索引。例如,在用户表的 username 字段上创建索引,可加快根据用户名查找用户的查询速度。当经常需要多个字段组合查询时,创建复合索引。例如,对于查询 SELECT * FROM products WHERE category = 'Electronics' AND price < 1000,可创建复合索引 (category, price)。如果查询所需的数据都可以从索引中获取,数据库就无需再回表查询数据行,提高查询效率。
    • 重建或重新组织索引:随着数据的插入、更新和删除,索引可能会变得碎片化,影响查询性能。定期对索引进行重建或重新组织,可提高索引的效率。
数据库架构优化
  • 垂直拆分:将一个包含很多列的大表拆分成多个小表,每个小表包含原表的一部分列。例如,用户表中若包含基本信息(如姓名、性别)和扩展信息(如兴趣爱好、简介),可拆分成两个表,减少每次查询时需要读取的数据量。
  • 水平拆分:当单表数据量过大时,将数据按一定规则(如日期、地域等)分散到多个表中。如将订单表按年份拆分为多个表,每年一个表,能提高查询和维护效率。

服务器配置层面

内存配置
  • 调整缓存大小:对于关系型数据库如 MySQL,可增大 innodb_buffer_pool_size 参数,让数据库有更多内存用于缓存数据和索引,减少磁盘 I/O。一般可将其设置为服务器物理内存的 70% - 80%。
磁盘 I/O 优化
  • 使用 SSD 硬盘:相比传统的机械硬盘,SSD 硬盘具有更快的读写速度,能显著提高数据库的性能。
  • 合理规划磁盘布局:将数据文件、日志文件和临时文件分别存放在不同的磁盘分区,避免 I/O 竞争。

疑问解答

为什么尽量用连接查询替代子查询?

在 SQL Server 中,尽量使用连接查询替代子查询主要基于以下几个方面的原因:

性能方面
  • 执行计划与优化
    • 连接查询的执行计划通常更容易被 SQL Server 查询优化器理解和优化。优化器可以更有效地分析连接条件和表之间的关系,从而选择更合适的索引和执行策略。例如,对于两个表的连接查询,优化器可以根据表的大小、索引情况等因素选择嵌套循环连接、哈希连接或合并连接等方式。
    • 子查询在某些情况下可能会导致优化器难以生成最优的执行计划。尤其是相关子查询,它会针对外部查询的每一行都执行一次子查询,这可能会导致大量的重复计算,性能较差。例如下面的相关子查询:
SELECT column1, column2
FROM TableA
WHERE column1 > (SELECT AVG(column1) FROM TableB WHERE TableB.key = TableA.key);

这个查询会对 `TableA` 中的每一行都执行一次子查询来计算 `TableB` 中对应行的平均值,效率较低。

资源利用方面
  • 内存使用效率
    • 连接查询在内存使用上更加高效。它可以直接在内存中对多个表的数据进行关联处理,而不需要额外的临时表存储中间结果。
    • 子查询可能会占用更多的内存资源。特别是当子查询的结果集较大时,需要在内存中创建临时表来存储这些结果,这会增加内存的压力。

但在某些特定情况下,子查询可能更合适,例如需要获取满足特定条件的单个值或进行复杂的过滤操作时。因此,在实际应用中,需要根据具体的业务需求和数据情况来选择合适的查询方式。

索引碎片化产生的原因

数据频繁插入与删除:当数据库中频繁进行数据的插入和删除操作时,就容易导致索引碎片化。例如,在一个用户信息表中,不断有新用户注册(插入数据)和老用户注销(删除数据),这会使得索引页中的空闲空间变得零散,新的数据可能会被插入到这些分散的空闲空间中,从而造成索引数据的不连续。

数据更新:对索引列的数据进行更新操作也可能引发碎片化。如果更新操作导致索引键值的大小发生变化,就可能需要重新安排该索引项在索引页中的位置,进而破坏了索引的连续性。

SQL Server 中为什么要减少事务持有的时间

在 SQL Server 里,减少事务持有的时间至关重要,主要体现在以下几个方面:

提升并发性能
  • 锁的机制:在 SQL Server 中,事务执行期间会根据需要对数据资源加锁,以保证数据的一致性和完整性。锁会阻止其他事务对被锁定资源的访问。如果事务持有锁的时间过长,其他需要访问这些资源的事务就会被阻塞,只能等待锁被释放。
  • 示例:假设有一个在线商城系统,一个事务负责处理用户的订单,在事务执行期间对商品库存表加了排他锁。如果这个事务持有锁的时间过长,其他用户的订单处理事务就无法同时修改库存信息,会导致系统响应变慢,降低了系统的并发处理能力。
降低死锁风险
  • 死锁的产生:死锁是指两个或多个事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象,导致这些事务都无法继续执行下去。事务持有时间越长,与其他事务发生资源竞争的可能性就越大,死锁发生的概率也就越高。
  • 示例:事务 A 持有资源 X 的锁并请求资源 Y 的锁,而事务 B 持有资源 Y 的锁并请求资源 X 的锁,此时就会发生死锁。如果事务持有锁的时间较短,那么在其他事务请求相同资源之前,该事务可能已经完成并释放了锁,从而避免了死锁的发生。

SQL Server 进行多表连接,每两个表连接时的中间数据需要占用新的内存进行存储吗

在 SQL Server 中进行多表连接时,每两个表连接时的中间数据是否需要占用新的内存进行存储,取决于多种因素,下面为你详细分析:

通常情况下会使用内存存储中间结果

在大多数多表连接操作里,SQL Server 为了处理连接逻辑,往往会在内存中生成中间数据。当进行多表连接时,数据库引擎需要把参与连接的表中的行进行匹配操作,这个过程会产生中间结果集。例如,执行 SELECT * FROM TableA JOIN TableB ON TableA.ID = TableB.ID JOIN TableC ON TableB.OtherID = TableC.OtherID; 时,先对 TableATableB 进行连接操作,此时会在内存里生成一个中间结果集,这个结果集包含了 TableATableB 连接后的匹配行。接着再用这个中间结果集与 TableC 进行连接。这个中间结果集就需要占用一定的内存空间。

内存使用的优化策略

SQL Server 有一些机制来优化内存使用,避免过度存储中间数据:

  • 流式处理:对于某些连接类型和数据分布情况,SQL Server 可能采用流式处理的方式。在流式处理中,数据会逐行进行处理,而不是一次性将所有中间结果存储在内存中。例如,在嵌套循环连接算法中,如果其中一个表的数据量较小,SQL Server 可以将小表加载到内存中,然后逐行扫描大表,将匹配的行直接输出,而不需要存储完整的中间结果。

磁盘临时存储

当内存不足以存储中间数据时,SQL Server 会将部分中间数据存储到磁盘上的临时文件中。这通常发生在处理大规模数据或者复杂连接操作时。磁盘存储会显著降低查询性能,因为磁盘 I/O 操作比内存操作慢得多。

综上所述,每两个表连接时的中间数据通常需要占用一定的内存进行存储,但 SQL Server 会采取多种优化策略来尽量减少内存使用,并且在必要时会将数据存储到磁盘上。

执行计划

执行计划的主要作用

使用执行计划主要是对SQL语句进行问题诊断,从而对其存在的问题进行性能优化。比如,当查询执行缓慢时,执行计划可帮助开发者定位问题,判断是否全表扫描过多、索引未被正确使用,进而排查出语句本身逻辑、索引设置等问题。这样就能找出执行效率低的环节,针对性地调整查询语句、添加或修改索引,提升查询性能。

如何使用执行计划
 

未完待续。。。想了解如何使用执行计划的评论区扣1,我后续更新一下

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

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

相关文章

Blender插件NodeWrangler导入贴图报错解决方法

Blender用NodeWrangler插件 CtrlShiftT 导入贴图 直接报错 解决方法: 用CtrlshiftT打开需要导入的材质文件夹时&#xff0c;右边有一个默认勾选的相对路径&#xff0c;取消勾选就可以了。 开启node wrangler插件&#xff0c;然后在导入贴图是取消勾选"相对路径"&am…

java项目之基于ssm的药店药品信息管理系统(源码+文档)

项目简介 药店药品信息管理系统实现了以下功能&#xff1a; 个人信息管理 负责管理个人用户的信息。 员工管理 负责管理药店或药品管理机构的员工信息。 药品管理 负责管理药品的详细信息&#xff0c;可能包括药品名称、成分、剂量、价格、库存等。 进货管理 负责管理药品…

论文分享 | HE-Nav: 一种适用于复杂环境中空地机器人的高性能高效导航系统

阿木实验室始终致力于通过开源项目和智能无人机产品&#xff0c;为全球无人机开发者提供强有力的技术支持&#xff0c;并推出了开源项目校园赞助活动&#xff0c;助力高校学子在学术研究与技术创新中取得更大突破。近日&#xff0c;香港大学王俊铭同学&#xff0c;基于阿木实验…

ubuntu 24 安装 python3.x 教程

目录 注意事项 一、安装不同 Python 版本 1. 安装依赖 2. 下载 Python 源码 3. 解压并编译安装 二、管理多个 Python 版本 1. 查看已安装的 Python 版本 2. 配置环境变量 3. 使用 update-alternatives​ 管理 Python 版本 三、使用虚拟环境为项目指定特定 Python 版本…

【sql靶场】第13、14、17关-post提交报错注入保姆级教程

目录 【sql靶场】第13、14、17关-post提交报错注入保姆级教程 1.知识回顾 1.报错注入深解 2.报错注入格式 3.使用的函数 4.URL 5.核心组成部分 6.数据编码规范 7.请求方法 2.第十三关 1.测试闭合 2.列数测试 3.测试回显 4.爆出数据库名 5.爆出表名 6.爆出字段 …

93.HarmonyOS NEXT窗口管理基础教程:深入理解WindowSizeManager

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT窗口管理基础教程&#xff1a;深入理解WindowSizeManager 文章目录 HarmonyOS NEXT窗口管理基础教程&#xff1a;深入理解WindowSiz…

Python----数据分析(Pandas一:pandas库介绍,pandas操作文件读取和保存)

一、Pandas库 1.1、概念 Pandas是一个开源的、用于数据处理和分析的Python库&#xff0c;特别适合处理表格类数 据。它建立在NumPy数组之上&#xff0c;提供了高效的数据结构和数据分析工具&#xff0c;使得数据操作变得更加简单、便捷和高效。 Pandas 的目标是成为 Python 数据…

基于WebRTC技术的EasyRTC嵌入式音视频SDK:多平台兼容与性能优化

在当今数字化、智能化的时代背景下&#xff0c;实时音视频通信技术已成为众多领域不可或缺的关键技术。基于WebRTC技术的EasyRTC嵌入式音视频SDK&#xff0c;凭借其在ARM、Linux、Windows、安卓、iOS等多平台上的兼容性&#xff0c;为开发者提供了强大的工具&#xff0c;推动了…

【快速入门】MyBatis

一.基础操作 1.准备工作 1&#xff09;引入依赖 一个是mysql驱动包&#xff0c;一个是mybatis的依赖包&#xff1a; <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><vers…

交互式可视化进阶(Plotly Dash构建疫情仪表盘)

这里写目录标题 交互式可视化进阶(Plotly Dash构建疫情仪表盘)1. 引言2. 项目背景与意义3. 数据集生成与介绍4. GPU加速在数据处理中的应用5. 交互式仪表盘构建与Plotly Dash6. PyQt GUI集成与美化7. 工程整体架构8. 部分代码实现9. 代码自查与BUG排查10. 总结与展望交互式可…

如何选择适合您智能家居解决方案的通信协议?

如何选择适合您智能家居解决方案的通信协议&#xff1f; 在开发智能家居产品时&#xff0c;选择合适的通信协议对于设备的高效运行及其在智能家居系统中的互操作性至关重要。市面上协议众多&#xff0c;了解它们的特性并在做决定前考虑各种因素是非常必要的。以下是一些帮助您…

RabbitMQ可靠性进制

文章目录 1.生产者可靠性生产者重连生产者确认小结 2. MQ的可靠性数据持久化LazyQueue小结 3. 消费者的可靠性消费者确认机制消费者失败处理方案业务幂等性唯一消息ID业务判断 兜底方案业务判断 兜底方案 1.生产者可靠性 生产者重连 在某些场景下由于网络波动&#xff0c;可能…

版本控制器Git(5)

文章目录 前言一、理解标签二、创建标签三、操作标签四、多人协作场景一五、多人协作场景二总结 前言 本篇是最后一篇&#xff0c;主要介绍标签管理有关的内容 一、理解标签 标签定义&#xff1a;在Git中&#xff0c;标签&#xff08;tag&#xff09;是对某次提交&#xff08;c…

【数据分析】读取文件

3. 读取指定列 针对只需要读取数据中的某一列或多列的情况&#xff0c;pd.read_csv()函数提供了一个参数&#xff1a;usecols&#xff0c;将包含对应的columns的列表传入该参数即可。 上面&#xff0c;我们学习了读取 "payment" 和 "items_count" 这…

Dify使用部署与应用实践

最近在研究AI Agent&#xff0c;发现大家都在用Dify&#xff0c;但Dify部署起来总是面临各种问题&#xff0c;而且我在部署和应用测试过程中也都遇到了&#xff0c;因此记录如下&#xff0c;供大家参考。Dify总体来说比较灵活&#xff0c;扩展性比较强&#xff0c;适合基于它做…

Java 大视界 -- 基于 Java 的大数据机器学习模型的迁移学习应用与实践(129)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

1.Windows+vscode+cline+MCP配置

文章目录 1.简介与资源2.在windows中安装vscode及Cline插件1. 安装vscode2. 安装Cline插件3. 配置大语言模型3. 配置MCP步骤(windows) 1.简介与资源 MCP官方开源仓库 MCP合集网站 参考视频 2.在windows中安装vscode及Cline插件 1. 安装vscode 2. 安装Cline插件 Cline插件…

C#的字符串之String类与StringBuilder类区别于适用场景

一、分清楚值类型与引用类型 正确理解值类型与引用类型&#xff0c;可以更好的帮助软件开发人员写出性能更好且正确稳定运行的程序&#xff1a; C#值类型与引用类型区别 区别值类型引用类型定义所有继承自【System.ValueType】类型的都是值类型&#xff08;valueType继承自Sys…

关于WPS的Excel点击单元格打开别的文档的两种方法的探究【为单元格添加超链接】

问题需求 目录和文件结构如下&#xff1a; E:\Dir_Level1 │ Level1.txt │ └─Dir_Level2│ Level2.txt│ master.xlsx│└─Dir_Level3Level3.txt现在要在master.xlsx点击单元格进而访问Level1.txt、Level2.txt、Level3.txt这些文件。 方法一&#xff1a;“单元格右键…

conda的基本使用及pycharm里设置conda环境

创建conda环境 conda create --name your_env_name python3.8 把your_env_name换成实际的conda环境名称&#xff0c;python后边的根据自己的需要&#xff0c;选择python的版本。 激活conda环境 conda activate your_env_name 安装相关的包、库 conda install package_name …