এসইটি অপারেশনে অংশ নিতে পারে এমন স্থানীয় ভেরিয়েবলের সর্বাধিক সংখ্যা কত?


11

আমার কাছে একটি সঞ্চিত প্রক্রিয়া রয়েছে যাতে ব্যবসায়িক যুক্তি রয়েছে। এর ভিতরে আমার প্রায় 1609 ভেরিয়েবল রয়েছে (আমাকে জিজ্ঞাসা করবেন না কেন, ইঞ্জিন এভাবে কাজ করে)। আমি SETঅন্যান্য সমস্ত ভেরিয়েবলের সংমিশ্রিত মানের সাথে একটি ভেরিয়েবলের চেষ্টা করি । সৃষ্টির ফলস্বরূপ আমি ত্রুটিটি পেয়েছি:

এমএসজি 8631, স্তর 17, রাজ্য 1, পদ্ধতি XXX, লাইন ওয়াইওয়াই অভ্যন্তরীণ ত্রুটি: সার্ভার স্ট্যাকের সীমাটি পৌঁছে গেছে। আপনার ক্যোয়ারিতে সম্ভাব্য গভীর নেস্টিংয়ের সন্ধান করুন এবং এটিকে সহজ করার চেষ্টা করুন।

আমি বুঝতে পেরেছি যে ত্রুটিটি SETঅপারেশনটিতে আমার প্রয়োজনীয় ভেরিয়েবলগুলির সংখ্যার কারণে । দু'ভাগে বিভক্ত হয়ে আমি কার্য সম্পাদন করতে পারি।

আমার প্রশ্ন এই এলাকায় কিছু বিধিনিষেধ আছে? আমি চেক করেছিলাম, কিন্তু আমি কিছু পাইনি।

আমরা এই কেবিতে বর্ণিত ত্রুটিটি পরীক্ষা করেছি , তবে এটি আমাদের ক্ষেত্রে নয়। আমরা CASEআমাদের কোডের মধ্যে কোনও অভিব্যক্তি ব্যবহার করি না । আমরা সিএলআর ফাংশন ব্যবহার করে প্রতিস্থাপন করতে হবে এমন মানগুলির একটি তালিকা প্রস্তুত করতে সেই অস্থায়ী পরিবর্তনশীলটি ব্যবহার করি। আমরা আমাদের এসকিউএল সার্ভারকে এসপি 3 সিইউ 6 তে আপডেট করেছি (সর্বশেষ আপডেটে) তবে আমরা ত্রুটিটি এখনও অনুভব করি the

উত্তর:


16

এমএসজি 8631, স্তর 17, রাজ্য 1, লাইন xxx
অভ্যন্তরীণ ত্রুটি: সার্ভার স্ট্যাকের সীমাটি পৌঁছে গেছে।
আপনার ক্যোয়ারিতে সম্ভাব্য গভীর নেস্টিংয়ের সন্ধান করুন এবং এটিকে সহজ করার চেষ্টা করুন।

এই ত্রুটিটি দীর্ঘ SETএবং SELECTপরিবর্তনশীল অ্যাসাইনমেন্ট কনটেনটেশন তালিকার সাথে ঘটে যে কারণে এসকিউএল সার্ভার এই ধরণের বিবৃতি পার্স করে এবং বেঁধে রাখে - দ্বি-ইনপুট সংক্ষেপণের নেস্টেড তালিকা হিসাবে।

উদাহরণস্বরূপ, SET @V = @W + @X + @Y + @Zফর্মের একটি গাছে আবদ্ধ:

ScaOp_Arithmetic x_aopAdd
    ScaOp_Arithmetic x_aopAdd
        ScaOp_Arithmetic x_aopAdd
            ScaOp_Identifier @W 
            ScaOp_Identifier @X 
        ScaOp_Identifier @Y 
    ScaOp_Identifier @Z 

প্রথম দুটিয়ের পরে প্রতিটি সংক্ষিপ্ত উপাদান এই প্রতিনিধিত্ব করে বাড়তি বাসা বাঁধে in

এসকিউএল সার্ভারে যে পরিমাণ স্ট্যাক স্পেস উপলব্ধ রয়েছে তা এই নীড়ের চূড়ান্ত সীমাটি নির্ধারণ করে। সীমা অতিক্রম করা হলে, অভ্যন্তরীণভাবে একটি ব্যতিক্রম উত্থাপিত হয়, যা পরিণামে উপরে প্রদর্শিত ত্রুটি বার্তায় ফলাফল দেয়। ত্রুটি নিক্ষিপ্ত হলে কল স্ট্যাকের একটি উদাহরণ প্রক্রিয়া নীচে দেখানো হয়:

স্ট্যাক ট্রেস

Repro

DECLARE @SQL varchar(max);

SET @SQL = '
    DECLARE @S integer, @A integer = 1; 
    SET @S = @A'; -- Change to SELECT if you like

