2012-06-14 11 views
7

का उपयोग करते समय एसक्यूएल फ़ंक्शंस को बहुत धीमा करना कॉलिंग मैं अपने सी # एएसपी.Net एप्लिकेशन से SQL फंक्शन (यूडीएफ) को कॉल कर रहा हूं। जिस फ़ंक्शन को मैं कॉल कर रहा हूं उसे "अद्वितीय पहचानकर्ता" प्रकार का एक पैरामीटर चाहिए।एसक्यूएल कॉमांड पैरामीटर

अगर मैं फोन करना और SqlCommand के CommandText में "अशक्त" गुजरती हैं, परिणाम के बारे में 3 सेकंड में वापस आने के लिए ...

SqlCommand Command = new SqlCommand(); 
Command.Connection = (SqlConnection)(DbDataModifier.CreateConnection()); 
Command.CommandText = "select * from GetLocalFirmLoginsSummary(null) order by Date asc" 
Command.CommandType = CommandType.Text; 

Command.Connection.Open(); 

SqlDataReader Reader = Command.ExecuteReader(); // takes 3 seconds 

लेकिन, अगर मैं फोन करना और DBNull गुजरती हैं। एक SqlParameter के रूप में मूल्य, परिणाम अगर मैं एसक्यूएल प्रबंधन स्टूडियो में एक ही क्वेरी चलाने 60 से अधिक सेकंड लग लौटने के लिए ...

SqlCommand Command = new SqlCommand(); 
Command.Connection = (SqlConnection)(DbDataModifier.CreateConnection()); 
Command.CommandText = "select * from GetLocalFirmLoginsSummary(@CustomerGroupID) order by Date asc" 
Command.CommandType = CommandType.Text; 

SqlParameter Param = new SqlParameter(); 
Param.ParameterName = "@CustomerGroupID"; 
Param.SqlDbType = SqlDbType.UniqueIdentifier; 
Param.Direction = ParameterDirection.Input; 
Param.IsNullable = true; 
Param.Value = DBNull.Value; 
Command.Parameters.Add(Param); 

Command.Connection.Open(); 

SqlDataReader Reader = Command.ExecuteReader(); // takes over 60 seconds 

, इसके बारे में 3 सेकंड लेता है, तब भी जब एक पैरामीटर के रूप अशक्त गुजर ..

declare @CustomerGroupID uniqueidentifier 
set @CustomerGroupID = null 

select * from GetLocalFirmLoginsSummary(@CustomerGroupID) 

समारोह मैं फोन कर रहा हूँ के रूप में परिभाषित किया गया है:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[GetLocalFirmLoginsSummary] 
( 
    @CustomerGroupID uniqueidentifier 
) 
RETURNS TABLE 
AS 
RETURN 
(

SELECT  CustomerGroupID, CustomerGroupName, USR, DATEADD(MONTH, DATEDIFF(MONTH, 0, createdDate), 0) AS Date, COUNT(*) AS Quantity 
FROM   dbo.GetLocalFirmLogins(@CustomerGroupID) AS Logins 
GROUP BY USR, CustomerGroupID, CustomerGroupName, DATEADD(MONTH, DATEDIFF(MONTH, 0, createdDate), 0) 

) 

...

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[GetLocalFirmLogins] 
( 
@CustomerGroupID uniqueidentifier 
) 
RETURNS TABLE 
AS 
RETURN 
(

SELECT  vw_CustomerGroupAccountDetails.CustomerGroupID, vw_CustomerGroupAccountDetails.CustomerGroupName, Organisations.USR, Organisations.town AS FirmTown, 
        Users.id AS ID, Users.userName, Users.password, Users.isPartner, Users.isFeeEarner, Users.nlisUserName, Users.nlisPassword, Users.email, Users.lastLoginDate, Users.createdDate 
FROM   vw_CustomerGroupAccountDetails RIGHT OUTER JOIN 
         Organisations ON vw_CustomerGroupAccountDetails.AccountID = CAST(Organisations.id AS nvarchar(50)) RIGHT OUTER JOIN 
        Users ON Organisations.clientId = Users.uploadedBy 
WHERE  (Users.canLogin = 1) AND (Users.isDeleted = 0) AND (NOT (Organisations.USR IS NULL)) AND 
         ((vw_CustomerGroupAccountDetails.CustomerGroupID = @CustomerGroupID) OR (@CustomerGroupID IS NULL)) 

) 

तो क्या हुआ तो बहुत लंबे समय तक लेने के लिए जब मैं सी # से एसक्यूएल समारोह फोन कर रहा हूँ यह कारण बनता है एक SQLCommand के एक वर्गमीटर का उपयोग कर?

मैं एसक्यूएल सर्वर का उपयोग कर रहा 2000

मैं हर जगह और हर तरह से मैं के बारे में सोच सकते हैं में खोज की है, लेकिन किसी और एक समान समस्या हो रही नहीं मिल रहा।

+0

जब आप एसक्यूएल कहते हैं, तो आप डेटाबेस-स्वतंत्र [संरचित क्वेरी भाषा] (http://stackoverflow.com/questions/tagged/sql) के बारे में बात नहीं कर रहे हैं, आप माइक्रोसॉफ्ट डेटाबेस उत्पाद [SQL सर्वर पर चर्चा कर रहे हैं ] (http://stackoverflow.com/questions/tagged/sql- सर्वर), सही? –

+6

काफी संभावित पैरामीटर स्नीफिंग। –

+0

क्या आपने परीक्षण किया है कि यह शून्य के लिए विशिष्ट है? सामान्य मूल्य के साथ क्या? – Sebas

उत्तर

1

जिम, क्या आप dbo.GetLocalFirmLogins का स्रोत पोस्ट कर सकते हैं?

जैसा कि मार्टिन कहते हैं, यह पैरामीटर स्नीफिंग हो सकता है। यदि ऐसा है, तो उस कोड में एक प्रश्न संकेत जहां @CustomerGroupID की तलाश "शल्य चिकित्सा" को ठीक करने का सबसे अच्छा तरीका हो सकता है।

dbo.GetLocalFirmLogins में क्वेरी में विकल्प जोड़ना (लूप जॉइन) जोड़ना ठीक हो सकता है।

मुझे लगता है कि मैं यह भी समझा सकता हूं कि क्यों एसएसएमएस समस्या को नहीं देखता है, जबकि सी # करता है। क्वेरी का यह हिस्सा:

(CustomerGroupID = @CustomerGroupID) OR (@CustomerGroupID IS NULL) 

कनेक्शन आप से आ रहे हैं की एएनएसआई शून्य सेटिंग के आधार पर दो अलग-अलग योजनाओं मिल सकता है। एएनएसआई शून्य और प्रभाव यहाँ वर्णित है:

SET ANSI_NULLS

आप अपने कनेक्शन की एएनएसआई सेटिंग देख सकते हैं इस क्वेरी के परिणामों को पुन: प्राप्त द्वारा:

DBCC USEROPTIONS

SSMS एक अलग शून्य हो सकता है यह सेटिंग कि आप सी # कोड और क्वेरी का एक अलग मूल्यांकन का कारण बनते हैं।

+0

मैंने अब अपनी मूल पोस्ट के नीचे GetLocalFirmLogins को जोड़ा है। – JimRarbs

+0

बीटीडब्ल्यू, मुझे उम्मीद है कि एक समाधान है जिसे सी # कोड में कार्यान्वित किया जा सकता है, क्योंकि मुझे उम्मीद है कि मैं इसे अन्य लोगों को छोड़ सकता हूं ताकि कम एसक्यूएल अनुभव वाले यूडीएफ को उनकी जरूरतों के अनुरूप समायोजित किया जा सके। – JimRarbs

+0

मैंने यह भी पाया है कि यह वास्तव में SQL Server 2000 है जिसका उपयोग मैं कर रहा हूं, 2008 नहीं :( – JimRarbs

0

प्रबंधन स्टूडियो और .NET कोड के बीच प्रदर्शन में अंतर अक्सर ANSI_NULLS जैसी सेटिंग्स से संबंधित होते हैं।

यह SQL Server 2000 में एक बग हो सकता है - this post देखें जो प्रतीत होता है कि फ़ंक्शन बनाने से पहले SET ANSI_NULLS चालू नहीं किया जाता है।

मेरे पास इसका परीक्षण करने के लिए SQL Server 2000 नहीं है, लेकिन शायद आप अपने फ़ंक्शन को स्क्रिप्ट करने का प्रयास कर सकते हैं।

+0

आमतौर पर ** ** सेटिंग स्वयं नहीं होती है। यह सिर्फ इतना है कि विभिन्न सेटिंग्स का मतलब है कि योजनाओं को सत्रों के बीच साझा नहीं किया जाता है, इसलिए गैर-प्रतिनिधि मानकों के लिए संकलित कैश योजना का उपयोग करने के बजाय आपको एक नई नई योजना मिलती है जो ठीक प्रदर्शन करती है। शायद यदि ओपी सभी सेटिंग्स को वही रखता है और योजना कैश को साफ़ करता है तो समस्या दूर हो जाएगी (अस्थायी रूप से जब यह योजना को फिर से सम्मिलित किया जा सकता है) –

+0

ठीक है, मैंने एसएसएमएस में समान विकल्पों के साथ अपना सी # कनेक्शन सेटअप किया है , ANSI_NULLS को चालू करने के लिए सेट सहित। अब जब मैं यूडीएफ को एक अद्वितीय पहचानकर्ता के साथ आबादी वाले पैरामीटर के साथ बुलाता हूं, तो कैश प्लान इसे एक nvarchar (36) के रूप में पारित किया जाता है, लेकिन जब मैं इसे डीबीएनयूएल के साथ बुलाता हूं। पैरामीटर के रूप में वैल्यू, ऐसा लगता है कि यह एक nvarchar के रूप में पारित होता है (4000), जो मैं अनुमान लगा रहा हूं प्रदर्शन प्रदर्शन का कारण बन रहा है? जब मैं यूडीएफ की परिभाषा में ऐसा करने के लिए निर्दिष्ट कर रहा हूं तो यह हमेशा "अनोखा पहचानकर्ता" के रूप में क्यों नहीं पारित होता है? – JimRarbs

+0

मैं पुष्टि कर सकता हूं कि nvarchar (4000) मुद्दा है। यदि मैं एक CAST (x AS NVARCHAR (36)) @CustomerGroupID और ग्राहक समूह समूह कॉलम संदर्भों के आस-पास जहां संभव हो, गति नाटकीय रूप से बढ़ जाती है। तो मैं NVARCHAR (4000) के रूप में SQL को पास नहीं होने के लिए शून्य पैरामीटर मान को कैसे बल दूं? – JimRarbs

1

शायद यह SQL सर्वर में पैरामीटर स्नीफिंग समस्या के कारण हो सकता है।

आप नीचे दिए गए लिंक में और अधिक विस्तार पा सकते हैं:

Parameter Sniffing

मुझे आशा है कि आप इस उपयोगी मिल जाएगा।

संबंधित मुद्दे

 संबंधित मुद्दे