database_scoped_configurations में बग


9

मैं परिणाम सेट को सम्मिलित करने का प्रयास कर रहा हूं:

SELECT * FROM sys.database_scoped_configurations

एक अस्थायी तालिका में, क्योंकि मैं अपने सर्वर पर सभी डेटाबेस के लिए सेटिंग्स की जांच करना चाहता हूं। इसलिए मैंने यह कोड लिखा:

DROP TABLE IF EXISTS #h
CREATE TABLE #h(dbname sysname, configuration_id INT, name sysname,     value SQL_VARIANT,  value_for_secondary SQL_VARIANT)
EXEC sys.sp_MSforeachdb 'USE ?; insert into #h(dbname, configuration_id, name, value,value_for_secondary)  SELECT ''?'' as dbname, * FROM sys.database_scoped_configurations  D'
SELECT * FROM #h H

लेकिन फिर वहाँ केवल डेटाबेस प्रति एक पंक्ति, नहीं होगा चार पंक्तियों कि मैं प्रत्येक डेटाबेस में एक सादे चयन चलने से उम्मीद करते हैं।

मुझे पता है कि sp_MSForEachDB का उपयोग करने की तुलना में इसे कोड करने के लिए बेहतर तरीके हैं, और मैंने कई प्रयास किए। लेकिन मुझे अभी भी प्रति डेटाबेस केवल एक पंक्ति मिलती है। मैंने इसे SQL Server 2016 RTM और SP1 दोनों पर आज़माया है

यह SQL Server 2016 के साथ एक बग है, या मैं कुछ गलत कर रहा हूं?


बग को ठीक कर दिया गया है, कम से कम Microsoft SQL Server 2017 (RTM-CU15-GDR) में
हेनरिक स्टॉन पॉल्सेन

जवाबों:


8

यह SQL Server 2016 के साथ एक बग है?

हाँ। निश्चित रूप से यह सही व्यवहार नहीं है। मैंने इसे यहां रिपोर्ट किया है और यह SQL Server 2016 SP2 CU9 में तय किया गया है

जैसा कि मिकेल एरिकसन टिप्पणियों में कहते हैं sys.database_scoped_configurationsऔर sys.dm_exec_sessionsप्रारूप में विचारों के रूप में कार्यान्वित किए जाते हैं

SELECT ...  
FROM OpenRowset(TABLE xxxx)  

हालांकि नीचे दो योजनाओं की तुलना करना एक स्पष्ट अंतर है।

DBCC TRACEON(3604);

DECLARE @database_scoped_configurations TABLE(x INT);

INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM   sys.database_scoped_configurations
OPTION (QUERYTRACEON 8608, QUERYTRACEON 8615, QUERYTRACEON 8619, QUERYTRACEON 8620 );


DECLARE @dm_exec_sessions TABLE(x INT);

INSERT INTO @dm_exec_sessions
SELECT session_id
FROM   sys.dm_exec_sessions
OPTION (QUERYTRACEON 8608, QUERYTRACEON 8615, QUERYTRACEON 8619, QUERYTRACEON 8620 );

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

इन दोनों प्रश्नों के लिए ट्रेस ध्वज 8619 आउटपुट दिखाता है

नियम लागू करें: EnforceHandAccCard - x0-> स्पूल या टॉप (x0)

SQL सर्वर स्पष्ट रूप से यह पता लगाने में सक्षम नहीं है कि TVF के लिए स्रोत भी सम्मिलित लक्ष्य नहीं है, इसलिए इसे हेलोवीन सुरक्षा की आवश्यकता होती है।

सत्र मामले में इसे एक स्पूल के रूप में लागू किया गया था जो पहले सभी पंक्तियों को कैप्चर करता है। में database_scoped_configurationsएक जोड़कर TOP 1योजना के लिए। TOPहैलोवीन सुरक्षा के लिए उपयोग इस लेख में चर्चा की गई है । इस लेख में एक अनछुए ट्रेस ध्वज का भी उल्लेख किया गया है जो अपेक्षा के TOPअनुसार काम करने के बजाय एक स्पूल को बाध्य करने के लिए है।

DECLARE @database_scoped_configurations TABLE(x INT);

INSERT INTO @database_scoped_configurations
SELECT configuration_id
FROM   sys.database_scoped_configurations
OPTION (QUERYTRACEON 8692)

TOP 1स्पूल के बजाय उपयोग के साथ एक स्पष्ट समस्या यह है कि यह मनमाने ढंग से डाली गई पंक्तियों की संख्या को सीमित करेगा। तो यह केवल तभी मान्य होगा जब फ़ंक्शन द्वारा दी गई पंक्तियों की संख्या <= 1 थी।

प्रारंभिक ज्ञापन इस तरह दिखता है

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

क्वेरी 2 के लिए प्रारंभिक ज्ञापन के साथ इसकी तुलना करें

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

