उपयोगकर्ता-परिभाषित स्केलर फ़ंक्शन को इस तरह से अनुकरण करें जो समानता को नहीं रोकता है


12

मैं यह देखने की कोशिश कर रहा हूं कि क्या क्वेरी के लिए एक निश्चित योजना का उपयोग करने के लिए SQL सर्वर को ट्रिक करने का एक तरीका है।

1. पर्यावरण

कल्पना कीजिए कि आपके पास कुछ डेटा है जो विभिन्न प्रक्रियाओं के बीच साझा किया गया है। तो, मान लीजिए कि हमारे पास कुछ प्रयोग परिणाम हैं जो बहुत अधिक स्थान लेते हैं। फिर, प्रत्येक प्रक्रिया के लिए हम जानते हैं कि हम किस वर्ष / महीने के प्रयोग परिणाम का उपयोग करना चाहते हैं।

if object_id('dbo.SharedData') is not null
    drop table SharedData

create table dbo.SharedData (
    experiment_year int,
    experiment_month int,
    rn int,
    calculated_number int,
    primary key (experiment_year, experiment_month, rn)
)
go

अब, हर प्रक्रिया के लिए हमारे पास तालिका में सहेजे गए पैरामीटर हैं

if object_id('dbo.Params') is not null
    drop table dbo.Params

create table dbo.Params (
    session_id int,
    experiment_year int,
    experiment_month int,
    primary key (session_id)
)
go

2. परीक्षण डेटा

आइए कुछ परीक्षण डेटा जोड़ें:

insert into dbo.Params (session_id, experiment_year, experiment_month)
select 1, 2014, 3 union all
select 2, 2014, 4 
go

insert into dbo.SharedData (experiment_year, experiment_month, rn, calculated_number)
select
    2014, 3, row_number() over(order by v1.name), abs(Checksum(newid())) % 10
from master.dbo.spt_values as v1
    cross join master.dbo.spt_values as v2
go

insert into dbo.SharedData (experiment_year, experiment_month, rn, calculated_number)
select
    2014, 4, row_number() over(order by v1.name), abs(Checksum(newid())) % 10
from master.dbo.spt_values as v1
    cross join master.dbo.spt_values as v2
go

3. परिणाम प्राप्त करना

अब, प्रयोग के परिणाम प्राप्त करना बहुत आसान है @experiment_year/@experiment_month:

create or alter function dbo.f_GetSharedData(@experiment_year int, @experiment_month int)
returns table
as
return (
    select
        d.rn,
        d.calculated_number
    from dbo.SharedData as d
    where
        d.experiment_year = @experiment_year and
        d.experiment_month = @experiment_month
)
go

योजना अच्छी और समानांतर है:

select
    calculated_number,
    count(*)
from dbo.f_GetSharedData(2014, 4)
group by
    calculated_number

क्वेरी 0 योजना

यहाँ छवि विवरण दर्ज करें

4. समस्या

लेकिन, डेटा के उपयोग को थोड़ा अधिक सामान्य बनाने के लिए, मैं एक और कार्य करना चाहता हूं - dbo.f_GetSharedDataBySession(@session_id int)। तो, सीधा तरीका स्केलर फ़ंक्शंस बनाना होगा, अनुवाद करना @session_id-> @experiment_year/@experiment_month:

create or alter function dbo.fn_GetExperimentYear(@session_id int)
returns int
as
begin
    return (
        select
            p.experiment_year
        from dbo.Params as p
        where
            p.session_id = @session_id
    )
end
go

create or alter function dbo.fn_GetExperimentMonth(@session_id int)
returns int
as
begin
    return (
        select
            p.experiment_month
        from dbo.Params as p
        where
            p.session_id = @session_id
    )
end
go

और अब हम अपना कार्य बना सकते हैं:

create or alter function dbo.f_GetSharedDataBySession1(@session_id int)
returns table
as
return (
    select
        d.rn,
        d.calculated_number
    from dbo.f_GetSharedData(
        dbo.fn_GetExperimentYear(@session_id),
        dbo.fn_GetExperimentMonth(@session_id)
    ) as d
)
go

क्वेरी 1 योजना

यहाँ छवि विवरण दर्ज करें

यह योजना समान है, सिवाय इसके कि, समानांतर नहीं, क्योंकि स्केलर फ़ंक्शंस प्रदर्शन डेटा एक्सेस पूरे प्लान को सीरियल बनाते हैं

