首頁 資料庫 mysql教程 MSSQL优化之探索MSSQL执行计划(转)

MSSQL优化之探索MSSQL执行计划(转)

Jun 07, 2016 pm 06:03 PM
mssql 執行計劃

最近总想整理下对MSSQL的一些理解与感悟,却一直没有心思和时间写,晚上无事便写了一篇探索MSSQL执行计划,本文讲执行计划但不仅限于讲执行计划

网上的SQL优化的文章实在是很多,说实在的,我也曾经到处找这样的文章,什么不要使用IN了,什么OR了,什么AND了,很多很多,还有很多人拿出仅几S甚至几MS的时间差的例子来证明着什么(有点可笑),让许多人不知道其是对还是错。而SQL优化又是每个要与数据库打交道的程序员的必修课,所以写了此文,与朋友们共勉。
谈到优化就必然要涉及索引,就像要讲锁必然要说事务一样,所以你需要了解一下索引,仅仅是索引,就能讲半天了,所以索引我就不说了(打很多字是很累的,况且我也知之甚少),可以去参考相关的文章,这个网上资料比较多了。
今天来探索下MSSQL的执行计划,来让大家知道如何查看MSSQL的优化机制,以此来优化SQL查询。
代码如下:
--DROP TABLE T_UserInfo----------------------------------------------------
--建测试表
CREATE TABLE T_UserInfo
(
Userid varchar(20), UserName varchar(20),
RegTime datetime, Tel varchar(20),
)
--插入测试数据
DECLARE @I INT
DECLARE @ENDID INT
SELECT @I = 1
SELECT @ENDID = 100 --在此处更改要插入的数据,重新插入之前要删掉所有数据
WHILE @I BEGIN
INSERT INTO T_UserInfo
SELECT 'ABCDE'+CAST(@I AS VARCHAR(20))+'EF','李'+CAST(@I AS VARCHAR(20)),
GETDATE(),'876543'+CAST(@I AS VARCHAR(20))
SELECT @I = @I + 1
END

--相关SQL语句解释
---------------------------------------------------------------------------
--建聚集索引
CREATE CLUSTERED INDEX INDEX_Userid ON T_UserInfo (Userid)
--建非聚集索引
CREATE NONCLUSTERED INDEX INDEX_Userid ON T_UserInfo (Userid)
--删除索引
DROP INDEX T_UserInfo.INDEX_Userid
---------------------------------------------------------------------------
---------------------------------------------------------------------------
--显示有关由Transact-SQL 语句生成的磁盘活动量的信息
SET STATISTICS IO ON
--关闭有关由Transact-SQL 语句生成的磁盘活动量的信息
SET STATISTICS IO OFF
--显示[返回有关语句执行情况的详细信息,并估计语句对资源的需求]
SET SHOWPLAN_ALL ON
--关闭[返回有关语句执行情况的详细信息,并估计语句对资源的需求]
SET SHOWPLAN_ALL OFF
---------------------------------------------------------------------------
请记住:SET STATISTICS IO 和 SET SHOWPLAN_ALL 是互斥的。
OK,现在开始:
首先,我们插入100条数据
然后我写了一个查询语句:
SELECT * FROM T_UserInfo WHERE USERID='ABCDE6EF'
选中以上语句,按Ctrl+L,如下图
这就是MSSQL的执行计划:表扫描:扫描表中的行
然后我们来看该语句对IO的读写:
执行:SET STATISTICS IO ON
此时再执行该SQL:SELECT * FROM T_UserInfo WHERE USERID='ABCDE6EF'
切换到消失栏显示如下:
表'T_UserInfo'。扫描计数1,逻辑读1 次,物理读0 次,预读0 次。
解释下其意思:
四个值分别为:
执行的扫描次数;
从数据缓存读取的页数;
从磁盘读取的页数;
为进行查询而放入缓存的页数
重要:如果对于一个SQL查询有多种写法,那么这四个值中的逻辑读(logical reads)决定了哪个是最优化的。

