[SQL]改善SQL查詢執行效能小方法

[SQL]改善SQL查詢執行效能小方法

 

複習一下老師上課講的東西,這些步驟都很簡單,不用太高深的技術。

採用2-part name

當下SQL指令時,會先根據schema name一一去找是否物件屬於該schema,如果明確指定schema name,可以減少搜尋時間。

原先的sql


SELECT * FROM EMPLOYEE

修改後的sql


SELECT * FROM dbo.EMPLOYEE

採用SARGs寫法

有下面這些原則

1.避免不等比較運算子 (如下所示的資料行! = 常數)。這不是有效的搜尋引數,並不允許評估您對本專欄中,索引的使用性最佳化器,如果有的話。

2.減少可行的範圍內的區域變數使用 (如下所示的資料行 = @ 區域變數、) 除非在執行階段之前,可以判定 @ 本機變數的值。這是因為在編譯時期不知道 @ 本機變數的值。這可能會導致最佳化器使用魔法密度或索引密度。沒有可用的值時,它無法核對分配步驟。如果當做參數傳遞至預存程序時,區域變數就會使用做為有效的搜尋引數。

3.請盡量避免在資料行操作 (如下所示的資料行 1 100 = 常數)。這不會被視為有效的搜尋引數。相反地,請試著重新寫入同一個運算式 (如下所示的表單欄等於常數/100)。

4.子查詢是否為"...where 資料行的運算子 (從資料表選取資料行)",最佳化器可能無法使用散發步驟,因為直到執行查詢時,才會知道常數運算式的值。

5.發佈網頁不能使用 join 子句的 (不同於 [搜尋] 引數)。

簡單來說就是避免在where的等號左邊進行運算,查詢的欄位及條件使用索引的欄位。

範例SQL如下


-- SARGs測試
-- 資料來源: 德瑞克老師的上課筆記+自行改寫
USE [tempdb]
GO
-- 建立測試表格

if EXISTS
(SELECT name
 FROM
	 sys.tables
 WHERE
	 name = 'EMPLOYEE') DROP TABLE dbo.EMPLOYEE
CREATE TABLE [dbo].[EMPLOYEE](	
	[STAFF] [nvarchar](6) NOT NULL,
	[NAME] [nvarchar](30) NULL,
	[BRNO] [nvarchar](4) NULL,
	[ID] [nvarchar](18) NULL,	
)
GO
-- 輸入測試資料(來源資料表格約13009筆資料)
INSERT INTO tempdb.dbo.EMPLOYEE
SELECT [STAFF]
	 , [NAME]
	 , [BRNO]
	 , [ID]
FROM
	production.dbo.EMPLOYEE
GO
-- 建立 nonclusterindex 在ID欄位上
CREATE NONCLUSTERED INDEX [ix_ID] on
[dbo].[EMPLOYEE]([ID])
GO

-- 檢查index是否建立
sp_helpindex 'dbo.EMPLOYEE'
GO
-- 檢查測試資料
SELECT *
FROM
	dbo.EMPLOYEE
GO

-- 非SARGs寫法
SELECT ID
FROM
	dbo.EMPLOYEE
WHERE
	ID + ',' + Name = 'A123456789,林大貓'
GO

-- SARGs寫法
SELECT ID
FROM
	dbo.EMPLOYEE
WHERE
	ID = 'A123456789'
	AND Name = '林大貓'
GO

-- 非SARGs寫法
SELECT ID
FROM
	dbo.EMPLOYEE
WHERE
	substring(ID,1,3)= 'A12'
GO

-- SARGs寫法
SELECT ID
FROM
	dbo.EMPLOYEE
WHERE
	ID LIKE 'A12%'
GO

-- 刪除測試表格
if EXISTS
(SELECT name
 FROM
	 sys.tables
 WHERE
	 name = 'EMPLOYEE') DROP TABLE dbo.EMPLOYEE

 

在function或stored procedure加入SET NOCOUNT ON

當 SET NOCOUNT 為 ON 時,不返回計數(表示受 Transact-SQL 語句影響的行數)。當 SET NOCOUNT 為 OFF 時,返回計數。即使當 SET NOCOUNT 為 ON 時,也更新 @@ROWCOUNT 函數。

當 SET NOCOUNT 為 ON 時,將不給客戶端發送存儲過程中的每個語句的 DONE_IN_PROC 信息。當使用 Microsoft SQL Server 提供的工具執行查詢時,在 Transact-SQL 語句(如 SELECT、INSERT、UPDATE 和 DELETE)結束時將不會在查詢結果中顯示"nn rows affected"。

如果存儲過程中包含的一些語句並不返回許多實際的數據,則該設置由於大量減少了網絡流量,因此可顯著提高性能。

SET NOCOUNT 設置是在執行或運行時設置,而不是在分析時設置。

 

參考資料

德瑞克老師的上課筆記

INF: 決定發佈的頁面使用的搜尋引數

INF: Search Arguments That Determine Distribution Page Usage

SQL Server 2005 Compact Edition Books Online

INF: 將 Microsoft SQL Server 效能最佳化

資訊: 撰寫有效率的查詢和預存程序

SQL SET NOCOUNT ON的含义和作用