इसलिए मैंने कई अलग-अलग तरीकों की कोशिश की है, जैसे, स्केलर फ़ंक्शंस के बजाय सबक्वेरीज़ का उपयोग करना:

create or alter function dbo.f_GetSharedDataBySession2(@session_id int)
returns table
as
return (
    select
        d.rn,
        d.calculated_number
    from dbo.f_GetSharedData(
       (select p.experiment_year from dbo.Params as p where p.session_id = @session_id),
       (select p.experiment_month from dbo.Params as p where p.session_id = @session_id)
    ) as d
)
go

प्रश्न 2 योजना

यहाँ छवि विवरण दर्ज करें

या उपयोग कर रहे हैं cross apply

create or alter function dbo.f_GetSharedDataBySession3(@session_id int)
returns table
as
return (
    select
        d.rn,
        d.calculated_number
    from dbo.Params as p
        cross apply dbo.f_GetSharedData(
            p.experiment_year,
            p.experiment_month
        ) as d
    where
        p.session_id = @session_id
)
go

प्रश्न 3 योजना

यहाँ छवि विवरण दर्ज करें

लेकिन मैं इस क्वेरी को स्केलर फ़ंक्शंस का उपयोग करने के रूप में अच्छा होने के लिए लिखने का एक तरीका नहीं ढूंढ सकता हूं।

विचारों के जोड़े:

  1. मूल रूप से जो मैं चाहता हूं वह यह है कि किसी तरह SQL सर्वर को कुछ मानों की पूर्व-गणना करने और फिर उन्हें स्थिरांक के रूप में आगे पारित करने में सक्षम होना चाहिए।
  2. यदि कुछ मध्यवर्ती भौतिकीकरण संकेत हो तो क्या सहायक हो सकता है । मैंने कुछ वेरिएंट (मल्टी-स्टेटमेंट TVF या टॉप के साथ cte) की जाँच की है, लेकिन कोई भी योजना उतनी अच्छी नहीं है, जो अब तक के स्केलर फंक्शंस के साथ है
  3. मैं SQL Server 2017 के आने वाले सुधार के बारे में जानता हूं - Froid: एक रिलेशनल डेटाबेस में इंपीरियल प्रोग्राम्स का अनुकूलन। मुझे यकीन नहीं है कि यह मदद करेगा, हालांकि। हालाँकि यहाँ गलत साबित होना अच्छा होता।

अतिरिक्त जानकारी

मैं एक फ़ंक्शन का उपयोग कर रहा हूं (तालिकाओं से सीधे डेटा का चयन करने के बजाय) क्योंकि यह कई अलग-अलग प्रश्नों में उपयोग करना बहुत आसान है, जो आमतौर पर @session_idएक पैरामीटर के रूप में होता है।

मुझे वास्तविक निष्पादन समय की तुलना करने के लिए कहा गया था। इस विशेष मामले में

  • क्वेरी 0 रन ~ 500ms के लिए
  • क्वेरी ~ 1500ms के लिए 1 रन
  • क्वेरी ~ 1500ms के लिए 2 रन
  • क्वेरी ~ 2000ms के लिए 3 रन।

योजना # 2 में एक तलाश के बजाय एक सूचकांक स्कैन है, जिसे तब नेस्टेड छोरों पर विधेय द्वारा फ़िल्टर किया जाता है। प्लान # 3 उतना बुरा नहीं है, लेकिन फिर भी अधिक काम करता है और धीमी गति से काम करता है जो प्लान # 0 है।

मान लेते हैं कि dbo.Paramsशायद ही कभी बदला जाता है, और आमतौर पर लगभग 1-200 पंक्तियाँ होती हैं, इससे अधिक नहीं, मान लें कि 2000 कभी अपेक्षित है। यह अब लगभग 10 कॉलम है और मुझे अक्सर कॉलम जोड़ने की उम्मीद नहीं है।

परमेस में पंक्तियों की संख्या निश्चित नहीं है, इसलिए प्रत्येक के लिए @session_idएक पंक्ति होगी। स्तंभों की संख्या निश्चित नहीं है, यह एक कारण है कि मैं dbo.f_GetSharedData(@experiment_year int, @experiment_month int)हर जगह से कॉल नहीं करना चाहता , इसलिए मैं आंतरिक रूप से इस क्वेरी में नया कॉलम जोड़ सकता हूं। मुझे इस पर कोई राय / सुझाव सुनने में खुशी होगी, भले ही इसमें कुछ प्रतिबंध हों।


