记一次SqlServer大表查询语句优化和执行计划分析
数据库: sqlserver2008r2
表: device_data
数据量:2000w行左右
表结构
CREATE TABLE [dbo].[device_data](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DeviceId] [nvarchar](30) NOT NULL,
[CollectCycle] [int] NOT NULL,
[BroadcastCycle] [int] NOT NULL,
[Behavior] [tinyint] NOT NULL,
[SystemTick] [int] NOT NULL,
[Sport] [int] NOT NULL,
[SportTime] [int] NOT NULL,
[SleepTime] [int] NOT NULL,
[Temperature] [int] NOT NULL,
[Voltage] [int] NOT NULL,
[DeviceSatatus] [int] NOT NULL,
[DeviceType] [int] NOT NULL,
[FireVersion] [int] NOT NULL,
[SportRange] [int] NOT NULL,
[UploadTime] [datetime] NOT NULL,
[DataFlag] [tinyint] NOT NULL,
[TagType] [tinyint] NOT NULL,
[RSSI] [tinyint] NOT NULL,
[CollectorMac] [nvarchar](20) NOT NULL,
CONSTRAINT [PK__device_d__3214EC0770FDBF69] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
索引情况:分别有两个联合索引
idx_deviceid(DeviceId,UploadTime)
idx_collector(CollectorMac,UploadTime)
问题:这张表上传的数据都是随上传时间递增,批量有序插入进去。但是 最近几天日志经常出现插入数据超时,然后去分析了一下数据库,发现对外接口出现了慢 sql导致了死锁,
慢sql是where条件在某些情况下没有加上时间筛选过滤,2000万的表导致非常慢,于是进行了优化,优化的时候变出现了下面的两条sql语句
这两个索引对应着两个接口 查询语句分别是:
select top 100 Id,DeviceId,Sport,Temperature,CollectorMac,UploadTime from device_data
where [DeviceId]='C9C810B18272' and UploadTime>'2020-12-01 15:16:55.000' order by UploadTime desc;
和
select top 100 Id,DeviceId,Sport,Temperature,CollectorMac,UploadTime from device_data
where [CollectorMac]='95DE5F0B' and UploadTime>'2020-12-01 15:16:55.000' order by UploadTime desc;
现在遇到一个情况是 相同的where条件下 如果我Order by Id Desc 就会发现返回结果中会比order by UploadTime desc慢一点,我一开始不太理解为啥会出现这个情况。
于是想到了sqlserver的查询分析器来分析一下具体的sql执行计划
1,首先我来执行order by UploadTime desc的语句来看一下具体的执行计划
dbcc dropcleanbuffers
set statistics io on
select top 100 Id,DeviceId,Sport,Temperature,CollectorMac,UploadTime from device_data
where [CollectorMac]='95DE5F0B' and UploadTime>'2020-12-01 15:16:55.000' order by UploadTime desc;
set statistics io off
具体执行计划为:
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。 (100 行受影响)
表 'device_data'。扫描计数 1,逻辑读取 1899 次,物理读取 5 次,预读 24 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (1 行受影响)

2,再来看一下order by Id desc的具体执行计划
dbcc dropcleanbuffers
set statistics io on
select top 100 Id,DeviceId,Sport,Temperature,CollectorMac,UploadTime from device_data
where [CollectorMac]='95DE5F0B' and UploadTime>'2020-12-01 15:16:55.000' order by Id desc;
set statistics io off
具体执行计划为:
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。 (100 行受影响)
表 'device_data'。扫描计数 1,逻辑读取 40 次,物理读取 36 次,预读 4942 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (1 行受影响)

