这里有新鲜出炉的SQL Server教程,程序狗速度看过来!
SQL是英文Structured Query Language的缩写,意思为结构化查询语言。SQL语言的主要功能就是同各种数据库建立联系,进行沟通。按照ANSI(美国国家标准协会)的规定,SQL被作为关系型数据库管理系统的标准语言。
SQL Server 即 Microsoft SQL Server 。
本篇文章详细讲解了SQL ServerSQL的简单查询语句。图文并茂,方便大家理解与学习。有兴趣的朋友可以看下
前言
对于一些原理性文章园中已有大量的文章尤其是关于索引这一块,我也是花费大量时间去学习,对于了解索引原理对于后续理解查询计划和性能调优有很大的帮助,而我们只是一些内容进行概括和总结,这一节我们开始正式步入学习SQL中简单的查询语句,简短的内容,深入的理解。
简单查询语句
所有复杂的语句都是由简单的语句组成基本都是由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 = '71'
- GROUP BY empid, YEAR(orderdate)
- HAVING COUNT(*) > 1
- ORDER BY empid, orderyear
但是实际上按照我们上述所说的顺序,其逻辑化的子句是这样的。
- FROM Sales.Orders
- WHERE custid = 71
- GROUP BY empid, YEAR(orderdate)
- HAVING COUNT(*) > 1
- 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 1
- 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 1
- FROM Sales.Orders
- WHERE shipname = 'Ship to 85-B') = 1
- SELECT 'SELECT 1'
- GO
- IF (
- SELECT COUNT(*)
- FROM Sales.Orders
- WHERE shipname = 'Ship to 85-B') = 1
- SELECT 'SELECT *'
- GO
我们看到查询计划依然一样。
查询方式四(使用聚合函数Count在非索引列上查找)
- USE TSQL2012
- GO
- IF (
- SELECT COUNT(1)
- FROM Sales.Orders
- WHERE freight = '41.3400') = 1
- SELECT 'SELECT 1'
- GO
- IF (
- SELECT COUNT(*)
- FROM Sales.Orders
- WHERE freight = '41.3400') = 1
- 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 1 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 1 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 1/* 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也研究不深,所以希望看到此文的读者,能给出精彩的回答,同时也让我学习学习。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,同时也希望多多支持PHPERZ!
来源: http://www.phperz.com/article/17/0907/339209.html