Froid के साथ क्वेरी की योजना ऊपर दिए गए query2 के समान होगी, हां, यह आपको उस समाधान तक नहीं ले जाएगा जो आप इस मामले में हासिल करना चाहते हैं।
कार्तिक

जवाबों:


13

आप वास्तव में सुरक्षित रूप से वास्तव में वही हासिल नहीं कर सकते जो आप SQL सर्वर में आज चाहते हैं, यानी एक ही बयान में और समानांतर निष्पादन के साथ, प्रश्न में रखी गई प्रतिबंधों के भीतर (जैसा कि मैं उन्हें समझता हूं)।

तो मेरा सीधा सा जवाब है, नहीं । इस उत्तर के बाकी हिस्से में ज्यादातर इस बात की चर्चा होती है कि यह ब्याज की स्थिति में क्यों है।

एक समानांतर योजना प्राप्त करना संभव है, जैसा कि प्रश्न में उल्लेख किया गया है, लेकिन दो मुख्य किस्में हैं, जिनमें से कोई भी आपकी आवश्यकताओं के लिए उपयुक्त नहीं हैं:

  1. एक सहसंबद्ध नेस्टेड लूप जुड़ते हैं, एक राउंड-रॉबिन शीर्ष स्तर पर स्ट्रीम वितरित करते हैं। यह देखते हुए कि एक एकल पंक्ति Paramsएक विशिष्ट session_idमूल्य के लिए आने की गारंटी है , आंतरिक पक्ष एक एकल थ्रेड पर चलेगा, भले ही यह समानांतरवाद आइकन के साथ चिह्नित हो। यही कारण है कि स्पष्ट रूप से समानांतर योजना 3 भी प्रदर्शन नहीं करती है; यह वास्तव में धारावाहिक है।

  2. अन्य विकल्प नेस्टेड छोरों के अंदरूनी हिस्से में स्वतंत्र समानता के लिए है। यहां स्वतंत्र का मतलब है कि धागे आंतरिक तरफ से शुरू किए गए हैं, न कि केवल उसी धागे (ओं) के रूप में जो नेस्टेड छोरों के बाहरी हिस्से को निष्पादित कर रहे हैं। SQL सर्वर केवल स्वतंत्र इनर-साइड नेस्टेड लूप्स समानता का समर्थन करता है जब एक बाहरी-साइड पंक्ति होने की गारंटी दी जाती है और कोई सहसंबंधित जॉइन्ट पैरामीटर ( प्लान 2 ) नहीं होते हैं।

इसलिए, हमारे पास एक समानांतर योजना का विकल्प है जो वांछित सहसंबद्ध मूल्यों के साथ धारावाहिक (एक धागे के कारण) है; या एक आंतरिक पक्ष समानांतर योजना जिसे स्कैन करना है क्योंकि इसके पास कोई पैरामीटर नहीं है। (इसके अलावा: यह वास्तव में सहसंबद्ध मापदंडों के बिल्कुल एक सेट का उपयोग करके आंतरिक-पक्ष समानता को चलाने की अनुमति दी जानी चाहिए , लेकिन इसे कभी लागू नहीं किया गया है, शायद अच्छे कारण के लिए)।

एक स्वाभाविक प्रश्न यह है: हमें सहसंबद्ध मापदंडों की आवश्यकता क्यों है? एसक्यूएल सर्वर केवल एक उपश्रेणी द्वारा प्रदान किए गए स्केलर मानों के लिए सीधे क्यों नहीं खोज सकता है?

खैर, SQL सर्वर केवल साधारण स्केलर संदर्भों का उपयोग करके 'इंडेक्स सीक' कर सकता है, उदाहरण के लिए एक स्थिर, चर, कॉलम या अभिव्यक्ति संदर्भ (इसलिए एक स्केलर फ़ंक्शन परिणाम भी अर्हता प्राप्त कर सकता है)। एक सबक्वेरी (या अन्य समान निर्माण) स्टोरेज इंजन में धकेलने के लिए बस बहुत जटिल (और संभवतः असुरक्षित) है। इसलिए, अलग क्वेरी प्लान ऑपरेटरों की आवश्यकता होती है। इस मोड़ को सहसंबंध की आवश्यकता होती है, जिसका अर्थ है कि आप जिस तरह की इच्छा रखते हैं, उसकी कोई समानता नहीं है।