接下来我们为其建一个聚集索引
执行CREATE CLUSTERED INDEX INDEX_Userid ON T_UserInfo (Userid)
然后再执行SELECT * FROM T_UserInfo WHERE USERID='ABCDE6EF'
切换到消息栏如下显示:
表'T_UserInfo'。扫描计数1,逻辑读2 次,物理读0 次,预读0 次。
此时逻辑读由原来的1变成2,
说明我们又加了一个索引页,现在我们查询时,逻辑读就是要读两页(1索引页+1数据页),此时的效率还不如不建索引。
此时再选中查询语句,然后再Ctrl+L,如下图:



聚集索引查找:扫描聚集索引中特定范围的行
说明,此时用了索引。
OK,到这里你应该已经知道初步知道MSSQL查询计划和如何查看对IO的读取消耗了吧!


接下来我们继续:

现在我再把测试数据改变成1000条
再执行SET STATISTICS IO ON,再执行
SELECT * FROM T_UserInfo WHERE USERID='ABCDE6EF'
在不加聚集索引的情况下:
表'T_UserInfo'。扫描计数1,逻辑读7 次,物理读0 次,预读0 次。
在加聚集索引的情况下:CREATE CLUSTERED INDEX INDEX_Userid ON T_UserInfo (Userid)
表'T_UserInfo'。扫描计数1,逻辑读2 次,物理读0 次,预读0 次。
(其实也就是说此时是读了一个索引页,一个数据页)
如此,在数据量稍大时,索引的查询优势就显示出来了。



先小总结下:
当你构建SQL语句时,按Ctrl+L就可以看到语句是如何执行,是用索引扫描还是表扫描?
通过SET STATISTICS IO ON 来查看逻辑读,完成同一功能的不同SQL语句,逻辑读
越小查询速度越快(当然不要找那个只有几百条记录的例子来反我)。

我们再继续深入:
OK,现在我们再来看一次,我们换个SQL语句,来看下MSSQL如何来执行的此SQL呢?
现在去掉索引:DROP INDEX T_UserInfo.INDEX_Userid
现在打开[显示语句执行情况的详细信息]:SET SHOWPLAN_ALL ON
然后再执行:SELECT * FROM T_UserInfo WHERE USERID LIKE 'ABCDE8%'
看结果栏:结果中有些具体参数,比如IO的消耗,CPU的消耗。
在这里我们只看StmtText:
SELECT * FROM T_UserInfo WHERE USERID LIKE 'ABCDE8%'
|--Table Scan(OBJECT:([student].[dbo].[T_UserInfo]), WHERE:(like([T_UserInfo].[Userid], 'ABCDE8%', NULL)))
Ctrl+L看下此时的图行执行计划:


我再加上索引:
先关闭:SET SHOWPLAN_ALL OFF
再执行:CREATE CLUSTERED INDEX INDEX_Userid ON T_UserInfo (Userid)
再开启:SET SHOWPLAN_ALL ON
再执行:SELECT * FROM T_UserInfo WHERE USERID LIKE 'ABCDE8%'
查看StmtText:
SELECT * FROM T_UserInfo WHERE USERID LIKE 'ABCDE8%'
|--Clustered Index Seek(OBJECT:([student].[dbo].[T_UserInfo].[INDEX_Userid]), SEEK:([T_UserInfo].[Userid] >= 'ABCDE8' AND [T_UserInfo].[Userid] Ctrl+L看下此时的图行执行计划:

在有索引的情况下,我们再写一个SQL:
SET SHOWPLAN_ALL ON
SELECT * FROM T_UserInfo WHERE LEFT(USERID,4)='ABCDE8%'
查看StmtText:
SELECT * FROM T_UserInfo WHERE LEFT(USERID,4)='ABCDE8%'
|--Clustered Index Scan(OBJECT:([student].[dbo].[T_UserInfo].[INDEX_Userid]), WHERE:(substring([T_UserInfo].[Userid], 1, 4)='ABCDE8%'))
Ctrl+L看下此时的图行执行计划:


我们再分别看一下三种情况下对IO的操作
分别如下:
第一种情况:表'T_UserInfo'。扫描计数1,逻辑读7 次,物理读0 次,预读0 次。
第二种情况:表'T_UserInfo'。扫描计数1,逻辑读3 次,物理读0 次,预读0 次。
第三种情况:表'T_UserInfo'。扫描计数1,逻辑读8 次,物理读0 次,预读0 次。
这说明:
第一次是表扫描,扫了7页,也就是全表扫描
第二次是索引扫描,扫了1页索引,2页数据页
第三次是索引扫描+表扫描,扫了1页索引,7页数据页
[图形界面也有对CPU和IO的消耗,也可以看出来哪个最优!]

通过比较,嘿嘿,很容易的看出:第二种第三种写法在都有索引的情况下,like有效的使用索引,而left则不能,这样一个最简单的优化的例子就出来了,哈哈。

如果以上你都明白了,那么你可能已经对SQL的优化有初步新的想法了,网上一堆堆的SQL优化的文章真的是那样吗?你自己试试就知道了,而不必盲目去记那些东西,自己试试,看看MSSQL到底是怎么来执行就明白了。
在我举的例子中,用的是聚集索引扫描,字段是字母加数字,大家可以试试看纯数字的、字母的、汉字的等等,了解下MMSQL会如何改变SQL语句来利用索引。然后再试试非聚集索引是什么情况?用不用索引和什么有关?子查询MSSQL是如何执行?IN用不用索引,LIKE用不用索引?函数用不用索引?OR、AND、UNION?子查询呢?在这里我不一一去试给大家看了,只要知道了如何去看MSSQL的执行计划(图形和文本),很多事情就很明朗了。

大总结:
实现同一查询功能的SQL写法可能会有多种,如果判断哪种最优化,如果仅仅是从时间上来测,会受很多外界因素的影响,而我们明白了MSSQL如何去执行,通过IO逻辑读、通过查看图示的查询计划、通过其优化后而执行的SQL语句,才是优化SQL的真正途径。

另外提醒下:数据量的多少有时会影响MSSQL对同一种查询写法语句的执行计划,这一点在非聚集索引上特别明显,还有就是在多CPU与单CPU下,在多用户并发情况下,同一写法的查询语句执行计划会有所不同,这个就需要大家有机会去试验了(我也没有这方面的太多经验与大家分享)。

先写这些吧,由于我对MSSQL认识还很浅薄,如有不对的地方,还请指正。
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

php怎麼連接mssql資料庫 php怎麼連接mssql資料庫 Oct 23, 2023 pm 12:02 PM

php連接mssql資料庫的方法有使用PHP的MSSQL擴充、使用PDO等。詳細介紹:1.使用PHP的MSSQL擴充方法,確保PHP安裝了MSSQL擴充。可以在PHP設定檔(php.ini)中檢查是否啟用了mssql擴充;2、使用PDO方法,確保PHP安裝了PDO擴充。可以在PHP設定檔(php.ini)中檢查是否啟用了pdo_sqlsrv擴充。

Ubuntu安裝PHP並設定MSSQL連線的詳細指南 Ubuntu安裝PHP並設定MSSQL連線的詳細指南 Feb 29, 2024 am 11:15 AM

Ubuntu是一款流行的開源作業系統,常用於伺服器運作。在Ubuntu上安裝PHP並設定MSSQL連線是許多開發者和系統管理員經常需要做的操作之一。本文將為讀者提供一份詳細的指南,步驟包含安裝PHP、設定Apache、安裝MSSQLServer等內容,並附上具體的程式碼範例。第一步:安裝PHP及相關擴展首先,我們需要安裝PHP及其相關擴展,以便支援PHP連接

Ubuntu環境下安裝PHP支援MSSQL資料庫的步驟詳解 Ubuntu環境下安裝PHP支援MSSQL資料庫的步驟詳解 Feb 29, 2024 am 10:39 AM

在Ubuntu環境下安裝PHP支援MSSQL資料庫的步驟詳解在開發Web應用程式時,常會遇到需要連接MicrosoftSQLServer(MSSQL)資料庫的情況。在Ubuntu環境下,要實現PHP對MSSQL資料庫的連接,需要安裝相關的軟體以及配置適當的設定。接下來,將詳細介紹在Ubuntu環境下安裝PHP支援MSSQL資料庫的步驟,並提供具體的程式碼

mysql執行計畫是什麼 mysql執行計畫是什麼 Jul 20, 2023 am 10:24 AM

mysql執行計畫是指mysql資料庫管理系統在執行sql語句時,所採取的特定執行策略和操作順序。執行計劃是透過查詢最佳化器產生的,並且它描述了mysql發現和評估sql查詢的過程,提供了有關如何使用索引、執行連接操作、執行排序等重要信息,來幫助開發人員優化查詢效能。 mysql執行計劃的產生過程涉及查詢解析器、查詢最佳化器和執行器等元件。

MySql的SQL語句執行計畫:如何最佳化MySQL的查詢過程 MySql的SQL語句執行計畫:如何最佳化MySQL的查詢過程 Jun 16, 2023 am 09:15 AM

隨著網路的快速發展,資料的儲存和處理也變得越來越重要。因此,關係型資料庫是現代軟體平台中不可或缺的組成部分。 MySQL資料庫已經成為最受歡迎的關聯式資料庫之一,因為它使用簡單,易於部署和管理。然而,在處理大量資料時,MySQL資料庫的效能問題經常會成為問題。在本文中,我們將深入探討MySQL的SQL語句執行計劃,介紹如何透過最佳化查詢過程來提高MySQL數據

Ubuntu下安裝PHP並連接MSSQL資料庫的完整教程 Ubuntu下安裝PHP並連接MSSQL資料庫的完整教程 Feb 29, 2024 am 11:18 AM

在Ubuntu作業系統下安裝PHP並連接MSSQL資料庫是許多開發者和系統管理員所需掌握的技能之一。本文將提供一個詳細的教學課程,包括安裝PHP、安裝MSSQL伺服器端驅動程式、設定PHP連接MSSQL資料庫,並提供對應的程式碼範例。第一部分:安裝PHP首先,我們需要安裝PHP及相關的擴展,以便能夠連接MSSQL資料庫。在終端機中輸入以下命令來安裝PHP及必要的擴

一次mssql注入+白名單上傳繞過360的範例分析 一次mssql注入+白名單上傳繞過360的範例分析 May 12, 2023 pm 02:37 PM

資訊收集:站點使用vue+aspx+iis8.5搭建。網站登入框有版本號碼且url欄中存在siteserver字樣,因此懷疑是cms搭建的,但未見過該cms,使用谷歌搜尋發現該網站是用siteservercms搭建的,版本為最新,且網路上提供的漏洞在此無法使用,在登入框嘗試注入+弱口令+驗證碼繞過+未授權之類等等手段之後無果,由於具有測試的帳號,乾脆因此直接登入網站進行測試。圖示為我從網路上尋找的登入圖片,紅框處當時是版本號碼而非cms提示。功能測試:進入後台之後簡單瀏覽了一下功能,多是一些頁面管理的

ubuntu怎麼安裝php mssql ubuntu怎麼安裝php mssql Jan 28, 2023 am 09:25 AM

ubuntu安裝php mssql的方法:1、進入終端機指令視窗;2、執行「curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/ mssql-release.list」;3、透過install指令安裝「pdo_sqlsrv」即可。

See all articles