यदि मैं उपरोक्त को सही ढंग से समझता हूं तो यह सोचता है कि पहला टीवीएफ अधिकतम एक पंक्ति में वापस आ सकता है और इसलिए एक गलत अनुकूलन लागू करता है। दूसरी क्वेरी के लिए अधिकतम 1.34078E+154( 2^512) पर सेट है ।

मुझे नहीं पता कि यह अधिकतम उपद्रव कहां से हुआ है। शायद DMV के लेखक द्वारा आपूर्ति की गई मेटाडेटा? यह भी अजीब है कि TOP(50)वैकल्पिक हल के लिए फिर से लिखा नहीं होता है TOP(1)क्योंकि TOP(50)हेलोवीन मुद्दा बंद नहीं होंगे होने से (हालांकि यह अनिश्चित काल के लिए जारी बंद कर देंगे)


6

कृपया उपयोग करना बंद करें sp_MSForEachDB। यह असमर्थित, अनिर्दिष्ट है, और यह छोटी गाड़ी है - जो यहाँ समस्या हो सकती है। मेरा प्रतिस्थापन एक ही समस्या को यहाँ प्रदर्शित करता है, लेकिन सामान्य तौर पर यह उपयोग करने के लिए एक सुरक्षित चीज है।

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

अवलोकन से उधार लेना कि सिस्टम को देखने वाले कोड को लागू करता है a TOP (1), हम इस तरह से कोशिश कर सकते हैं:

DROP TABLE IF EXISTS #h;

CREATE TABLE #h(dbname sysname, configuration_id INT, name sysname, 
  value SQL_VARIANT,  value_for_secondary SQL_VARIANT);

DECLARE @sql nvarchar(max) = N'', @base nvarchar(max) = N'insert into #h
  (dbname, configuration_id, name, value,value_for_secondary)  SELECT TOP ($c$) 
  $db$ as dbname, * FROM $qdb$.sys.database_scoped_configurations;';

SELECT @sql += REPLACE(REPLACE(REPLACE(@base, N'$qdb$', QUOTENAME(name)), 
  N'$db$', CHAR(39) + name + CHAR(39)), N'$c$', RTRIM(COUNT(*) OVER()))
FROM sys.databases WHERE state = 0;

PRINT @sql;
EXEC sys.sp_executesql @sql;
SELECT * FROM #h;

ध्यान दें कि मैं USEयहाँ उपयोग नहीं करता , बल्कि sysडेटाबेस नाम के साथ कैटलॉग दृश्य को उपसर्ग करता हूँ ।

क्यों दृश्य जादुई तरीकों से काम करता है, मुझे नहीं पता; मुझे नहीं पता कि आपको यहां एक अच्छा जवाब मिलेगा, क्योंकि इसके लिए Microsoft से टिप्पणियों की आवश्यकता होती है (या स्रोत कोड तक पहुंच वाले किसी व्यक्ति या डीबगर को आग लगाने के लिए तैयार)।


मैंने जिन कई तरीकों की कोशिश की, उनमें से पहला था, लेकिन मुझे नहीं लगा कि मैं उदाहरण में उस स्पोक का उपयोग कर सकता हूं।
हेनरिक स्टॉउन पॉल्सन

6

इस विषय पर जानकारी देने के लिए धन्यवाद!

यह वास्तव में एक बग है जिसमें क्वेरी ऑप्टिमाइज़र sys.database_scoped_configurationsकैटलॉग दृश्य के लिए एक योजना बनाता है । हम इसे SQL Server 2016 के अगले अपडेट और Azure SQL डेटाबेस में से एक पर संबोधित करेंगे।

वर्कअराउंड के रूप में, आप सही प्लान प्राप्त करने के लिए अपने इंसर्ट TOPके SELECTहिस्से पर एक क्लॉज जोड़ सकते हैं , जैसे:

DECLARE @database_scoped_configurations TABLE(x INT); 
INSERT INTO @database_scoped_configurations 
SELECT **TOP 100** configuration_id 
FROM sys.database_scoped_configurations 

3

मैं मानता हूं कि यह बहुत ही अजीब और संभावित बग है, लेकिन उदाहरण के लिए एक शीर्ष (50) को जोड़ना, आपके चयन के लिए वास्तव में सभी पंक्तियों को वापस करता है, ताकि कम से कम आपको मिल रहा हो। परिणाम एक सिस्टम टेबल वैल्यू फंक्शन ([DB_SCOPED_CONFIG]) से आ रहा है, इसलिए मैं वास्तव में नहीं बता सकता कि क्या चल रहा है।

मैं इस धागे पर कोई नजर रख रहा हूं कि क्या 'होशियार' लोग जानते हैं कि ऐसा क्यों हो रहा है।


क्या आपको प्रत्येक डेटाबेस के लिए केवल MAXDOP पंक्ति मिलती है?
डैन गुज़मैन

@DanGuzman - हाँ स्वयं का चयन केवल ठीक काम करता है (बिना किसी फ़ॉरेस्ट सामान के, केवल एक डेटाबेस पर)। जब आप सम्मिलित होते हैं, तो यह अजीब व्यवहार पैदा करता है
स्कॉट होडगिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.