सब के सब, वास्तव में कोई बेहतर समाधान वर्तमान में तरीकों की तरह नहीं है जैसे कि वैरिएबल को लुकअप मान असाइन करना और फिर फ़ंक्शन मापदंडों का उपयोग करके एक अलग बयान में।

अब आपके पास विशिष्ट स्थानीय विचार हो सकते हैं जिसका अर्थ है कि वर्ष और महीने के वर्तमान मूल्यों SESSION_CONTEXTको रोकना सार्थक है:

SELECT FGSD.calculated_number, COUNT_BIG(*)
FROM dbo.f_GetSharedData
(
    CONVERT(integer, SESSION_CONTEXT(N'experiment_year')), 
    CONVERT(integer, SESSION_CONTEXT(N'experiment_month'))
) AS FGSD
GROUP BY FGSD.calculated_number;

लेकिन यह वर्कअराउंड की श्रेणी में आता है।

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

लेकिन स्केलर टी-एसक्यूएल कार्यों से सावधान रहें, विशेष रूप से कॉलमस्टोर स्टोरेज के साथ, क्योंकि एक अलग पंक्ति-मोड फ़िल्टर में प्रति-पंक्ति मूल्यांकन किए जाने वाले फ़ंक्शन के साथ समाप्त करना आसान है। यह आमतौर पर काफी पेचीदा होता है कि कितनी बार SQL सर्वर स्केलर का मूल्यांकन करेगा, और बेहतर प्रयास नहीं करेगा।


धन्यवाद, पॉल, महान जवाब! मैंने उपयोग करने के बारे में सोचा था session_contextलेकिन मैं तय करता हूं कि यह मेरे लिए एक विचार है। हालांकि क्या उपयोगी होगा, हो सकता है, कुछ संकेत जो मैं आशावादी को बताने के लिए उपयोग कर सकता हूं कि यह एक साधारण स्केलर संदर्भ की तरह सबक्वेरी का परिणाम होना चाहिए।
रोमन पाकर

8

जहाँ तक मुझे पता है कि योजना आकार जो आप चाहते हैं वह सिर्फ टी-एसक्यूएल के साथ संभव नहीं है। ऐसा लगता है कि आप मूल कार्य आकार (क्वेरी 0 योजना) को अपने कार्यों से उपश्रेणियों के साथ फ़िल्टर किए गए सूचकांक स्कैन के खिलाफ सीधे फ़िल्टर के रूप में लागू करना चाहते हैं। यदि आप स्केलर फ़ंक्शंस के रिटर्न वैल्यूज़ को होल्ड करने के लिए स्थानीय चर का उपयोग नहीं करते हैं तो आपको कभी भी इस तरह की क्वेरी प्लान नहीं मिलेगी। इसके बजाय फ़िल्टरिंग को नेस्टेड लूप के रूप में लागू किया जाएगा। तीन अलग-अलग तरीके हैं (एक समानता के दृष्टिकोण से) जो कि लूप में शामिल हो सकते हैं:

  1. पूरी योजना धारावाहिक है। यह आपको स्वीकार्य नहीं है। यह वह योजना है जो आपको क्वेरी 1 के लिए मिलती है।
  2. पाश सीरियल में रन जोड़ते हैं। मेरा मानना ​​है कि इस मामले में आंतरिक पक्ष समानांतर में चल सकता है, लेकिन इसके लिए किसी भी विधेय को पारित करना संभव नहीं है। इसलिए अधिकांश काम समानांतर में किए जाएंगे, लेकिन आप पूरी तालिका को स्कैन कर रहे हैं और आंशिक रूप से पहले की तुलना में बहुत अधिक महंगा है। यह वह योजना है जो आपको क्वेरी 2 के लिए मिलती है।
  3. लूप समानांतर में चलता है। समानांतर नेस्टेड लूप के साथ सीरियल में लूप के अंदरूनी हिस्से को जोड़ा जाता है, लेकिन आप एक बार भीतर की तरफ चलने वाले डीओपी थ्रेड तक हो सकते हैं। आपके बाहरी परिणाम सेट में सिर्फ एक पंक्ति होगी, इसलिए आपकी समानांतर योजना प्रभावी रूप से धारावाहिक होगी। यह वह योजना है जो आपको क्वेरी 3 के लिए मिलती है।

वे ही संभव योजना आकार हैं जिनसे मैं अवगत हूं। यदि आप एक अस्थायी तालिका का उपयोग करते हैं तो आप कुछ अन्य प्राप्त कर सकते हैं, लेकिन उनमें से कोई भी आपकी मूलभूत समस्या को हल नहीं करता है यदि आप चाहते हैं कि क्वेरी प्रदर्शन केवल उतना ही अच्छा हो जितना कि यह क्वेरी 0 के लिए था।

आप स्थानीय वेरिएबल्स में रिटर्न वैल्यूज़ असाइन करने के लिए स्केलर यूडीएफ का उपयोग करके और अपनी क्वेरी में उन स्थानीय वेरिएबल्स का उपयोग करके बराबर क्वेरी प्रदर्शन प्राप्त कर सकते हैं। आप उस कोड को संग्रहीत कार्यविधि या बहु-स्टेटमेंट UDF में बनाए रख सकते हैं ताकि स्थिरता की समस्या से बचा जा सके। उदाहरण के लिए:

DECLARE @experiment_year int = dbo.fn_GetExperimentYear(@session_id);
DECLARE @experiment_month int = dbo.fn_GetExperimentMonth(@session_id);

select
    calculated_number,
    count(*)
from dbo.f_GetSharedData(@experiment_year, @experiment_month)
group by
    calculated_number;

स्केलर UDFs को क्वेरी के बाहर ले जाया गया है जो आप समानता के लिए योग्य होना चाहते हैं। क्वेरी प्लान जो मुझे मिलता है वह वही है जो आप चाहते हैं:

समानांतर क्वेरी योजना

यदि आपको अन्य प्रश्नों में सेट इस परिणाम का उपयोग करने की आवश्यकता है, तो दोनों दृष्टिकोणों के नुकसान हैं। आप सीधे संग्रहीत प्रक्रिया में शामिल नहीं हो सकते। आपको परिणामों को एक अस्थायी तालिका में सहेजना होगा, जिसमें समस्याओं का अपना सेट है। आप एक MS-TVF में शामिल हो सकते हैं, लेकिन SQL Server 2016 में आप कार्डिनैलिटी का अनुमान लगा सकते हैं। SQL सर्वर 2017 MS-TVF के लिए इंटरलेयड निष्पादन प्रदान करता है जो समस्या को पूरी तरह से हल कर सकता है।

बस कुछ चीजों को साफ करने के लिए: T-SQL स्केलर UDFs हमेशा समानता का निषेध करते हैं और Microsoft ने यह नहीं कहा है कि FROID SQL Server 2017 में उपलब्ध होगा।


SQL 2017 में Froid से संबंधित - मुझे यकीन नहीं है कि मुझे लगा कि यह वहां क्यों है। यह vNext में होने की पुष्टि की जाती है - brentozar.com/archive/2018/01/…
Roman Pekar

4

यह संभवतः SQLCLR का उपयोग करके किया जा सकता है। SQLCLR स्केलर यूडीएफ का एक लाभ यह है कि यदि वे कोई डेटा एक्सेस नहीं करते हैं (और कभी-कभी उन्हें "नियतात्मक" के रूप में भी चिह्नित करने की आवश्यकता होती है) तो वे समानता को नहीं रोकते हैं । तो आप किसी ऐसी चीज़ का उपयोग कैसे करते हैं जिसके लिए कोई डेटा एक्सेस की आवश्यकता नहीं होती है जब ऑपरेशन के लिए डेटा एक्सेस की आवश्यकता होती है?

ठीक है, क्योंकि dbo.Paramsतालिका से उम्मीद की जाती है:

  1. आम तौर पर इसमें कभी भी 2000 से अधिक पंक्तियाँ नहीं होती हैं,
  2. शायद ही कभी संरचना बदलें,
  3. केवल (वर्तमान में) दो INTकॉलम होना चाहिए

यह तीन स्तंभों को कैश करने के लिए संभव है - session_id, experiment_year int, experiment_month- एक स्थिर संग्रह (जैसे एक शब्दकोश, शायद) में, जो आउट-ऑफ-प्रोसेस पॉपुलेटेड है और स्केलर यूडीएफ द्वारा पढ़ा जाता है जो मूल्यों experiment_year intऔर experiment_monthमूल्यों को प्राप्त करते हैं। "आउट-ऑफ-प्रोसेस" से मेरा क्या मतलब है: आपके पास एक पूरी तरह से अलग SQLCLR स्केलर UDF या संग्रहित प्रक्रिया हो सकती है dbo.Paramsजो स्थैतिक संग्रह को आबाद करने के लिए तालिका से डेटा एक्सेस और रीडिंग कर सकती है । उस UDF या Stored Procedure को "वर्ष" और "महीना" मान प्राप्त करने वाले UDF का उपयोग करने से पहले निष्पादित किया जाएगा, इस तरह UDF जो कि "वर्ष" और "माह" मान प्राप्त करते हैं, किसी भी DBD एक्सेस का उपयोग नहीं कर रहे हैं।

यूडीएफ या संग्रहित प्रक्रिया जो डेटा को पढ़ती है, यह देखने के लिए पहले जांच सकती है कि संग्रह में 0 प्रविष्टियां हैं और यदि हां, तो पॉप्युलेट करें, अन्यथा छोड़ दें। आप उस समय का ट्रैक भी रख सकते हैं जो इसे आबादी में रखा गया था और अगर यह एक्स मिनट (या ऐसा कुछ) हुआ है, तो संग्रह में प्रविष्टियां होने पर भी स्पष्ट और फिर से आबाद करें। लेकिन जनसंख्या को रोकने में मदद मिलेगी क्योंकि इसे यह सुनिश्चित करने के लिए अक्सर निष्पादित करने की आवश्यकता होगी कि मूल्यों को प्राप्त करने के लिए यह दो मुख्य यूडीएफ के लिए हमेशा आबादी है।

मुख्य चिंता तब होती है जब SQL सर्वर जो भी कारण के लिए ऐप डोमेन को अनलोड करने का निर्णय लेता है (या इसका उपयोग करके किसी चीज को ट्रिगर किया जाता है DBCC FREESYSTEMCACHE('ALL');)। आप "वर्ष" और "माह" मान प्राप्त करने के लिए "पॉप्युलेट" यूडीएफ या संग्रहीत प्रक्रिया और यूडीएफ के निष्पादन के बीच उस संग्रह को समाप्त करने का जोखिम नहीं उठाना चाहते हैं। जिस स्थिति में आप संग्रह खाली होने पर अपवाद को फेंकने के लिए उन दो यूडीएफ की शुरुआत में चेक कर सकते हैं, क्योंकि यह गलत परिणाम देने की तुलना में सफलतापूर्वक त्रुटि के लिए बेहतर है।

बेशक, ऊपर बताई गई चिंता यह मानती है कि इच्छा को विधानसभा के रूप में चिह्नित करना है SAFE। यदि असेंबली को चिह्नित किया जा सकता है EXTERNAL_ACCESS, तो यह संभव है कि एक स्टैटिक कंस्ट्रक्टर उस विधि को निष्पादित करे जो डेटा को पढ़ता है और संग्रह को पॉप्युलेट करता है, ताकि आपको केवल पंक्तियों को ताज़ा करने के लिए मैन्युअल रूप से निष्पादित करने की आवश्यकता हो, लेकिन वे हमेशा आबाद रहेंगे (क्योंकि स्टैटिक क्लास कंस्ट्रक्टर हमेशा क्लास लोड होने पर चलता है, जो तब होता है जब भी इस क्लास में कोई विधि रीस्टार्ट होने के बाद निष्पादित होती है या ऐप डोमेन अनलोड होता है)। इसके लिए एक नियमित कनेक्शन का उपयोग करना पड़ता है, न कि इन-प्रोसेस कॉनटेक्स्ट कनेक्शन (जो स्थिर कंस्ट्रक्टर के लिए उपलब्ध नहीं है, इसलिए इसकी आवश्यकता है EXTERNAL_ACCESS)।

