2019年3月3日 星期日

SQL Server join to hash join and optimize plan

env:Windows Server 2016
       SQL Server 2016 SP2

報表有一個新需求,在測試期間執行完畢大都需要11分鐘左右,在嘗試調整語法後還是一直卡在11分鐘。在想不到任何方法下,想說看看執行計畫是不是有遇到警告,可以優化警告的訊息來拯救我這一個建議要做倉儲卻被否決的DBA。

1.嘗試把部分資料取到要執行報表的DB,並補上需要的索引
command:
CREATE CLUSTERED INDEX [IX_CreatOn] ON [dbo].[TESTTB01]
(
[CreatOn] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, 
DROP_EXISTING = OFF, ONLINE = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON,
DATA_COMPRESSION=PAGE) ON [PRIMARY]
GO

USE [TESTDB01]
GO
CREATE NONCLUSTERED INDEX [IX_Brand_Session_Date]
ON [dbo].[TESTTB01] ([Brand],[Session],[Date])
INCLUDE ([GId],[CreatOn],[Amount],[Revenue])
WITH(ONLINE=ON, DATA_COMPRESSION=PAGE)
GO


2.在執行計畫發現inner join出現警告訊息
message:
Operator used tempdb to spill data during execution with spill level 2 and 1 spilled thread(s)

一開始看到這個訊息完全想不透,跟TEMPDB有什麼關係?
上網找了一下,大多圍繞在TEMPDB空間,SQL Server記憶體。看到下面第四張圖更出現"NO STATS()",這一定更會認為是缺少統計資訊。























































3.嘗試檢查tempdb,統計資訊是否不足或缺失
command:
check cpu
SELECT cpu_count AS [Logical CPU Count], hyperthread_ratio AS [Hyperthread Ratio],
cpu_count/hyperthread_ratio AS [Physical CPU Count], 
physical_memory_kb/1024 AS [Physical Memory (MB)], affinity_type_desc, 
virtual_machine_type_desc, sqlserver_start_time
FROM sys.dm_os_sys_info WITH (NOLOCK) OPTION (RECOMPILE);

chack memory:
SELECT
(physical_memory_in_use_kb/1024) AS Memory_usedby_Sqlserver_MB,
(locked_page_allocations_kb/1024) AS Locked_pages_used_Sqlserver_MB,
(total_virtual_address_space_kb/1024) AS Total_VAS_in_MB,
process_physical_memory_low,
process_virtual_memory_low
FROM sys.dm_os_process_memory

更新統計資訊,tempdb空間充足

結果還是一樣。


4.變更inner join為inner hash join
有這個想法是剛好想起看某個教學影片講到execution plan提到hash join

調整後重新看執行計畫警告消失了,速度也有加快,剩下1分鐘。
在其他使用到這2個表的語法也改為inner hash join也有加速的效果
























5.心得
個人覺得這是一個特例,看到這個狀況還是第一次。網路上找到的都是通例。倒是多嘗試找到新方法比較有成就感。





沒有留言:

張貼留言