程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> 分析TOP語句放到表值函數外,效率異常低下的原因

分析TOP語句放到表值函數外,效率異常低下的原因

編輯:關於SqlServer
 

SQLSERVER的表值函數是SQLSERVER 2005以來的新特性,由於它使用比較方便,就像一個單獨的表一樣,在我們的系統中大量使用。有一個獲取客戶數據的SQLSERVER 表值函數,如果使用管理員登錄,這個函數會返回150W行記錄,大概需要30秒左右,但如果將TOP語句放到表值函數外,效率異常低下,需要約3分鐘:

  1. select top 20 * from GetFrame_CustomerSerch('admin','1')

下面是該存儲過程的定義:

  1. ALTER FUNCTION [dbo].[GetFrame_CustomerSerch]
  2. (
  3. -- Add the parameters for the function here
  4. @WorkNo varchar(38)
  5. ,@SerchChar varchar(500)
  6. )
  7. RETURNS TABLE
  8. AS
  9. RETURN
  10. (
  11. -- Add the SELECT statement with parameter references here
  12. select a.GUID,a.CustomerName,a.CustomerIDcard,a.CustomerPhone,a.CustomerMobile from
  13. (
  14. --具體子查詢略
  15. )
  16. ) a union all
  17. select b.GUID,b.CustomerName,b.CustomerIDcard,b.CustomerPhone,
  18. b.CustomerMobile from WFT_ManagerCollectUsers a left join WFT_Customer b on
  19. a.FundAccount=b.FundAccount
  20. --where a.WorkNo=@WorkNo
  21. WHERE a.WorkNo IN
  22. (
  23. --具體子查詢略
  24. )
  25. )

這個語句放在PDF.NET數據開發框架的SQL-MAP文件中,開始還以為是框架引起的,將這個語句直接在查詢分析器中查詢,仍然很慢。

將GetFrame_CustomerSerch 中的SQL語句提取出來,直接加上Top查詢,只需要6秒,快了N倍:

  1. declare @WorkNo varchar(38)
  2. declare @SerchChar varchar(500)
  3. set @WorkNo='admin'
  4. set @SerchChar='1'
  5. select top 20 a.GUID,a.CustomerName,a.CustomerIDcard,a.CustomerPhone,
  6. a.CustomerMobile from
  7. (
  8. --具體子查詢略
  9. )
  10. ) a union all
  11. select b.GUID,b.CustomerName,b.CustomerIDcard,b.CustomerPhone,b.CustomerMobile
  12. from WFT_ManagerCollectUsers
  13. a left join WFT_Customer b on a.FundAccount=b.FundAccount
  14. WHERE a.WorkNo IN
  15. (
  16. --具體子查詢略
  17. )

為什麼會有這麼大的差異?

我分析可能有如下原因:

1,在表值函數外使用Top或者其它條件,SQLSERVER 的查詢優化器無法針對此查詢進行優化,比如先返回所有記錄,然後再在臨時表中選取前面的20條記錄;

2,雖說該表值函數使用了“表變量”,它是內存中的,但如果這個“表”結果很大,很有可能內存放不下(並非還有物理內存就會將結果放到物理內存中,數據庫自己還會有保留的,會給其它查詢預留一定的內存空間),使用虛擬內存,而虛擬內存實際上就是磁盤頁面文件,當記錄太多就會發生頻繁的頁面交換,從而導致這個查詢效率非常低。

看來,“表值函數”也不是傳說中的那麼好,不知道大家是怎麼認為的。

最近還遇到一個怪異的問題,有一個存儲過程,老是在系統運行1-2天後變得極其緩慢,但重新修改一下又很快了(只是加一個空格之類),不知道大家遇到過沒有,什麼原因?

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved