简单查询语句(三)

前言

对于一些原理性文章园中已有大量的文章尤其是关于索引这一块,我也是花费大量时间去学习,对于了解索引原理对于后续理解查询计划和性能调优有很大的帮助,而我们只是一些内容进行概括和总结,这一节我们开始正式步入学习SQL中简单的查询语句,简短的内容,深入的理解。

简单查询语句

所有复杂的语句都是由简单的语句组成基本都是由SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY等组成,当然还包括一些谓词等等。比如当我们要查询某表中所有数据时我们会像如下进行。

SELECT * FROM TABLE

到这里是不是查询就是从SELECT开始呢?我们应该从实际生活举例,如我们需要到菜市场买菜,我们想买芹菜,我们应该是到有芹菜的摊位上去买,也就是从哪里去买,到这里我们会发现上述查询数据的顺序应该是先FROM然后是SELECT。在SQL 2012基础教程中列出子句是按照以下顺序进行逻辑处理。

1    FROM
2    WHERE
3    GROUP BY
4    HAVING
5    SELECT
6    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也研究不深,所以希望看到此文的读者,能给出精彩的回答,同时也让我学习学习。

时间: 2024-12-25 23:25:41

简单查询语句(三)的相关文章

T-SQL简单查询语句(模糊查询)

1 T-SQL简单查询语句 2 3 简单查询: 4 5 1.最简单查询(查所有数据) 6 select * from 表名: 注:* 代表所有列 7 select * from info 8 9 2.查询指定列 10 select code,name from info 11 12 3.修改结果集的列名 13 select code as '代号',name as '姓名' from info 14 15 4.条件查询 16 select * from info where code='p003

oracle中简单查询语句的格式及执行顺序分析

一条简单的查询sql格式如下: SELECT ... FROM .... [WHERE ...] --过滤单行 [GROUP BY ...   [HAVING ...]]--GROUP BY对前面where条件过滤后的结果进行分组,HAVING过滤行组 [ORDER BY ...]--对结果进行排序 eg: 现在有个exchangetime表,表结构如下 名称                                            是否为空? 类型 ----------------

MySQL简单查询语句练习

数据查询语法(DQL) DQL就是数据查询语言,数据库执行DQL语句不会对数据进行改变,而是让数据库发送结果集给客户端. 语法: SELECT selection_list /*要查询的列名称*/ FROM table_list /*要查询的表名称*/ WHERE condition /*行条件*/ GROUP BY grouping_columns /*对结果分组*/ HAVING condition /*分组后的行条件*/ ORDER BY sorting_columns /*对结果分组*/

MongoDB简单查询语句

左边是mongodb查询语句,右边是sql语句.对照着用,挺方便. db.users.find() select * from users db.users.find({"age" : 27}) select * from users where age = 27 db.users.find({"username" : "joe", "age" : 27}) select * from users where "us

nodejs Sequelize 简单查询语句和 mysql常用的几个查询命令

我是前端,但总有需求让做后端的活,所以顺带着熟悉了下简单的查询语句 贴出来,如果有需要可以参考下,备注很详细,就不多解释了废话不多说贴代码: #去除unionid 重复的搜索结果 #query_resultsign 表名 select *, count(unionid) from query_resultsign where issign='false' group by unionid ; #去除unionid 重复的搜索结果 #query_resultsign 表名 select *, co

T-SQL 的简单查询语句

通配符: “_”: 代表匹配一个字符 “%”: 代表匹配多个字符: []:表示范围,可以包含多个数据 [^] 表示取反 “-“  表示范围 逻辑与 and 逻辑或 or  逻辑非 not 聚会函数 : 聚合函数:sum()/max()/min()/avg()/count() where /group by /having -----------删除数据------------------------------ delete:有选择性的删除 删除的信息不能被子表所有使用 truncate:删除整

MySQL表的几个简单查询语句

1. 创建数据库CREATE DATABASE database-name 2. 删除数据库drop database dbname 3.    创建新表create table tabname(col1 type1 [not null] [primary key],col2 type2 [not   null],..) 根据已有的表创建新表: A:create table tab_new like tab_old (使用旧表创建新表) B:create table tab_new as sel

简单查询语句

范例1:查询emp表中的数据 SELECT * FROM emp ;   范例2:现在要求查询出公司的雇员雇佣情况,所以希望通过数据库可以查找到每个雇员的编号.姓名.基本工资三个信息进行浏览 SELECT empno,ename,job FROM emp ;   范例3:现在要求查询公司中所有雇员的职位信息 SELECT job FROM emp ; 范例4:显示的职位包含了太多的重复内容,使用了DISTINCT关键字去掉全部的重复显示内容 SELECT DISTINCT job FROM em

MySQL的简单查询语句

查询:一:查询所有数据select * from Info 查所有数据select Code,Name from Info 查特定列 二:根据条件查select * from Info where Code='p001' 一个条件查询select * from Info where Code='p001' and Nation='n001' 多条件 并关系 查询select * from Info where Name='胡军' or Nation='n001' 多条件 或关系 查询select