SQL Server-简单查询语句,疑惑篇(三)
前言
对于一些原理性文章园中已有大量的文章尤其是关于索引这一块,我也是花费大量时间去学习,对于了解索引原理对于后续理解查询计划和性能调优有很大的帮助,而我们只是一些内容进行概括和总结,这一节我们开始正式步入学习SQL中简单的查询语句,简短的内容,深入的理解,Always to review the basics。
简单查询语句
所有复杂的语句都是由简单的语句组成基本都是由SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY等组成,当然还包括一些谓词等等。比如当我们要查询某表中所有数据时我们会像如下进行。
SELECT * FROM TABLE
到这里是不是查询就是从SELECT开始呢?我们应该从实际生活举例,如我们需要到菜市场买菜,我们想买芹菜,我们应该是到有芹菜的摊位上去买,也就是从哪里去买,到这里我们会发现上述查询数据的顺序应该是先FROM然后是SELECT。在SQL 2012基础教程中列出子句是按照以下顺序进行逻辑处理。
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
比如我们要查询筛选客户71下的订单,我们会进行如下查询。
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numbers
FROM Sales.Orders
WHERE custid = ''
GROUP BY empid, YEAR(orderdate)
HAVING COUNT(*) >
ORDER BY empid, orderyear
但是实际上按照我们上述所说的顺序,其逻辑化的子句是这样的。
FROM Sales.Orders
WHERE custid =
GROUP BY empid, YEAR(orderdate)
HAVING COUNT(*) >
SELECT empid, YEAR(orderdate) AS orderyear, COUNT(*) AS numberorders
ORDER BY empid, orderyear
对于博主的SQL系列并非会将SELECT、HAVING等语句单独拿来讲,针对的是有了一定基础的人群,后续内容也是如此,所以到了这里我们算是将简单查询语句叙述完毕。但是我一直强调的是简短的内容,深入的理解,所以接下来看看有些需要注意的地方。
我们看到过很多文章一直在讲SQL性能问题,比如在查询所有数据时要列出所有列而非SELECT *,所以在本系列中,我也会在适当的去讲性能问题,比如本节要讲的SELECT 1和SELECT *的性能问题。
SELECT 1和SELECT *性能探讨
在数据库中查看执行计划时我们通常会点击【显示估计的执行计划】快捷键是Ctrl+L,这里我们可以看到它已经表明显示的只是估计的执行计划,所以是不准确的,所以为了显示实际的执行计划,我们应该启动【包括实际的执行计划】,快捷键是Ctrl+M,这样才能得到比较准确的执行计划,如下

查询方式一(整表查询)
USE TSQL2012
GO
IF EXISTS(
SELECT
FROM Sales.Orders)
SELECT 'SELECT 1'
GO
IF EXISTS(
SELECT *
FROM Sales.Orders)
SELECT 'SELECT *'
GO
此时查看执行计划是相同的,如下:

查询方式二(在索引列上条件查找)
我们对某一列创建索引
CREATE INDEX ix_shipname
ON Sales.Orders(shipname)
接下来继续查看其执行计划。

此时显示查询计划依然一样。我们再来看看其他查询方式。
查询方式三(使用聚合函数)
USE TSQL2012
GO
IF (
SELECT
FROM Sales.Orders
WHERE shipname = 'Ship to 85-B') =
SELECT 'SELECT 1'
GO
IF (
SELECT COUNT(*)
FROM Sales.Orders
WHERE shipname = 'Ship to 85-B') =
SELECT 'SELECT *'
GO
我们看到查询计划依然一样。

查询方式四(使用聚合函数Count在非索引列上查找)
USE TSQL2012
GO
IF (
SELECT COUNT()
FROM Sales.Orders
WHERE freight = '41.3400') =
SELECT 'SELECT 1'
GO
IF (
SELECT COUNT(*)
FROM Sales.Orders
WHERE freight = '41.3400') =
SELECT 'SELECT *'
GO
我们看到执行计划还是一样。

查询方式五(子查询)
我们看看在子查询中二者性能如何
USE TSQL2012
SELECT custid, companyname FROM Sales.Customers AS C
WHERE country = N'USA' AND
EXISTS (SELECT * FROM Sales.Orders AS O WHERE O.custid = C.custid)
GO SELECT custid, companyname FROM Sales.Customers AS C
WHERE country = N'USA' AND
EXISTS (SELECT FROM Sales.Orders AS O WHERE O.custid = C.custid)
此时结果二者查看执行计划还是一样

查询方式六(在视图中查询)
我们创建视图继续来比较SELECT 1和SELECT *的性能
USE TSQL2012
Go
CREATE VIEW SaleOdersView
AS SELECT shipaddress,shipname,(SELECT unitprice FROM Sales.OrderDetails AS sod where sod.orderid = so.orderid) as tc3
FROM Sales.Orders AS so GO
进行视图查询
USE TSQL2012
SELECT FROM dbo.SaleOdersView
go
SELECT * FROM dbo.SaleOdersView
go
结果执行计划如下:

此时我们通过上述图发现利用视图查询时,SELECT *的性能是如此低下占有97%,而SELECT 1才3%,这是为何呢?不明白其中原因,希望有清楚其中原因的园友能够留下你们的评论给出合理的解释。
SELECT 所有列和SELECT *性能探讨
一直以来所有教程都在讲SELECT *性能比SELECT 所有列性能低,同时也给出了合理的理由,我也一直这样认为,但是在查资料学习过程中,发现如下一段话。
I don’t think there is any difference, as long as the SELECT /* is inside EXISTS, which really doesn’t return any rows – it just returns boolean as soon as condition of the WHERE is checked. I’m quite sure that the SQL Server Query Optimizer is smart enough not to search for the unneeded meta data in the case of EXISTS. I agree that in all the other situations SELECT * shouldn’t be used for the reasons Simon mentioned. Also, index usage wouldn’t be optimal etc. For me EXISTS (SELECT * ..) is the only place where I allow myself to write SELECT * in production code ;)
最后一句表明SELECT *使用的唯一场景是在EXISTS中,看到这里颠覆我以往看的教程的想法,不太明确,真的是这样吗?
总结
通过以上对SELECT 1和SELECT *性能的探讨,在视图中利用SELECT *性能更加低下,同时也结合SELECT *尽量避免用,我是不是可以下结论我可以更倾向于用SELECT 1呢?第二点是看到上述所给的资料SELECT *在Exist中的性能是不是和一定SELECT 所有列一样呢?这是我存在疑问的两个问题,是不是我所疑问的两个问题,没有具体的答案,需要看应用场景呢?那应用场景又是在哪里?毕竟不是专业的DBA,同时对SQL也研究不深,所以希望看到此文的读者,能给出精彩的回答,同时也让我学习学习。
SQL Server-简单查询语句,疑惑篇(三)的更多相关文章
- Sql Server 简单查询 异步服务器更新语句
//结构:select 子句 [into 子句] from 子句 [where 子句] [group by 子句] [having 子句] [order by 子句] select dept_c ...
- sql server 2008 查询语句的红色波浪线
在 Microsoft sql server management studio 里点击“编辑”——“IntelliSense”——“刷新本地缓存” 就会发现红色波浪线没了(前提是你的代码没错)
- Sql Server中查询当天,最近三天,本周,本月,最近一个月,本季度的数据的sql语句
--当天: --最近三天: --本周: select * from T_news WHERE (DATEPART(wk, addtime) = DATEPART(wk, GETDATE())) AND ...
- Sql server统计查询语句消耗时间
1. set statistics time on go xxxx go set statistics time off 2. DECLARE @begin dateTime DECLARE @en ...
- SQL Server调优系列进阶篇(查询语句运行几个指标值监测)
前言 上一篇我们分析了查询优化器的工作方式,其中包括:查询优化器的详细运行步骤.筛选条件分析.索引项优化等信息. 本篇我们分析在我们运行的过程中几个关键指标值的检测. 通过这些指标值来分析语句的运行问 ...
- SQL Server-简单查询语句,疑惑篇
前言 对于一些原理性文章园中已有大量的文章尤其是关于索引这一块,我也是花费大量时间去学习,对于了解索引原理对于后续理解查询计划和性能调优有很大的帮助,而我们只是一些内容进行概括和总结,这一节我们开 ...
- SQL Server调优系列基础篇(常用运算符总结——三种物理连接方式剖析)
前言 上一篇我们介绍了如何查看查询计划,本篇将介绍在我们查看的查询计划时的分析技巧,以及几种我们常用的运算符优化技巧,同样侧重基础知识的掌握. 通过本篇可以了解我们平常所写的T-SQL语句,在SQL ...
- SQL Server调优系列基础篇(子查询运算总结)
前言 前面我们的几篇文章介绍了一系列关于运算符的介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符.有兴 ...
- SQL Server调优系列基础篇 - 子查询运算总结
前言 前面我们的几篇文章介绍了一系列关于运算符的介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符.有兴 ...
随机推荐
- 一起学微软Power BI系列-使用技巧(5)自定义PowerBI时间日期表
1.日期函数表作用 经常使用Excel或者PowerBI,Power Pivot做报表,时间日期是一个重要的纬度,加上做一些钻取,时间日期函数表不可避免.所以今天就给大家分享一个自定义的做日期表的方法 ...
- iOS开发系列--打造自己的“美图秀秀”
--绘图与滤镜全面解析 概述 在iOS中可以很容易的开发出绚丽的界面效果,一方面得益于成功系统的设计,另一方面得益于它强大的开发框架.今天我们将围绕iOS中两大图形.图像绘图框架进行介绍:Quartz ...
- mac osx 安装redis扩展
1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...
- 【初学python】使用python连接mysql数据查询结果并显示
因为测试工作经常需要与后台数据库进行数据比较和统计,所以采用python编写连接数据库脚本方便测试,提高工作效率,脚本如下(python连接mysql需要引入第三方库MySQLdb,百度下载安装) # ...
- ASP.NET Core 1.0 使用 Dapper 操作 MySql(包含事务)
操作 MySql 数据库使用MySql.Data程序包(MySql 开发,其他第三方可能会有些问题). project.json 代码: { "version": "1. ...
- PHP之GD函数的使用
本文讲解常用GD函数的应用 1.一个简单的图像 我们先看一个例子: <?php $w = 200; $h = 200; $img = imagecreatetruecolor($w,$h); $ ...
- Go web开发初探
2017年的第一篇博客,也是第一次写博客,写的不好,请各位见谅. 本人之前一直学习java.java web,最近开始学习Go语言,所以也想了解一下Go语言中web的开发方式以及运行机制. 在< ...
- JS继承之借用构造函数继承和组合继承
根据少一点套路,多一点真诚这个原则,继续学习. 借用构造函数继承 在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数(constructor stealing)的技术( ...
- 玩转spring boot——开篇
很久没写博客了,而这一转眼就是7年.这段时间并不是我没学习东西,而是园友们的技术提高的非常快,这反而让我不知道该写些什么.我做程序已经有十几年之久了,可以说是彻彻底底的“程序老炮”,至于技术怎么样?我 ...
- $ORACLE_HOME变量值末尾多“/”惹的祸
之前一直误以为$ORACLE_HOME变量的路径中末尾多写一个"/"不会有影响. 今天做实验时碰到一个情景,发现并不是这样. 环境:OEL 5.7 + Oracle 10.2.0. ...