SET @SQL += REPLICATE(CONVERT(varchar(max), ' + @A'), 3410) +';'; -- Change the number 3410

-- SET @S = @A + @A + @A...
EXECUTE (@SQL);

অভ্যন্তরীণভাবে একাধিক কনটেস্টেশন পরিচালনা করার কারণে এটি একটি মৌলিক সীমা। এটা তোলে প্রভাবিত SETএবং SELECTপরিবর্তনশীল নিয়োগ বিবৃতি সমানভাবে।

কর্মসংস্থানটি হ'ল একক বিবৃতিতে সম্পাদিত সংক্ষেপণের সংখ্যা সীমাবদ্ধ করা। এটি সাধারণত আরও দক্ষ হবে, যেহেতু গভীর কোয়েরি গাছ সংকলন করা সম্পদ-নিবিড়।


5

দ্বারা অনুপ্রাণিত @Paul এর উত্তর , আমি কিছু গবেষণা করেছেন এবং দেখা গেছে যে এটা সত্য যে স্ট্যাকের স্থান সীমা concatenations সংখ্যা আছে, যখন এবং যে স্ট্যাকের স্থান উপলব্ধ মেমরি একটি ফাংশন এবং এইভাবে পরিবর্তিত হয়, নিম্নলিখিত দুই পয়েন্ট এছাড়াও সত্য :

  1. একটি একক বিবৃতিতে অতিরিক্ত যুক্তি ছড়িয়ে দেওয়ার একটি উপায় রয়েছে, এবং
  2. প্রাথমিক স্ট্যাক স্পেস সীমাবদ্ধতা অতিক্রম করার জন্য এই পদ্ধতিটি ব্যবহার করে, একটি আসল যৌক্তিক সীমা (এটি ভিন্ন হয় বলে মনে হয় না) পাওয়া যেতে পারে

প্রথমত, আমি পলের পরীক্ষার কোডটি স্ট্রিংকে সংযুক্ত করার জন্য রূপান্তর করেছি:

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = N'
    DECLARE @S VARCHAR(MAX), @A VARCHAR(MAX) = ''a''; 
    SET @S = @A';

SET @SQL += REPLICATE(CONVERT(NVARCHAR(MAX), N' + @A'), 3312) + N';';

-- SET @S = @A + @A + @A...
SET @SQL += N'SELECT DATALENGTH(@S) AS [Chars In @S];';
EXECUTE (@SQL);

এই পরীক্ষার মাধ্যমে, আমার অ-দুর্দান্ত-ল্যাপটপ চালানোর সময় আমি যে সর্বোচ্চটি পেতে পারি (কেবলমাত্র 6 গিগাবাইট র‌্যাম) ছিল:

  • 3311 (এসসিএল সার্ভার 2017 এক্সপ্রেস সংস্করণ লোকালডিবি (14.0.3006) ব্যবহার করে 3312 মোট অক্ষর প্রদান করে)
  • 3512 (এসকিউএল সার্ভার 2012 বিকাশকারী সংস্করণ এসপি 4 (কেবি 4018073) (11.0.7001) ব্যবহার করে 3513 মোট অক্ষর প্রদান করে)

ত্রুটি পাওয়ার আগে 8631

এরপরে, আমি প্রথম বন্ধনী ব্যবহার করে কনটেটেশনগুলি গোষ্ঠীভুক্ত করার চেষ্টা করেছি যাতে এই ক্রিয়াকলাপটি একাধিক গোষ্ঠীর সংক্ষেপণকে বোঝায়। উদাহরণ স্বরূপ:

SET @S = (@A + @A + @A + @A) + (@A + @A + @A + @A) + (@A + @A + @A + @A);

এটি করে আমি 3312 এবং 3513 ভেরিয়েবলের আগের সীমা ছাড়িয়ে ভালভাবে যেতে পেরেছিলাম। আপডেট করা কোডটি হ'ল:

DECLARE @SQL VARCHAR(MAX), @Chunk VARCHAR(MAX);

SET @SQL = '
    DECLARE @S VARCHAR(MAX), @A VARCHAR(MAX) = ''a''; 
    SET @S = (@A+@A)';

SET @Chunk = ' + (@A' + REPLICATE(CONVERT(VARCHAR(MAX), '+@A'), 42) + ')';

SET @SQL += REPLICATE(CONVERT(VARCHAR(MAX), @Chunk), 762) + ';';

SET @SQL += 'SELECT DATALENGTH(@S) AS [Chars In @S];';

-- PRINT @SQL; -- for debug

-- SET @S = (@A+@A) + (@A + @A...) + ...
EXECUTE (@SQL);