कृपया ध्यान दें: विधानसभा को चिह्नित करने के लिए आवश्यक नहीं होने के लिए UNSAFE, आपको किसी भी स्थिर वर्ग चर के रूप में चिह्नित करना होगा readonly। इसका मतलब है, बहुत कम से कम, संग्रह। यह कोई समस्या नहीं है क्योंकि रीड-ओनली कलेक्शन में आइटम जोड़े जा सकते हैं या उनसे हटाए जा सकते हैं, उन्हें केवल कंस्ट्रक्टर या प्रारंभिक लोड के बाहर इनिशियलाइज़ नहीं किया जा सकता है। एक्स-मिनट के बाद इसे समाप्त करने के उद्देश्य से संग्रह को लोड किए जाने के समय को ट्रैक करना मुश्किल है क्योंकि एक static readonly DateTimeवर्ग चर को कंस्ट्रक्टर या प्रारंभिक लोड के बाहर नहीं बदला जा सकता है। इस प्रतिबंध के आसपास जाने के लिए, आपको एक स्थिर, केवल पढ़ने के लिए संग्रह का उपयोग करने की आवश्यकता है जिसमें एक भी ऐसा आइटम है जो DateTimeमूल्य है ताकि इसे हटा दिया जा सके और एक ताज़ा पर फिर से जोड़ा जा सके।


पता नहीं क्यों किसी ने इसे नीचा दिखाया। बहुत सामान्य नहीं है, लेकिन मुझे लगता है कि यह मेरे वर्तमान मामले में लागू हो सकता है। मैं शुद्ध एसक्यूएल समाधान रखना पसंद करता हूं, लेकिन मैं निश्चित रूप से इस पर करीब से नज़र
डालूंगा

@RomanPekar यकीन नहीं है, लेकिन वहाँ बहुत से लोग हैं जो SQLCLR विरोधी हैं। और शायद कुछ जो मेरे विरोधी हैं; ;-) किसी भी तरह से, मैं नहीं सोच सकता कि यह समाधान क्यों काम नहीं करेगा। मैं शुद्ध टी-एसक्यूएल के लिए वरीयता को समझता हूं, लेकिन मुझे नहीं पता कि ऐसा कैसे करना है, और यदि कोई प्रतिस्पर्धात्मक जवाब नहीं है, तो शायद कोई और नहीं करता है। मुझे नहीं पता कि स्मृति अनुकूलित तालिकाओं और मूल रूप से संकलित UDFs यहां कोई बेहतर काम करेगी। इसके अलावा, मैंने बस कुछ कार्यान्वयन के नोटों को ध्यान में रखने के लिए एक पैराग्राफ जोड़ा।
सोलोमन रटज़की

1
मुझे इस बात पर पूरा यकीन नहीं है कि readonly staticsSQLCLR में सुरक्षित या बुद्धिमान का उपयोग करना है। बहुत कम मैं इस बारे में आश्वस्त हूं कि readonlyउस संदर्भ प्रकार को बनाकर सिस्टम को मूर्ख बनाना , जिसे आप तब जाकर बदलते हैं । मुझे पूरी इच्छाशक्ति tbh देता है।
पॉल व्हाइट 9

@PaWWhite अंडरस्टूड, और मुझे याद है कि यह निजी वार्तालाप में वर्षों पहले आ रहा था। staticSQL सर्वर में ऐप डोमेन (और इसलिए ऑब्जेक्ट्स) की साझा प्रकृति को देखते हुए , हाँ, दौड़ की स्थिति के लिए जोखिम है। यही कारण है कि मैंने पहली बार ओपी से यह निर्धारित किया था कि यह डेटा न्यूनतम और स्थिर है, और मैंने इस दृष्टिकोण को "शायद ही कभी बदलने" की आवश्यकता के रूप में योग्य बनाया, और जरूरत पड़ने पर ताज़ा करने का साधन दिया। में इस उपयोग के मामले मैं बहुत किसी भी जोखिम अगर नहीं दिख रहा। मुझे डिज़ाइन द्वारा (C #, कोई चर्चा फिर से: SQLCLR) के रूप में आसानी से संग्रह करने की क्षमता को अद्यतन करने की क्षमता के बारे में एक पोस्ट साल पहले मिला था। इसे खोजने का प्रयास करेंगे।
सोलोमन रटज़की

2
कोई ज़रूरत नहीं है, कोई तरीका नहीं है कि आप मुझे आधिकारिक SQL सर्वर प्रलेखन से यह कहकर आराम से लें कि यह ठीक है, जो मुझे यकीन है कि मौजूद नहीं है।
पॉल व्हाइट 9
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.