2010-12-15 12 views
8

में स्केलर बनाम तालिका-मूल्यवान कार्यों का प्रदर्शन प्रदर्शन ठीक है इसलिए मैंने टेबल-वैल्यू फ़ंक्शंस का सुझाव देने वाले लेखों का एक पूरा समूह पढ़ा है और क्रॉस लागू स्केलर udf से बेहतर प्रदर्शन प्रदान करता है। मैं अपने काम को दोनों तरीकों से लिखना चाहता था और फिर यह देखने के लिए परीक्षण करता हूं कि कौन सा बेहतर है - लेकिन मैं यह नहीं समझ सकता कि मुझे क्या उपयोग करना है/यह समझने के लिए कि कौन सा बेहतर विकल्प है।एसक्यूएल सर्वर

मैं SQL सर्वर 2005 का उपयोग कर रहा हूं। मैंने अनुमानित निष्पादन योजना, वास्तविक निष्पादन योजना चलाने और डेटाबेस इंजन ट्यूनिंग सलाहकार में क्वेरी का विश्लेषण करने का प्रयास किया है और मुझे नहीं पता कि यह मुझे क्या बताने की कोशिश कर रहा है।

showplan_all चालू/बंद का उपयोग करना ऐसा लगता है कि तालिका आधारित फ़ंक्शन अधिक cpu 1.157e-06 बनाम 8.3e-05 का उपयोग करेगा, लेकिन तालिका फ़ंक्शन में 0.000830157 बनाम 0.01 9 83356 की कुल उप-लागत है।

तालिका मूल्यवान फ़ंक्शन की क्वेरी लागत स्केलर की तुलना में अधिक लागत लगती है। भले ही मैंने सोचा कि यह बेहतर विकल्प माना जाता है।

तो जब भी मैं इसे साबित करना चाहता हूं कि कौन सा बेहतर प्रदर्शन देता है - मुझे यकीन नहीं है कि इन उपकरणों में क्या देखना है - इसलिए किसी भी सुझाव की सराहना की जाएगी!

मुझे कैलेंडर तिथि के आधार पर अकादमिक वर्ष मूल्य (डेटाबेस में सेट दिनांक सीमा के आधार पर) प्राप्त करने की आवश्यकता है ताकि फ़ंक्शन सामग्री नीचे दी गई हो - तो यह ठीक है कि मैं स्केलर या तालिका आधारित हूं या नहीं। इस साल अन्य प्रश्नों में फ़ीड ..

CREATE FUNCTION fn_AcademicYear 
(
    -- Add the parameters for the function here 
    @StartDate DateTime 
) 
RETURNS 
@AcademicYear TABLE 
(
    AcademicYear int 
) 
AS 
BEGIN 

DECLARE @YearOffset int, @AcademicStartDate DateTime 

    -- Lookup Academic Year Starting Date 
    SELECT @AcademicStartDate = CONVERT(DateTime,[Value]) 
    FROM dbo.SystemSetting 
    WHERE [Key] = 'AcademicYear.StartDate' 

    SET @YearOffset = DATEPART(YYYY,@StartDate) - DATEPART(YYYY,@AcademicStartDate); 
    -- try setting academic looking start date to year of the date passed in 
    SET @AcademicStartDate = DATEADD(YYYY, @YearOffset, @AcademicStartDate); 

    IF @StartDate < @AcademicStartDate 
    BEGIN 
     SET @AcademicStartDate = DATEADD(YYYY, @YearOffset-1, @AcademicStartDate); 
    END 

     INSERT @AcademicYear 
     SELECT YEAR(@AcademicStartDate) 

    RETURN 

धन्यवाद !!

+2

जिज्ञासा से बाहर - क्या आप वास्तव में पाते हैं कि 'YYYY'' वर्ष 'की तुलना में अधिक पठनीय है? –

+0

मैंने वास्तव में इसके बारे में सोचा नहीं है .. और किसी और के फ़ंक्शन से उस वाक्यविन्यास को लिया :) लेकिन हाँ साल अधिक पठनीय होगा। – Jen

उत्तर

16

आप उन प्रदर्शन लाभों को नहीं देख रहे हैं जिन्हें आप उम्मीद करते हैं क्योंकि आपकी तालिका-मूल्यवान फ़ंक्शन मल्टीफंक्शन है, इन-लाइन नहीं है। मल्टी-फ़ंक्शन टीवीएफ को उसी तरह स्केलर यूडीएफ के रूप में निष्पादित किया जाना चाहिए - प्रति पंक्ति एक बार - इसलिए बहुत कम लाभ होता है।