সর্বাধিক মানগুলি (আমার জন্য) এখন 42প্রথমটির জন্য ব্যবহার করতে হবে REPLICATE, এইভাবে প্রতি গ্রুপে ৪৩ টি ভেরিয়েবল ব্যবহার করা হবে এবং তারপরে 762দ্বিতীয়টির জন্য ব্যবহার করা হবে REPLICATE, এভাবে প্রতিটি ৪৩ টি ভেরিয়েবলের 6262২ টি গ্রুপ ব্যবহার করা হবে। প্রাথমিক গ্রুপটি দুটি ভেরিয়েবলের সাথে হার্ড-কোডড।

আউটপুট এখন দেখায় যে চলকটিতে 32,768 টি অক্ষর রয়েছে @S। আমি যদি প্রাথমিক গোষ্ঠীকে ন্যায়বিচারের (@A+@A+@A)পরিবর্তে আপডেট করে থাকি (@A+@A)তবে আমি নিম্নলিখিত ত্রুটিটি পেয়েছি:

এমএসজি 8632, স্তর 17, রাজ্য 2, লাইন এক্সএক্সএক্সএক্সএক্স
অভ্যন্তরীণ ত্রুটি: একটি এক্সপ্রেশন পরিষেবা সীমাতে পৌঁছে গেছে। আপনার ক্যোয়ারিতে সম্ভাব্য জটিল এক্সপ্রেশনগুলি সন্ধান করুন এবং সেগুলি সরল করার চেষ্টা করুন।

লক্ষ্য করুন যে ত্রুটি সংখ্যাটি আগের চেয়ে পৃথক। এটি এখন: 8632 । এবং, আমি আমার এসকিউএল সার্ভার 2012 উদাহরণটি বা এসকিউএল সার্ভার 2017 উদাহরণটি ব্যবহার করি কিনা তাতেই আমার এই সীমাবদ্ধতা রয়েছে।

এটা সম্ভবত কোন কাকতালীয় যে উপরের সীমা এখানে - 32.768 - সর্বোচ্চ ধারণক্ষমতা এর SMALLINT( Int16.NET মধ্যে) যদি থেকে শুরু 0(সর্বোচ্চ মান 32.767 কিন্তু অনেক / বেশীর ভাগ প্রোগ্রামিং ভাষায় অ্যারে 0-ভিত্তিক)।


0

এখন, অন্য কথায় এটি কেবল মেমরির বাইরে চলে যায়, কারণ মেমরিতে ব্যবহৃত স্টোরেজ পদ্ধতির অপারেশন এবং এসকিউএল-তে উপলব্ধ হার্ডওয়্যার ট্রানজিস্টর বা ভার্চুয়াল পৃষ্ঠা মেমরিটি পূর্ণ!

সুতরাং এটি মূলত এসকিউএল সার্ভারে স্ট্যাক ওভারফ্লো।

এখন, প্রথমে প্রক্রিয়াটি সহজ করার চেষ্টা করুন, কারণ আমরা জানি আপনার 1609 ভেরিয়েবলগুলি দরকার,

তবে আপনার কি একই সাথে সমস্ত ভেরিয়েবলের প্রয়োজন?

যেখানে প্রয়োজন সেখানে আমরা ভেরিয়েবলগুলি ঘোষণা করতে এবং ব্যবহার করতে পারি।

উদাহরণ স্বরূপ:

Declare @var1 int, @Var2 int @Var3 int, .... , @var1000 int; -- Here assume Thousand Variables are declared

Declare @Tot Int;
SET @Tot = 0;
if(True)
Begin
    SET @TOT = @TOT+ VAR1 + VAR2 + .... + VAR1000; -- This might fail; 
End

আমরা যদি যোগ করে একটি লুপে এটি চেষ্টা করি

Declare @Tot Int;
SET @Tot = 0;
DECLARE @i int, @Count int;
SET @i = 1;
SET @Count = 1609;
WHILE (@i <= @Count)
BEGIN
   DECLARE @SQL NVARCHAR(128);
   SET @SQL = 'SET @TOT = @TOT+ VAR'+ cast(@i as nvarchar);
   EXEC (@SQL);
   SET @i = @i + 1;
END

দ্রষ্টব্য: এটি আরও সিপিইউ ব্যবহার করবে এবং গণনায় কিছুটা বেশি সময় নেবে।

এখন এটি ধীর হবে তবে কম স্মৃতি ব্যবহারের সুবিধা পাবেন।

আমি আশা করি এটি সাহায্য করে, দয়া করে আপনার ক্যোয়ারী পোস্ট করুন যাতে আমরা সঠিক পরিস্থিতি বুঝতে পারি।


-4

SET এর পরিবর্তে SELECT স্টেটমেন্ট ব্যবহার করা পারফরম্যান্স এবং পাঠযোগ্যতার উন্নতি করতে পারে এবং আপনাকে বর্ণিত ত্রুটির আশপাশে পেতে পারে। এর পরিবর্তে:

SET @a = 1
SET @b = 2
SET @c = @e + 2*@d

আপনি করতে পারেন:

SELECT @a = 1, @b = 2, @c = @e + 2 * @d

এবং একটি বিবৃতিতে তিনটি মান সেট করুন।

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