SQL Server 百万数据查询优化技巧三十则

点击上方蓝字关注我

a1c8ce07c866d972475080c566569c5f.png

    互联网时代的进程越走越深,使用MySQL的人也越来越多,关于MySQL的数据库优化指南很多,而关于SQL SERVER的T-SQL优化指南看上去比较少,近期有学习SQLSERVER的同学问到SQL SERVER数据库有哪些优化建议?本文列举了部分常见的优化建议,具体内容如下:

1.   优化建议

  • 索引优化:

    eg:考虑一个订单表 Orders,其中有列 OrderDate 和 CustomerID。如果经常需要按订单日期范围和顾客ID进行查询,可以在这两列上建立复合索引,以提高查询性能。

  • NULL 值判断避免全表扫描:

    eg:对于包含 status 列的用户表 Users,避免使用 SELECT * FROM Users WHERE status IS NULL,可以在设计表时设置 status 默认值,确保所有用户都有一个状态,然后使用 SELECT * FROM Users WHERE status = 0 进行查询。

  • != 或 <> 操作符避免全表扫描:

    eg:考虑一个产品表 Products,如果要查询所有不属于某个特定类别的产品,避免使用 SELECT * FROM Products WHERE CategoryID != 5,而是使用 SELECT * FROM Products WHERE CategoryID <> 5。

  • OR 连接条件避免全表扫描:

    eg:对于一个学生成绩表 Grades,如果需要查询得分为 A 或 B 的记录,避免使用 SELECT * FROM Grades WHERE Grade = 'A' OR Grade = 'B',而是使用 SELECT * FROM Grades WHERE Grade = 'A' UNION ALL SELECT * FROM Grades WHERE Grade = 'B'。

  • IN 和 NOT IN 避免全表扫描:

    eg:考虑一个员工表 Employees,如果需要查询属于某个特定部门的员工,避免使用 SELECT * FROM Employees WHERE DepartmentID IN (1, 2, 3),而是使用 SELECT * FROM Employees WHERE DepartmentID BETWEEN 1 AND 3。

  • LIKE 查询优化:

    eg:在一个文章表 Articles 中,如果需要模糊查询标题包含关键词的文章,避免使用 SELECT * FROM Articles WHERE Title LIKE '%SQL%',可以考虑全文检索或者其他优化方式。

  • 参数使用避免全表扫描:

    eg:在一个订单表 Orders 中,如果需要根据输入的订单号查询订单信息,避免使用 SELECT * FROM Orders WHERE OrderID = @OrderID,可以使用强制索引的方式,如 SELECT * FROM Orders WITH(INDEX(OrderID_Index)) WHERE OrderID = @OrderID。

  • 字段表达式操作避免全表扫描:

    eg:在一个商品表 Products 中,如果需要查询价格除以2等于100的商品,避免使用 SELECT * FROM Products WHERE Price/2 = 100,可以改为 SELECT * FROM Products WHERE Price = 100*2。

  • 字段函数操作避免全表扫描:

    eg:在一个员工表 Employees 中,如果需要查询名字以"Smith"开头的员工,避免使用 SELECT * FROM Employees WHERE LEFT(LastName, 5) = 'Smith',可以改为 SELECT * FROM Employees WHERE LastName LIKE 'Smith%'。

  • 不要在“=”左边进行函数、算术运算:

eg:在一个库存表 Inventory 中,避免使用 SELECT * FROM Inventory WHERE YEAR(StockDate) = 2023,而是使用 SELECT * FROM Inventory WHERE StockDate >= '2023-01-01' AND StockDate < '2024-01-01'。

  • 索引字段顺序使用避免全表扫描:

eg:在一个订单表 Orders 中,如果有复合索引 (CustomerID, OrderDate),查询时应该先使用 CustomerID,如 SELECT * FROM Orders WHERE CustomerID = @CustomerID AND OrderDate BETWEEN @StartDate AND @EndDate。

  • 避免写没有意义的查询:

eg:不建议使用 SELECT col1, col2 INTO #t FROM t WHERE 1 = 0,可以改为明确创建表结构并使用 CREATE TABLE #t (...)。

  • 使用 EXISTS 代替 IN:

eg:在一个产品表 Products 中,避免使用 SELECT * FROM Products WHERE ProductID IN (SELECT ProductID FROM DiscontinuedProducts),可以改为 SELECT * FROM Products WHERE EXISTS (SELECT 1 FROM DiscontinuedProducts WHERE ProductID = Products.ProductID)。

  • 索引不一定对所有查询有效:

    eg:在一个性别字段 Gender 几乎均匀分布的表中,对 Gender 建立索引可能不会提高查询效率。

  • 索引数量谨慎选择:

    eg:在一个订单表 Orders 中,不宜过多地在每个列上建立索引,需要根据查询和更新的具体需求进行权衡。

  • 更新 clustered 索引数据列谨慎操作:

eg:在一个用户表 Users 中,如果频繁更新用户姓名,考虑是否将姓名列设为非聚集索引,以避免整个表记录顺序调整。

  • 使用数字型字段:

    eg:在一个学生成绩表 Grades 中,如果考试成绩以整数形式表示,使用整数型字段而非字符型字段。

  • 使用 VARCHAR/NVARCHAR:

eg:在一个文章表 Articles 中,如果存储文章内容,使用 VARCHAR(MAX) 而非 TEXT。

  • 避免使用 SELECT *:

eg:在一个员工表 Employees 中,避免使用 SELECT * FROM Employees,而是明确指定需要的列,如 SELECT EmployeeID, FirstName, LastName FROM Employees。

  • 使用表变量代替临时表:

eg:在一个小型数据集的情况下,可以使用表变量而不是创建临时表来存储中间结果。例如,使用表变量替代以下的临时表:

-- 不推荐
CREATE TABLE #TempResults (ID INT,Name VARCHAR(255),...-- 推荐
DECLARE @TempResults TABLE (ID INT,Name VARCHAR(255),...
);
  • 避免频繁创建和删除临时表:

eg:在一个存储过程中,如果需要多次使用相同的临时表,不要在每次使用时都创建和删除,而是在存储过程的开头创建一次,最后删除。

  • 合理使用临时表:

eg:在一个复杂的查询中,如果需要多次引用中间结果,可以考虑使用临时表。但应注意不要滥用,确保临时表的使用是必要的。

  • 选择合适的临时表创建方式:

eg:在需要一次性插入大量数据的情况下,可以使用 SELECT INTO 替代 CREATE TABLE 和 INSERT 的两步操作,以减少日志记录。

-- 不推荐
CREATE TABLE #TempTable (ID INT,Name VARCHAR(255),...
);INSERT INTO #TempTable
SELECT ID, Name, ...
FROM SomeTable;-- 推荐
SELECT ID, Name, ...
INTO #TempTable
FROM SomeTable;
  • 显式删除临时表:

eg:在存储过程或脚本的最后,确保显式删除所有创建的临时表,以释放系统表资源。

-- 不推荐
DROP TABLE #TempTable;-- 推荐
TRUNCATE TABLE #TempTable;
DROP TABLE #TempTable;
  • 避免使用游标:

eg:在一个订单表 Orders 中,避免使用游标来逐行处理数据,可以考虑使用集合操作或者其他优化方法。

  • 基于集的方法替代游标或临时表:

eg:在需要对大量数据进行操作时,尽量寻找基于集的解决方案,以避免使用游标或临时表。例如,使用窗口函数或联接来处理数据。

  • 存储过程中使用 SET NOCOUNT ON/OFF:

eg:在存储过程中使用 SET NOCOUNT ON 和 SET NOCOUNT OFF,以减少向客户端发送 DONE_IN_PROC 消息,提高性能。

-- 存储过程开头
SET NOCOUNT ON;-- 存储过程结尾
SET NOCOUNT OFF;
  • 避免大事务操作:

eg:在一个银行交易表 Transactions 中,避免在一个事务中处理过多的交易记录,以提高系统并发能力。

  • 避免向客户端返回大数据量:

eg:在一个日志表 Logs 中,如果查询可能返回大量的日志记录,应该审查客户端是否真的需要这么多数据,考虑分页或其他方式减少返回的数据量。

  • SQL Server执行计划掌握:

使用EXPLAINShow Execution Plan分析查询执行计划,发现潜在问题。

2.  结语

    熟悉其他数据库的同学应该也能对比出,很多数据库的优化经验是相通的,所以在学习其他数据库的时候可以借鉴已掌握的经验去对比学习,这样学习起来也会事半功倍。

3c8df4c32533400513c768f226a22373.png

往期精彩回顾

1.  MySQL高可用之MHA集群部署

2.  mysql8.0新增用户及加密规则修改的那些事

3.  比hive快10倍的大数据查询利器-- presto

4.  监控利器出鞘:Prometheus+Grafana监控MySQL、Redis数据库

5.  PostgreSQL主从复制--物理复制

6.  MySQL传统点位复制在线转为GTID模式复制

7.  MySQL敏感数据加密及解密

8.  MySQL数据备份及还原(一)

9.  MySQL数据备份及还原(二)

b50ef1488723ac35497d55cfeaca6b92.png

扫码关注     

f8c36cc9084415172549eb98165a2c1c.jpeg

775268cd63f124511a50f8d8d9b92735.png

dc06f175e904097159dd33fbece3fdb2.png

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

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

相关文章

Linux进程通信——信号(一)

原理 对于 Linux来说&#xff0c;实际信号是软中断&#xff0c;许多重要的程序都需要处理信号。 信号&#xff0c;为 Linux 提供了一种处理异步事件的方法。比如&#xff0c;终端用户输入了ctrlc来中断程序&#xff0c;会通过信号机制停止一个程序。 概述 信号的名字和编号 …

【Docker】从零开始:8.Docker命令:Commit提交命令

【Docker】从零开始&#xff1a;8.Docker命令:Commit命令 基本概念镜像镜像分层什么是镜像分层为什么 Docker 镜像要采用这种分层结构 本章要点commit 命令命令格式docker commit 操作参数实例演示1.下载一个新的ubuntu镜像2.运行容器3.查看并安装vim4.退出容器5提交自己的镜像…

【数据结构/C++】线性表_双链表基本操作

#include <iostream> using namespace std; typedef int ElemType; // 3. 双链表 typedef struct DNode {ElemType data;struct DNode *prior, *next; } DNode, *DLinkList; // 初始化带头结点 bool InitDNodeList(DLinkList &L) {L (DNode *)malloc(sizeof(DNode))…

成为AI产品经理——模型评估概述

目录 一、模型宣讲和评估的原因 二、模型宣讲 三、模型评估 1. 重要特征 ① 特征来源 ②特征意义 2.选择测试样本 3.模型性能和稳定性 一、模型宣讲和评估的原因 刘海丰老师提到他们在做一个金融AI产品未注重模型指标&#xff0c;过于注重业务指标&#xff0c;导致产生…

解决:ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘

解决&#xff1a;ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘ 背景 在使用之前的代码时&#xff0c;报错&#xff1a; from keras.optimizers import Adam ImportError: cannot import name ‘Adam’ 报错问题 from keras.optimizers import Adam I…

【Java 进阶篇】Redis持久化之RDB:数据的安全守护者

Redis&#xff0c;作为一款高性能的键值存储系统&#xff0c;支持多种持久化方式&#xff0c;其中RDB&#xff08;Redis DataBase&#xff09;是其最常用的一种。RDB可以将当前时刻的数据快照保存到磁盘&#xff0c;以便在Redis重启时快速恢复数据。本文将深入探讨RDB的原理、配…

飞书智能伙伴之 AI 数智参谋:先进团队,北极星指标也要遥遥领先

11 月 22 日&#xff0c;飞书在 2023 秋季飞书未来无限大会上正式发布了飞书智能伙伴。作为首批生态伙伴&#xff0c;基于 Kyligence 智能一站式指标平台实现的 AI 数智参谋也正式亮相。这是继 11 月 21 日 Kyligence 产品发布会后&#xff0c;Kyligence 在数据驱动决策智能领域…

第十五届蓝桥杯(Web 应用开发)模拟赛 1 期-大学组(详细分析解答)

目录 1.动态的Tab栏 1.1 题目要求 1.2 题目分析 1.3 源代码 2.地球环游 2.1 题目要求 2.2 题目分析 2.3 源代码 3.迷惑的this 3.1 题目要求 3.2 题目分析 3.3 源代码 4.魔法失灵了 4.1 题目要求 4.2 题目分析 4.3 源代码 5.燃烧你的卡路里 5.1 题目要求 5.2…

第十七章:数据库操作