this article by Itzik Ben-Gan में उदाहरण (जो इन-लाइन TVFs के लाभों पर चर्चा करता है), निम्नलिखित परीक्षण की स्थापना के बाद:

SET NOCOUNT ON; 
IF OBJECT_ID('dbo.T1') IS NOT NULL DROP TABLE T1; 
GO 

WITH 
    L0 AS (SELECT 0 AS c UNION ALL SELECT 0), 
    L1 AS (SELECT 0 AS c FROM L0 AS A CROSS JOIN L0 AS B), 
    L2 AS (SELECT 0 AS c FROM L1 AS A CROSS JOIN L1 AS B), 
    L3 AS (SELECT 0 AS c FROM L2 AS A CROSS JOIN L2 AS B), 
    L4 AS (SELECT 0 AS c FROM L3 AS A CROSS JOIN L3 AS B), 
    L5 AS (SELECT 0 AS c FROM L4 AS A CROSS JOIN L4 AS B), 
    Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS n FROM L5) 
SELECT n INTO dbo.T1 FROM Nums WHERE n <= 1000000; 

रन एक लाख:

1 लाख पंक्तियों के साथ एक संख्या तालिका बनाएं निम्नलिखित कोड का उपयोग कर अपने TVF की फांसी:

set statistics time on 
SELECT n,DATEADD(HOUR,n,'1900-01-01'),AY.AcademicYear 
FROM T1 
CROSS APPLY dbo.fn_AcademicYear(DATEADD(HOUR,n,'1900-01-01')) AS AY 
set statistics time off 

अपने सिस्टम पर, यह 83 सेकंड के एक औसत तीन फांसी के लिए समय बीत दिखाया, runn प्रत्येक निष्पादन के बीच DBCC dropcleanbuffers आईएनजी।

यदि आप अपने स्केलर मूल्यवान फ़ंक्शन के लिए एक समान परीक्षण करते हैं, तो आपको तुलनात्मक प्रदर्शन का एक स्पष्ट विचार होना चाहिए।

परीक्षण में यह भी पता चला कि आपके कार्य में एक बग क्या प्रतीत होता है। यदि AcademicYear.StartDate को '2010-09-01' पर सेट किया गया है, तो '1 9 00-01-01' के इनपुट के लिए लौटाया गया शैक्षणिक वर्ष 17 9 8 है, जहां ऐसा लगता है कि 18 99 की अपेक्षा की जाएगी।

श्रेष्ठ प्रदर्शन प्राप्त करने के लिए, आपको होने के लिए TVF बदलने की आवश्यकता होगी में लाइन - मैं निम्नलिखित है, जो मेरा मानना ​​है कि बग को सही के साथ आया था:

CREATE FUNCTION fn_AcademicYear2 
(
    @StartDate DATETIME 
) 
RETURNS TABLE 
AS 
RETURN 
(
    -- Lookup Academic Year Starting Date 
    WITH dtCTE 
    AS 
    (
     SELECT CONVERT(DATETIME,[Value]) AS dt 
     FROM dbo.SystemSetting 
     WHERE [KEY] = 'AcademicYear.StartDate' 
    ) 
    SELECT CASE WHEN @StartDate >= DATEADD(YEAR,DATEDIFF(YEAR,dt,@StartDate),dt) 
       THEN YEAR(@StartDate) 
       ELSE YEAR(DATEADD(YEAR,DATEDIFF(YEAR,dt,@StartDate) - 1,dt)) 
      END AS AcademicYear 
    FROM dtCTE 
) 
GO 

यह औसत गुजरे था तीन रनों पर 8.9 सेकेंड का समय - लगभग दस गुना तेजी से।

दूसरी बात यह है कि टीवीएफ का उपयोग करने से प्रदर्शन लाभ नगण्य होगा जब तक कि आप इसे कई पंक्तियों में लागू नहीं कर रहे हैं, जैसा कि इस परीक्षण में है। यदि आप एक समय में एक मूल्य पर इसका उपयोग कर रहे हैं, तो आपको बहुत सारे लाभ दिखाई नहीं देंगे जबतक आपके पास समानांतर में कार्य करने के हजारों उदाहरण नहीं होते हैं।

+0

वास्तव में विस्तृत उत्तर के लिए धन्यवाद और मेरे समारोह में सुधार के लिए धन्यवाद !! :) – Jen

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