मुझे एसक्यूएल कॉल का उपयोग करते समय मुख्य एसक्यूएल प्रदर्शन समस्याएं हैं। मैंने समस्या को प्रदर्शित करने के लिए एक छोटा सा मामला बनाया है।
मैंने SQL Server 2016 पर एक डेटाबेस बनाया है जो हमारे LAN में रहता है (इसलिए लोकलडीबी नहीं है)।
उस डेटाबेस में, मेरे पास WorkingCopy
2 कॉलम वाली एक तालिका है :
Id (nvarchar(255, PK))
Value (nvarchar(max))
DDL
CREATE TABLE [dbo].[Workingcopy]
(
[Id] [nvarchar](255) NOT NULL,
[Value] [nvarchar](max) NULL,
CONSTRAINT [PK_Workingcopy]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
उस तालिका में, मैंने एक भी रिकॉर्ड डाला है ( id
= 'PerfUnitTest', 1.5mb Value
स्ट्रिंग (बड़ा JSON डेटासेट का ज़िप))।
अब, यदि मैं SSMS में क्वेरी निष्पादित करता हूं:
SELECT [Value]
FROM [Workingcopy]
WHERE id = 'perfunittest'
मुझे तुरंत परिणाम मिलता है, और मैं SQL Servre Profiler में देखता हूं कि निष्पादन का समय लगभग 20 मिलीसेकंड था। सभी सामान्य।
.NET का उपयोग करते हुए क्वेरी को निष्पादित करते समय (4.6) कोड एक सादे का उपयोग कर SqlConnection
:
// at this point, the connection is already open
var command = new SqlCommand($"SELECT Value FROM WorkingCopy WHERE Id = @Id", _connection);
command.Parameters.Add("@Id", SqlDbType.NVarChar, 255).Value = key;
string value = command.ExecuteScalar() as string;
इसके लिए निष्पादन का समय भी लगभग 20-30 मिलीसेकंड है।
लेकिन जब इसे बदलकर async कोड:
string value = await command.ExecuteScalarAsync() as string;
निष्पादन का समय अचानक 1800 एमएस है ! SQL सर्वर प्रोफाइलर में भी, मैं देखता हूं कि क्वेरी निष्पादन की अवधि एक सेकंड से अधिक है। हालाँकि प्रोफाइलर द्वारा बताई गई निष्पादित क्वेरी बिल्कुल गैर-एस्किंक संस्करण के समान है।
लेकिन यह बदतर हो जाता है। यदि मैं कनेक्शन स्ट्रिंग में पैकेट के आकार के साथ खेलता हूं, तो मुझे निम्नलिखित परिणाम मिलते हैं:
पैकेट का आकार 32768: [समय]: SqlValueStore में ExecuteScalarAsync -> बीता हुआ समय: 450 मि।
पैकेट का आकार 4096: [समय]: SqlValueStore में ExecuteScalarAsync -> बीता हुआ समय: 3667 एमएस
पैकेट का आकार 512: [समय]: SqlValueStore में ExecuteScalarAsync -> बीता हुआ समय: 30776 एमएस
30,000 एमएस !! यह नॉन-एसिक्स संस्करण की तुलना में 1000x से अधिक धीमा है। और SQL सर्वर प्रोफाइलर रिपोर्ट करता है कि क्वेरी निष्पादन 10 सेकंड से अधिक समय लगा। यह भी स्पष्ट नहीं है कि अन्य 20 सेकंड कहाँ गए हैं!
फिर मैंने सिंक संस्करण पर वापस स्विच किया और पैकेट के आकार के साथ भी खेला, और हालांकि इसने निष्पादन के समय को थोड़ा प्रभावित किया, यह async संस्करण के साथ नाटकीय रूप में कहीं नहीं था।
एक सिडेनोट के रूप में, अगर यह मूल्य में सिर्फ एक छोटी स्ट्रिंग (<100bytes) डालता है, तो async क्वेरी निष्पादन सिंक संस्करण (परिणाम 1 या 2 एमएस में) के समान तेज़ है।
मैं वास्तव में इससे बहुत प्रभावित हुआ हूँ, खासकर जब से मैं SqlConnection
एक ORM भी नहीं बना रहा हूँ । इसके अलावा जब आसपास खोज की, तो मुझे कुछ भी नहीं मिला जो इस व्यवहार की व्याख्या कर सके। कोई विचार?
GetSqlChars
या GetSqlBinary
उन्हें पुनः प्राप्त करने के लिए। इन्हें स्टोरस्ट्राम डेटा के रूप में संग्रहीत करने पर भी विचार करें - तालिका के डेटा पृष्ठ में 1.5MB डेटा सहेजने का कोई कारण नहीं है