[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: Search Arguments That Determine Distribution Page Usage
SQL Server 2005 Compact Edition Books Online