数据库基础 SQL语言 1、select 语句 select 语句用于从数据中检索数据。语法如下&#xff1a; SELECT 搜选字段列表 FROM 数据表名 WHERE 条件表达式 GROUP BY 字段名 HAVING 条件表达式(指定分组的条件) ORDER BY 字段名[ASC|DESC] 2、insert 语句 insert 语句用于向表中插入…

【UE5】五大基类及其使用

UObject UObject表示对象&#xff0c;准确来说&#xff0c;虚幻引擎中的对象基础类为UObject UObject提供了以下功能&#xff1a; 垃圾收集&#xff08;Garbage collection&#xff09;引用自动更新&#xff08;Reference updating&#xff09;反射&#xff08;Reflection&am…

计算机基础知识57

前后端数据传输的编码格式(contentType) # 我们只研究post请求方式的编码格式&#xff1a; get请求方式没有编码格式-- index?useranme&password get请求方式没有请求体&#xff0c;参数直接在url地址的后面拼接着 # 有哪些方式可以提交post请求&#xff1a;f…

构建个性化预约服务:预约上门服务系统源码解读与实战

随着社会的发展&#xff0c;预约上门服务系统在满足用户需求、提升服务效率方面发挥着越来越重要的作用。在本文中&#xff0c;我们将深入研究预约上门服务系统的源码&#xff0c;通过实际的技术代码示例&#xff0c;揭示系统内部的关键机制&#xff0c;以及如何在实际项目中应…

深入了解接口测试:方法、工具和关键考虑因素(一)

接口测试是软件测试中的一项重要工作&#xff0c;它涉及到系统与系统之间的交互点。接口可以是外部接口&#xff0c;也可以是内部接口&#xff0c;包括上层服务与下层服务接口以及同级接口。在接口测试中&#xff0c;我们需要确保接口能够按照预期的方式进行通信和交互&#xf…

【攻防世界-misc】can_has_stdio?

1.用记事本打开文件是这样子的&#xff0c; 这是一段BF&#xff08;Brainfuck&#xff09;编程语言代码&#xff0c;属于一种极简化的编程语言&#xff0c;用于演示计算机程序设计概念。这段代码包含了一些操作符&#xff0c;如">"表示指针向右移动&#xff0c;&q…

【C++破局】泛型编程|函数模板|类模板

​作者主页 &#x1f4da;lovewold少个r博客主页 ⚠️本文重点&#xff1a;c模板初阶知识点讲解 &#x1f449;【C-C入门系列专栏】&#xff1a;博客文章专栏传送门 &#x1f604;每日一言&#xff1a;花有重开日&#xff0c;人无再少年 目录 前言 泛型编程 函数模板 函数模…

用Java实现简易的图书管理系统(超详细)

目录 1.设计背景 2.设计思路 3.模块展示及代码演示 3.1 Book类的实现 3.2 BookList类的实现(书架) 3.3 异常类的实现(OperationException) 3.4 用户类的实现 3.5 操作接口的实现(定义规范) 3.6 操作类的具体实现 3.6.1 增加操作 3.6.2 查找操作 3.6.3 删除操作 3.6…

标签打印机打印标签时出现,数据处理过程中错误 无法设置项目 图片1的内容无法打印

环境&#xff1a; Win10专业版 NiceLabel Designer 10.1 问题描述&#xff1a; 标签打印机打印标签时出现&#xff0c;数据处理过程中错误 无法设置项目 图片1的内容无法打印 解决方案&#xff1a; 1.删除标签部分文字打印测试 还是一样&#xff08;未解决&#xff09; …

jenkins 参数构建

应用保存 [rootjenkins-node1 .ssh]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved i…

【嵌入式面试】2022年嵌入式经典面试题汇总(C语言)

&#x1f4dc;作者&#xff1a;不想脱发的基兄 &#x1f4fa;专栏&#xff1a;《嵌入式面试》 &#x1f4e3;格言&#xff1a;不管前方的路有多苦&#xff0c;只要走的方向正确&#xff0c;不管多么崎岖不平&#xff0c;都比站在原地更接近幸福。 前言&#xff1a; 2022年秋招我…

C++之初始化列表详细剖析

一、初始化列表定义 初始化列表&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个"成员变量"后面跟一个放在括号中的初始值或表达式。 class Date { public:Date(int year, int month, int day): _year(year), _month(mont…