詳解SQL Server的簡(jiǎn)單查詢(xún)語(yǔ)句
前言
對(duì)于一些原理性文章園中已有大量的文章尤其是關(guān)于索引這一塊,我也是花費(fèi)大量時(shí)間去學(xué)習(xí),對(duì)于了解索引原理對(duì)于后續(xù)理解查詢(xún)計(jì)劃和性能調(diào)優(yōu)有很大的幫助,而我們只是一些內(nèi)容進(jìn)行概括和總結(jié),這一節(jié)我們開(kāi)始正式步入學(xué)習(xí)SQL中簡(jiǎn)單的查詢(xún)語(yǔ)句,簡(jiǎn)短的內(nèi)容,深入的理解。
簡(jiǎn)單查詢(xún)語(yǔ)句
所有復(fù)雜的語(yǔ)句都是由簡(jiǎn)單的語(yǔ)句組成基本都是由SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY等組成,當(dāng)然還包括一些謂詞等等。比如當(dāng)我們要查詢(xún)某表中所有數(shù)據(jù)時(shí)我們會(huì)像如下進(jìn)行。
SELECT * FROM TABLE
到這里是不是查詢(xún)就是從SELECT開(kāi)始呢?我們應(yīng)該從實(shí)際生活舉例,如我們需要到菜市場(chǎng)買(mǎi)菜,我們想買(mǎi)芹菜,我們應(yīng)該是到有芹菜的攤位上去買(mǎi),也就是從哪里去買(mǎi),到這里我們會(huì)發(fā)現(xiàn)上述查詢(xún)數(shù)據(jù)的順序應(yīng)該是先FROM然后是SELECT。在SQL 2012基礎(chǔ)教程中列出子句是按照以下順序進(jìn)行邏輯處理。
FROM WHERE GROUP BY HAVING SELECT ORDER BY
比如我們要查詢(xún)篩選客戶(hù)71下的訂單,我們會(huì)進(jìn)行如下查詢(xún)。
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
但是實(shí)際上按照我們上述所說(shuō)的順序,其邏輯化的子句是這樣的。
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
對(duì)于博主的SQL系列并非會(huì)將SELECT、HAVING等語(yǔ)句單獨(dú)拿來(lái)講,針對(duì)的是有了一定基礎(chǔ)的人群,后續(xù)內(nèi)容也是如此,所以到了這里我們算是將簡(jiǎn)單查詢(xún)語(yǔ)句敘述完畢。但是我一直強(qiáng)調(diào)的是簡(jiǎn)短的內(nèi)容,深入的理解,所以接下來(lái)看看有些需要注意的地方。
我們看到過(guò)很多文章一直在講SQL性能問(wèn)題,比如在查詢(xún)所有數(shù)據(jù)時(shí)要列出所有列而非SELECT *,所以在本系列中,我也會(huì)在適當(dāng)?shù)娜ブv性能問(wèn)題,比如本節(jié)要講的SELECT 1和SELECT *的性能問(wèn)題。
SELECT 1和SELECT *性能探討
在數(shù)據(jù)庫(kù)中查看執(zhí)行計(jì)劃時(shí)我們通常會(huì)點(diǎn)擊【顯示估計(jì)的執(zhí)行計(jì)劃】快捷鍵是Ctrl+L,這里我們可以看到它已經(jīng)表明顯示的只是估計(jì)的執(zhí)行計(jì)劃,所以是不準(zhǔn)確的,所以為了顯示實(shí)際的執(zhí)行計(jì)劃,我們應(yīng)該啟動(dòng)【包括實(shí)際的執(zhí)行計(jì)劃】,快捷鍵是Ctrl+M,這樣才能得到比較準(zhǔn)確的執(zhí)行計(jì)劃,如下

查詢(xún)方式一(整表查詢(xún))
USE TSQL2012 GO IF EXISTS( SELECT 1 FROM Sales.Orders) SELECT 'SELECT 1' GO IF EXISTS( SELECT * FROM Sales.Orders) SELECT 'SELECT *' GO
此時(shí)查看執(zhí)行計(jì)劃是相同的,如下:

查詢(xún)方式二(在索引列上條件查找)
我們對(duì)某一列創(chuàng)建索引
CREATE INDEX ix_shipname ON Sales.Orders(shipname)
接下來(lái)繼續(xù)查看其執(zhí)行計(jì)劃。

此時(shí)顯示查詢(xún)計(jì)劃依然一樣。我們?cè)賮?lái)看看其他查詢(xún)方式。
查詢(xún)方式三(使用聚合函數(shù))
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
我們看到查詢(xún)計(jì)劃依然一樣。

查詢(xún)方式四(使用聚合函數(shù)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
我們看到執(zhí)行計(jì)劃還是一樣。

查詢(xún)方式五(子查詢(xún))
我們看看在子查詢(xún)中二者性能如何
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)
此時(shí)結(jié)果二者查看執(zhí)行計(jì)劃還是一樣

查詢(xún)方式六(在視圖中查詢(xún))
我們創(chuàng)建視圖繼續(xù)來(lái)比較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
進(jìn)行視圖查詢(xún)
USE TSQL2012 SELECT 1 FROM dbo.SaleOdersView go SELECT * FROM dbo.SaleOdersView go
結(jié)果執(zhí)行計(jì)劃如下:

此時(shí)我們通過(guò)上述圖發(fā)現(xiàn)利用視圖查詢(xún)時(shí),SELECT *的性能是如此低下占有97%,而SELECT 1才3%,這是為何呢?不明白其中原因,希望有清楚其中原因的園友能夠留下你們的評(píng)論給出合理的解釋。
SELECT 所有列和SELECT *性能探討
一直以來(lái)所有教程都在講SELECT *性能比SELECT 所有列性能低,同時(shí)也給出了合理的理由,我也一直這樣認(rèn)為,但是在查資料學(xué)習(xí)過(guò)程中,發(fā)現(xiàn)如下一段話(huà)。
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 *使用的唯一場(chǎng)景是在EXISTS中,看到這里顛覆我以往看的教程的想法,不太明確,真的是這樣嗎?
總結(jié)
通過(guò)以上對(duì)SELECT 1和SELECT *性能的探討,在視圖中利用SELECT *性能更加低下,同時(shí)也結(jié)合SELECT *盡量避免用,我是不是可以下結(jié)論我可以更傾向于用SELECT 1呢?第二點(diǎn)是看到上述所給的資料SELECT *在Exist中的性能是不是和一定SELECT 所有列一樣呢?這是我存在疑問(wèn)的兩個(gè)問(wèn)題,是不是我所疑問(wèn)的兩個(gè)問(wèn)題,沒(méi)有具體的答案,需要看應(yīng)用場(chǎng)景呢?那應(yīng)用場(chǎng)景又是在哪里?畢竟不是專(zhuān)業(yè)的DBA,同時(shí)對(duì)SQL也研究不深,所以希望看到此文的讀者,能給出精彩的回答,同時(shí)也讓我學(xué)習(xí)學(xué)習(xí)。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,同時(shí)也希望多多支持腳本之家!
- SQL Server Table中XML列的操作代碼
- SQLSERVER查詢(xún)所有數(shù)據(jù)庫(kù)名,表名,和字段名的語(yǔ)句
- SQL Server SQL高級(jí)查詢(xún)語(yǔ)句小結(jié)
- SQLServer中用T—SQL命令查詢(xún)一個(gè)數(shù)據(jù)庫(kù)中有哪些表的sql語(yǔ)句
- SQL語(yǔ)句實(shí)現(xiàn)查詢(xún)SQL Server服務(wù)器名稱(chēng)和IP地址
- 關(guān)于SQL Server查詢(xún)語(yǔ)句的使用
- SqlServer 基礎(chǔ)知識(shí) 數(shù)據(jù)檢索、查詢(xún)排序語(yǔ)句
- SQL Server中Table字典數(shù)據(jù)的查詢(xún)SQL示例代碼
相關(guān)文章
ASP.NET下向SQLServer2008導(dǎo)入文件實(shí)例操作方法
在Microsoft SQL Server2008以后的版本中,將刪除image數(shù)據(jù)類(lèi)型。在新的開(kāi)發(fā)工作中將不適用此數(shù)據(jù)類(lèi)型,并打算修改當(dāng)前使用此數(shù)據(jù)類(lèi)型的應(yīng)用程序,改用varbinary(max)數(shù)據(jù)類(lèi)型。2010-09-09
SQL Server 2012 FileTable 新特性詳解
FileTable是基于FILESTREAM的一個(gè)特性。本文給大家介紹SQL Server 2012 FileTable 新特性詳解,非常不錯(cuò),感興趣的朋友一起學(xué)習(xí)吧2016-08-08
一些文件未注冊(cè)導(dǎo)致mssql表文件無(wú)法找開(kāi)的解決方法
只需要按下面的步驟注冊(cè)一些文件,即可。2009-09-09
關(guān)于 SQL Server ErrorLog 錯(cuò)誤日志說(shuō)明
關(guān)于 SQL Server ErrorLog 錯(cuò)誤日志說(shuō)明學(xué)習(xí)sqlserver的朋友可以參考下。2011-04-04
jdbc使用PreparedStatement批量插入數(shù)據(jù)的方法
這篇文章主要介紹了jdbc使用PreparedStatement批量插入數(shù)據(jù)的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
CREATE FUNCTION sqlserver用戶(hù)定義函數(shù)
創(chuàng)建用戶(hù)定義函數(shù),它是返回值的已保存的 Transact-SQL 例程。用戶(hù)定義函數(shù)不能用于執(zhí)行一組修改全局?jǐn)?shù)據(jù)庫(kù)狀態(tài)的操作。與系統(tǒng)函數(shù)一樣,用戶(hù)定義函數(shù)可以從查詢(xún)中喚醒調(diào)用。也可以像存儲(chǔ)過(guò)程一樣,通過(guò) EXECUTE 語(yǔ)句執(zhí)行2012-07-07
sqlserver連接錯(cuò)誤之SQL評(píng)估期已過(guò)的問(wèn)題解決
很久沒(méi)用sqlserver了,現(xiàn)在出現(xiàn)評(píng)估期已過(guò)的問(wèn)題,本文就介紹一下sqlserver連接錯(cuò)誤之SQL評(píng)估期已過(guò)的問(wèn)題解決,文中根據(jù)圖文詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Transactional replication(事務(wù)復(fù)制)詳解之如何跳過(guò)一個(gè)事務(wù)
事務(wù)復(fù)制由 SQL Server 快照代理、日志讀取器代理和分發(fā)代理實(shí)現(xiàn)。 快照代理準(zhǔn)備快照文件(其中包含了已發(fā)布表和數(shù)據(jù)庫(kù)對(duì)象的架構(gòu)和數(shù)據(jù)),然后將這些文件存儲(chǔ)在快照文件夾中,并在分發(fā)服務(wù)器中的分發(fā)數(shù)據(jù)庫(kù)中記錄同步作業(yè)。2014-08-08

