কেন ASYNC_NETWORK_IO এর জন্য একটি সাধারণ লুপের ফলাফল অপেক্ষা করে?


19

নিম্নলিখিত টি-এসকিউএল আমার মেশিনে এসএসএমএস ভি 17.9 সহ প্রায় 25 সেকেন্ড সময় নেয়:

DECLARE @outer_loop INT = 0,
@big_string_for_u VARCHAR(8000);

SET NOCOUNT ON;

WHILE @outer_loop < 50000000
BEGIN
    SET @big_string_for_u = 'ZZZZZZZZZZ';
    SET @outer_loop = @outer_loop + 1;
END;

এটা 532 MS accumulates ASYNC_NETWORK_IOউভয় অনুযায়ী অপেক্ষা করছে sys.dm_exec_session_wait_statsএবং sys.dm_os_wait_stats। লুপের পুনরাবৃত্তির সংখ্যা বাড়ার সাথে সাথে মোট অপেক্ষার সময় বাড়ে। wait_completedবর্ধিত ইভেন্টটি ব্যবহার করে আমি দেখতে পাচ্ছি যে কয়েকটি ব্যতিক্রমের সাথে প্রতি 43 এমএসে অপেক্ষা প্রায় হয়:

অপেক্ষা টেবিল

তদতিরিক্ত, আমি ASYNC_NETWORK_IOঅপেক্ষা করার আগে উপস্থিত কল স্ট্যাকগুলি পেতে পারি :

sqldk.dll!SOS_DispatcherBase::GetTrack+0x7f6c
sqldk.dll!SOS_Scheduler::PromotePendingTask+0x204
sqldk.dll!SOS_Task::PostWait+0x5f
sqldk.dll!SOS_Scheduler::Suspend+0xb15
sqllang.dll!CSECCNGProvider::GetBCryptHandleFromAlgID+0xf6af
sqllang.dll!CSECCNGProvider::GetBCryptHandleFromAlgID+0xf44c
sqllang.dll!SNIPacketRelease+0xd63
sqllang.dll!SNIPacketRelease+0x2097
sqllang.dll!SNIPacketRelease+0x1f99
sqllang.dll!SNIPacketRelease+0x18fe
sqllang.dll!CAutoExecuteAsContext::Restore+0x52d
sqllang.dll!CSQLSource::Execute+0x151b
sqllang.dll!CSQLSource::Execute+0xe13
sqllang.dll!CSQLSource::Execute+0x474
sqllang.dll!SNIPacketRelease+0x165d
sqllang.dll!CValOdsRow::CValOdsRow+0xa92
sqllang.dll!CValOdsRow::CValOdsRow+0x883
sqldk.dll!ClockHand::Statistic::RecordClockHandStats+0x15d
sqldk.dll!ClockHand::Statistic::RecordClockHandStats+0x638
sqldk.dll!ClockHand::Statistic::RecordClockHandStats+0x2ad
sqldk.dll!SystemThread::MakeMiniSOSThread+0xdf8
sqldk.dll!SystemThread::MakeMiniSOSThread+0xf00
sqldk.dll!SystemThread::MakeMiniSOSThread+0x667
sqldk.dll!SystemThread::MakeMiniSOSThread+0xbb9

অবশেষে, আমি লক্ষ্য করেছি যে এসএসএমএস লুপের সময় আশ্চর্যজনক পরিমাণ সিপিইউ ব্যবহার করে (গড়ে প্রায় অর্ধেক কোর)। এসএসএমএস সেই সময়কালে কী করছে তা আমি বুঝতে অক্ষম unable

ASYNC_NETWORK_IOযখন এসএসএমএসের মাধ্যমে কার্যকর করা হয় তখন একটি সাধারণ লুপ কারণ অপেক্ষা করে? এই ক্যোয়ারী এক্সিকিউশন থেকে ক্লায়েন্টের কাছ থেকে পাওয়া একমাত্র আউটপুট হ'ল "কমান্ডগুলি সফলভাবে সম্পন্ন হয়েছে।" বার্তা।

উত্তর:


31

এর জন্য ডকুমেন্টেশনSET NOCOUNT বলেছেন:

SET NOCOUNT ONDONE_IN_PROCসঞ্চিত পদ্ধতিতে প্রতিটি স্টেটমেন্টের জন্য ক্লায়েন্টকে বার্তা প্রেরণকে বাধা দেয় । সঞ্চিত প্রক্রিয়াগুলির জন্য যেখানে বেশ কয়েকটি স্টেটমেন্ট থাকে যা অনেক বেশি প্রকৃত ডেটা ফেরত দেয় না, বা লেনদেন-এসকিউএল লুপগুলি রয়েছে এমন পদ্ধতির জন্য, সেটিংস একটি উল্লেখযোগ্য পারফরম্যান্স উত্সাহ প্রদান SET NOCOUNTকরতে ONপারে কারণ নেটওয়ার্ক ট্র্যাফিক প্রচুর পরিমাণে হ্রাস পেয়েছে।

আপনি কোনও সঞ্চিত পদ্ধতিতে বিবৃতি চালাচ্ছেন না, সুতরাং এসকিউএল সার্ভার প্রতিটি এসকিউএল স্টেটমেন্টের সমাপ্তির স্থিতি নির্দেশ করতে DONEটোকেন (কোড 0xFD) প্রেরণ করে। এই বার্তাগুলি মুলতুবি করা হয় এবং যখন নেটওয়ার্ক প্যাকেট পূর্ণ থাকে তখন অ্যাসিনক্রোনালি পাঠানো হয়। যখন ক্লায়েন্টটি নেটওয়ার্ক প্যাকেটগুলি দ্রুত পর্যাপ্ত পরিমাণে গ্রাস করে না, অবশেষে বাফারগুলি পূর্ণ হয় এবং অপারেশনটি এসকিউএল সার্ভারের জন্য ব্লক হয়ে যায়, অপেক্ষাগুলি তৈরি করে ASYNC_NETWORK_IO

নোট ডকুমেন্টেশন নোট হিসাবে DONEটোকেনগুলি DONEINPROC(কোড 0xFF) থেকে পৃথক :

  • DONEভেরিয়েবলের ঘোষণা ব্যতীত এসকিউএল ব্যাচে প্রতিটি এসকিউএল স্টেটমেন্টের জন্য একটি টোকেন ফিরিয়ে দেওয়া হয়।

  • সঞ্চিত পদ্ধতিতে এসকিউএল স্টেটমেন্ট কার্যকর করার জন্য DONEPROCএবং DONEINPROCটোকেনের জায়গায় DONEটোকেন ব্যবহার করা হয় ।

আপনি ASYNC_NETWORK_IOঅপেক্ষা করতে নাটকীয় হ্রাস দেখতে পাবেন :

CREATE PROCEDURE #P AS
SET NOCOUNT ON;

DECLARE
    @outer_loop integer = 0,
    @big_string_for_u varchar(8000);


WHILE @outer_loop < 5000000
BEGIN
    SET @big_string_for_u = 'ZZZZZZZZZZ';
    SET @outer_loop = @outer_loop + 1;
END;
GO
EXECUTE dbo.#P;

আপনি sys.sp_executesqlএকই ফলাফল অর্জন করতে ব্যবহার করতে পারেন ।

উদাহরণস্বরূপ স্ট্যাক ট্রেস যেমন ASYNC_NETWORK_IOঅপেক্ষা শুরু হয়:

একটি প্যাকেট প্রেরণ

ইনডল ফাংশনে দেখা টিডিএস প্যাকেটের একটি উদাহরণ sqllang!srv_completioncode_ex<1>নিম্নলিখিত 13 বাইট রয়েছে:

fd 01 00 c1 00 01 00 00 00 00 00 00 00          

যা ডিকোড করে:

  • টোকেনটাইপ = 0xfd DONE_TOKEN
  • স্থিতি = 0x0001 DONE_MORE
  • কারCmd = 0x00c1 (193)
  • সম্পন্নRowCount = 0x00000001 (1)

শেষ পর্যন্ত, ASYNC_NETWORK_IOঅপেক্ষার সংখ্যা ক্লায়েন্ট এবং ড্রাইভারের উপর নির্ভর করে এবং সমস্ত DONEবার্তাগুলি সহ এটি যদি কিছু করে তবে কী করে । প্রশ্নে প্রদত্ত আকারের লুপ 1/10 তম (5,000,000 লুপ পুনরাবৃত্তি) দিয়ে পরীক্ষা করে আমি দেখতে পেয়েছি যে এসএসএমএস প্রায় 200 সেকেন্ডের জন্য 200-300 এমএস অপেক্ষা করে চলেছে। sqlcmdএকক অঙ্কের এমএস অপেক্ষা নিয়ে 2-3 সেকেন্ডের জন্য দৌড়ে; osqlপ্রায় 10 এমএস ওয়েট সহ একই রান টাইমের চারপাশে।

এই পরীক্ষার জন্য এখনও পর্যন্ত সবচেয়ে খারাপ ক্লায়েন্টটি ছিল অ্যাজুরে ডেটা স্টুডিও। এটি প্রায় 6 ঘন্টা চলছিল:

বিজ্ঞাপন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.