SQLServer性能優化一則小實例

首先找到 最耗CPU的top50 SQL
------------------------------------------
SELECT
     total_cpu_time,
     total_execution_count,
     number_of_statements,
     s2.text
     --(SELECT SUBSTRING(s2.text, statement_start_offset / 2, ((CASE WHEN statement_end_offset = -1 THEN (LEN(CONVERT(NVARCHAR(MAX), s2.text)) * 2) ELSE statement_end_offset END) - statement_start_offset) / 2) ) AS query_text
FROM
     (SELECT TOP 50
           SUM(qs.total_worker_time) AS total_cpu_time,
           SUM(qs.execution_count) AS total_execution_count,
           COUNT(*) AS  number_of_statements,
           qs.sql_handle --,
           --MIN(statement_start_offset) AS statement_start_offset,
           --MAX(statement_end_offset) AS statement_end_offset
     FROM
           sys.dm_exec_query_stats AS qs
     GROUP BY qs.sql_handle
     ORDER BY SUM(qs.total_worker_time) DESC) AS stats
     CROSS APPLY sys.dm_exec_sql_text(stats.sql_handle) AS s2
------------------------------------------------------------------------------------------------
有一條SQL執行效率非常差,大概30秒~80秒不等,而且佔據了所有CPU消耗時間的20%,並且執行次數也很多
select f_getconcatname(id) from table where id>1 and id<100
如果單個ID,速度還是很快的,初步判斷是ID未作索引的問題
後來查看了一下該表的定義,已經做了索引,索引可以排除掉
在接着判斷是函數的問題
查看了一下函數的定義,這個只是大概的函數
create function f_getconcatname(@id)
as
DECLARE cur_concat CURSOR FOR SELECT Name FROM tableB where id=@id
declare @ret varchar(200),@tmp varchar(20)
set @ret='';
set @tmp=''
OPEN cur_concat
FETCH NEXT FROM cur_concat into @tmp
WHILE @@FETCH_STATUS = 0
BEGIN
  set ret=@ret+@tmp+','
  FETCH NEXT FROM cur_concat into @tmp
END
CLOSE contact_cursor
DEALLOCATE contact_cursor
end
原以爲是函數內遊標循環太慢就修改了一下該函數
create function f_getconcatname(@id)
as
declare @ret varchar(200)
set @ret='';
SELECT @ret=@ret+Name+',' FROM tableB where id=@id
return @ret
end
沒想到竟然比遊標還慢
後來檢查了一下tableB關於ID的定義,發現ID沒有定義爲索引
添加索引後再次嘗試,發現速度提高到0~1秒
OK,解決該問題
同時在CPU 消耗總量的TOP 50中居然有25問題與之有關,一連串順帶解決了25個問題


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章