这里先说一下逻辑读取和物理读取等区别
那么,这几个词语代表什么意思呢?我们怎么根据这些来了解SQL语句或者存储过程的I/O过程呢?
预读:用于估计信息,去硬盘读取数据到缓存。
物理读:查询计划生成以后,如果发现缓存缺少所需要的数据,让缓存再次去读硬盘数据。如果内存里没有缓存数据或者执行计划(如果SQL语句发生了改变,
那么执行计划将不能重用,需要重新生成新的执行计划),那么SQLSERVER就要去硬盘读取这些数据,这个时候就是物理读取,我们大家都知道,硬盘速度
与内存速度根本不在一个数量级上,所以物理读是比较慢的。
逻辑读:SQLSERVER去内存里的缓存取数据或者执行计划,所以逻辑读是比较快的。
SQLSERVER存储的最小单位是页,每一页大小为8K,即8*1024=8192字节,SQLSERVER对页的读取是原子性的,即要么读完一页,要么完全不读。即使
仅仅要获得一条数据,也要读完该页,而页之间的数据组织结构为B树结构。所以SQLSERVER对于逻辑读,物理读,预读的单位是页。
可以看到bytime 走的是索引查找和键查找 并且大部分读取走的是逻辑读取
byid 走的是聚集索引扫描,并且大部分读取走的是预读取
看上面的介绍我们发现 逻辑读取走的是内存缓存,预读取是去硬盘读取数据到缓存然后再逻辑读取,在这一步我们基本确定了 byid慢的原因是读取了硬盘数据。
那么上图出现的索引查找和索引扫描这两者又有什么区别呢
查看了相关资料发现
Clustered Index Scan(聚集索引扫描)、Index Scan(非聚集索引扫描)

聚集索引扫描:聚集索引的数据体积实际是就是表本身,也就是说表有多少行多少列,聚集所有就有多少行多少列,那么聚集索引扫描就跟表扫描差不多,也要进行全表扫描,遍历所有表数据,查找出你想要的数据。
非聚集索引扫描:非聚集索引的体积是根据你的索引创建情况而定的,可以只包含你要查询的列。那么进行非聚集索引扫描,便是你非聚集中包含的列的所有行进行遍历,查找出你想要的数据。
Clustered Index Seek(聚集索引查找)、Index Seek(非聚集索引查找)

聚集索引查找和非聚集索引查找都是使用该图标。
聚集索引查找:聚集索引包含整个表的数据,也就是在聚集索引的数据上根据键值取数据。
非聚集索引查找:非聚集索引包含创建索引时所包含列的数据,在这些非聚集索引的数据上根据键值取数据。
Key Lookup(键值查找)

首先需要说的是查找,查找与扫描在性能上完全不是一个级别的,扫描需要遍历整张表,而查找只需要通过键值直接提取数据,返回结果,性能要好。
当你查找的列没有完全被非聚集索引包含,就需要使用键值查找在聚集索引上查找非聚集索引不包含的列。
我们发现byid引起全量扫描了 所以会慢很多
疑问:我的理解是既然我已经加了where条件去筛选数据了 order by Id还是 order by Uploadtime 是不是应该在我where筛选出来的数据中再去排序,为啥只是因为Orderby的不同,最终的执行计划差别这么大
我对理论方面不深入,只能从现象来解决问题,还请大佬们赐教
参考资料:
T-SQL查询高级--理解SQL SERVER中非聚集索引的覆盖,连接,交叉和过滤
MSSQLSERVER执行计划详解
记一次SqlServer大表查询语句优化和执行计划分析的更多相关文章
- MySQL 表查询语句练习题
MySQL 表查询语句练习题: 一. 设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表 ...
- sql查询语句优化
http://www.cnblogs.com/dubing/archive/2011/12/09/2278090.html 最近公司来一个非常虎的dba 10几年的经验 这里就称之为蔡老师吧 在征得 ...
- 转载《mysql 一》:mysql的select查询语句内在逻辑执行顺序
原文:http://www.jellythink.com/archives/924 我的抱怨 我一个搞应用开发的,非要会数据库,这不是专门的数据库开发人员干的事么?话说,小公司也没有数 据库开发人员这 ...
- mysql数据库系统学习(一)---一条SQL查询语句是如何执行的?
本文基于----MySQL实战45讲(极客时间----林晓斌 )整理----->https://time.geekbang.org/column/article/68319 一.第一节:一条sq ...
- php面试专题---MYSQL查询语句优化
php面试专题---MYSQL查询语句优化 一.总结 一句话总结: mysql的性能优化包罗甚广: 索引优化,查询优化,查询缓存,服务器设置优化,操作系统和硬件优化,应用层面优化(web服务器,缓存) ...
- 一文读懂一条 SQL 查询语句是如何执行的
2001 年 MySQL 发布 3.23 版本,自此便开始获得广泛应用,随着不断地升级迭代,至今 MySQL 已经走过了 20 个年头. 为了充分发挥 MySQL 的性能并顺利地使用,就必须正确理解其 ...
- 当程序执行一条查询语句时,MySQL内部到底发生了什么? (说一下 MySQL 执行一条查询语句的内部执行过程?
先来个最基本的总结阐述,希望各位小伙伴认真的读一下,哈哈: 1)客户端(运行程序)先通过连接器连接到MySql服务器. 2)连接器通过数据库权限身份验证后,会先查询数据库缓存是否存在(之前执行过相同条 ...
- SQLServer查询执行计划分析 - 案例
SQLServer查询执行计划分析 - 案例 http://pan.baidu.com/s/1pJ0gLjP 包括学习笔记.书.样例库
- mysql大表设计以及优化
MYSQL千万级数据量的优化方法积累https://m.toutiao.com/group/6583260372269007374/?iid=6583260372269007374 MySQL 千万级 ...
随机推荐
- CSS初识- 选择器 &背景& 浮动& 盒子模型
# CSS初识-目标: > 1. 学会使用CSS选择器 > 2. 熟记CSS样式和外观属性 > 3. 熟练掌握CSS各种基础选择器 > 4. 熟练掌握CSS各种复合选择器 &g ...
- 科大讯飞语音合成系统 V5.0绿色便携版
中文名: 中科大讯飞Interphonic 5.0语音合成系统英文名: Interphonic 5.0版本: 5.0发行时间: 2006年制作发行: 中科大讯飞语言: 简体中文系统简介InterPho ...
- Nginx 转发时的一个坑,运维居然让我背锅!!
最近遇到一个 Nginx 转发的坑,一个请求转发到 Tomcat 时发现有几个 http header 始终获取不到,导致线上出现 bug,运维说不是他的问题,这个锅我背了. 新增的几个 header ...
- JavaScript一个一维数组变为两个一维数组
//例如[1,2,3,4,5,6,7,8]变为[[1,2,3,4],[5,6,7,8]] var arr=[1,2,3,4,5,6,7,8]; function fixedArray(arr) { v ...
- 题解-NOI2003 智破连环阵
题面 NOI2003 智破连环阵 有 \(m\) 个靶子 \((ax_j,ay_j)\) 和 \(n\) 个箭塔 \((bx_i,by_i)\).每个箭塔可以射中距离在 \(k\) 以内的靶子.第 \ ...
- JavaSE07-字符串常用API
1.String 1.1 String类概述 String 类代表字符串,Java 程序中的所有字符串文字(例如"abc")都被实现为此类的实例.也就是说,Java 程序 中所有的 ...
- 初阶项目一-集成一套linux系统:红帽系统,LVM分区,Apache服务,MySQL服务,数据定时备份脚本
目录 一.项目目标 二.实施工具 三.项目实施计划 四.安装rhel7.5操作系统 4.1 配置虚拟机 4.2 安装操作系统 4.3 系统配置 4.3.1 网络配置 4.3.2 修改主机名 4.3.3 ...
- vue seo 优化
预渲染prerender-spa-plugin 如果你只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染.无需使用 web 服务器实时动态编译 ...
- SpringDataJPA 多对多的查询
主要的结构目录: 创建Role.java package cn.itcast.domain; import javax.persistence.*; import java.util.HashSet ...
- 一目了然的 Node.js Windows10 安装篇
本篇文章 介绍 NodeJS 的安装 及环境变量配置 Node JS 的 了解 1.Node.js简介 简单的说 Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于 ...