লুপ চলাকালীন কি সুস্পষ্ট লেনদেনের প্রয়োজন?


11

এসকিউএল সার্ভার 2014:

আমাদের একটি খুব বড় (100 মিলিয়ন সারি) টেবিল রয়েছে এবং এটিতে আমাদের কয়েকটি ক্ষেত্র আপডেট করতে হবে।

লগ শিপিং ইত্যাদির জন্য আমরা অবশ্যই স্পষ্টতই এটিকে কাটা-আকারের লেনদেনের মধ্যে রাখতে চাই।

যদি আমরা নীচের অংশটি কিছুটা চালিয়ে যেতে পারি, এবং তারপরে কোয়েরিটি বাতিল / বন্ধ করে দিই, তাহলে এখন পর্যন্ত করা কাজটি কি সমস্ত প্রতিশ্রুতিবদ্ধ হবে, বা আমাদের কী স্পষ্টত শুরু করা যেতে হবে BEGIN Transferences / End Transferences বিবৃতি যাতে আমরা যে কোনও সময় বাতিল করতে পারি?

DECLARE @CHUNK_SIZE int
SET @CHUNK_SIZE = 10000

UPDATE TOP(@CHUNK_SIZE) [huge-table] set deleted = 0, deletedDate = '2000-01-01'
where deleted is null or deletedDate is null

WHILE @@ROWCOUNT > 0
BEGIN
    UPDATE TOP(@CHUNK_SIZE) [huge-table] set deleted = 0, deletedDate = '2000-01-01'
    where deleted is null or deletedDate is null
END

উত্তর:


13

পৃথক বিবৃতি - ডিএমএল, ডিডিএল, ইত্যাদি - নিজের মধ্যে লেনদেন। সুতরাং হ্যাঁ, লুপের প্রতিটি পুনরাবৃত্তির পরে (প্রযুক্তিগতভাবে: প্রতিটি বিবৃতি দেওয়ার পরে), যা কিছু UPDATEবিবৃতি পরিবর্তিত হয়েছিল তা স্বয়ংক্রিয়ভাবে প্রতিশ্রুতিবদ্ধ।

অবশ্যই, সবসময় একটি ব্যতিক্রম আছে, তাই না? SET IMPLICIT_TRANSACTIONS এর মাধ্যমে অন্তর্নিহিত লেনদেনগুলি সক্ষম করা সম্ভব , যার ক্ষেত্রে প্রথম UPDATEবিবৃতিটি আপনাকে COMMITবা ROLLBACKশেষে থাকতে হবে এমন কোনও লেনদেন শুরু করে । এটি একটি সেশন স্তর সেটিং যা বেশিরভাগ ক্ষেত্রে ডিফল্টরূপে বন্ধ থাকে।

আমাদের যে কোনও সময় বাতিল করতে পারি সেজন্য স্পষ্টভাবে শুরু হওয়া শুরু / ট্রান্সএকশন বিবৃতি যুক্ত করার দরকার আছে?

না এবং প্রকৃতপক্ষে, আপনি প্রক্রিয়াটি থামাতে এবং পুনরায় চালু করতে সক্ষম হতে চাইলে, একটি স্পষ্ট লেনদেন (বা ইম্পিলিটি লেনদেনগুলি সক্ষম করা) যুক্ত করা একটি খারাপ ধারণা হবে কারণ প্রক্রিয়াটি থামানো আগে এটি আটকাতে পারে COMMITCOMMITসেক্ষেত্রে আপনাকে ম্যানুয়ালি ইস্যু করতে হবে (আপনি যদি এসএসএমএসে থাকেন), বা আপনি যদি এসকিউএল এজেন্ট কাজ থেকে এটি চালাচ্ছেন তবে আপনার সেই সুযোগ নেই এবং অনাথ লেনদেন শেষ হতে পারে।


এছাড়াও, আপনি @CHUNK_SIZEএকটি কম সংখ্যায় সেট করতে চাইবেন । লক বৃদ্ধি সাধারণত একটি একক বস্তুতে অর্জিত 5000 লকগুলিতে হয়। সারিগুলির আকারের উপর নির্ভর করে এবং যদি এটি পৃষ্ঠা লকগুলিতে সারি লকগুলি করে, আপনি সম্ভবত এই সীমাটি অতিক্রম করবেন। যদি কোনও সারিটির আকার এমন হয় যে প্রতি পৃষ্ঠায় কেবল 1 বা 2 টি সারি ফিট হয় তবে আপনি পৃষ্ঠা লকগুলি করে থাকলেও আপনি সর্বদা এটি হিট করছেন।

যদি টেবিলটি বিভক্ত হয় তবে আপনার কাছে টেবিলটির জন্য LOCK_ESCALATIONবিকল্পটি (এসকিউএল সার্ভার ২০০৮ এ প্রবর্তিত) সেট করার বিকল্প রয়েছে AUTOযাতে এটি কেবলমাত্র পার্টিশনটিকে লক করে রাখবে এবং ক্রমবর্ধমান পুরো টেবিলটি নয়। বা, যে কোনও টেবিলের জন্য আপনি একই বিকল্পটি সেট করতে পারেন DISABLE, যদিও আপনাকে সে সম্পর্কে খুব সতর্কতা অবলম্বন করতে হবে। বিস্তারিত জানার জন্য টেবিলটি দেখুন ।

এখানে কিছু ডকুমেন্টেশন রয়েছে যা লক এসক্লেশন এবং প্রান্তিকের বিষয়ে কথা বলে : লক এসক্লেশন (এটি বলছে "এসকিউএল সার্ভার ২০০৮ আর 2 এবং উচ্চতর সংস্করণগুলিতে প্রযোজ্য)"। এবং এখানে একটি ব্লগ পোস্ট রয়েছে যা লক বৃদ্ধি বৃদ্ধি এবং এটি নির্ধারণের জন্য কাজ করে: মাইক্রোসফ্ট এসকিউএল সার্ভারে লক করা (পার্ট 12 - লক এসক্লেশন)


সঠিক প্রশ্নের সাথে সম্পর্কিত নয়, তবে প্রশ্নের ক্যোয়ারির সাথে সম্পর্কিত, এখানে কয়েকটি উন্নতি করা যেতে পারে (বা কমপক্ষে এটি কেবল এটি দেখানো থেকে মনে হয়):

  1. আপনার লুপের জন্য, করণ WHILE (@@ROWCOUNT = @CHUNK_SIZE)কিছুটা ভাল কারণ যদি শেষ পুনরাবৃত্তিতে আপডেট হওয়া সারিগুলির সংখ্যা আপডেটের জন্য অনুরোধ করা পরিমাণের চেয়ে কম হয়, তবে আর কোনও কাজ বাকি নেই।

  2. যদি deletedক্ষেত্রের একটি হল BITডাটাটাইপ, তারপর যে মান নির্ধারিত হোক বা না হোক নয় deletedDateহয় 2000-01-01? তোমার দুজনের দরকার কেন?

  3. যদি এই দুটি ক্ষেত্র নতুন হয় এবং আপনি সেগুলি এটিকে যুক্ত করেছেন NULLযাতে এটি কোনও অনলাইন / অবরুদ্ধকরণ অপারেশন হতে পারে এবং এখন তাদের "ডিফল্ট" মানগুলিতে আপডেট করতে চাইছেন, তবে এটি প্রয়োজনীয় ছিল না। এসকিউএল সার্ভার ২০১২ (কেবলমাত্র এন্টারপ্রাইজ সংস্করণ) থেকে শুরু করা, NOT NULLডিফল্টের সীমাবদ্ধতা রয়েছে এমন কলামগুলি অ-ব্লকিং অপারেশন যতক্ষণ না ডিফল্টটির মান স্থির থাকে। সুতরাং আপনি যদি ক্ষেত্রগুলি এখনও ব্যবহার না করে থাকেন তবে কেবল NOT NULLএকটি ডিফল্ট সীমাবদ্ধতার সাথে ড্রপ এবং পুনরায় যুক্ত করুন ।

  4. আপনি এই আপডেটটি করার সময় যদি অন্য কোনও প্রক্রিয়া এই ক্ষেত্রগুলিকে আপডেট না করে তবে আপনি যে রেকর্ডগুলি আপডেট করতে চান তা সারিবদ্ধ করে রেখে কেবল সেই সারিটি বন্ধ করে দিলে দ্রুত হয়। বর্তমান পদ্ধতিতে একটি পারফরম্যান্স হিট হয়েছে কারণ আপনাকে পরিবর্তন করতে হবে এমন সেটটি পেতে প্রতিবার টেবিলটি পুনরায় জিজ্ঞাসা করতে হবে। পরিবর্তে, আপনি নিম্নলিখিতটি করতে পারেন যা কেবলমাত্র সেই দুটি ক্ষেত্রে একবার টেবিলটি স্ক্যান করে এবং তারপরে কেবল খুব টার্গেটযুক্ত আপডেটের বিবৃতি জারি করে। যে কোনও সময়ে প্রক্রিয়াটি থামানো এবং এটি শুরু করার পরে কোনও জরিমানা নেই, যেহেতু সারি প্রাথমিক জনগোষ্ঠী কেবল আপডেটের জন্য রেকর্ডগুলি খুঁজে পাবে।

    1. একটি অস্থায়ী সারণী (# ফুলসেট) তৈরি করুন যেখানে এটির মধ্যে ক্লাস্টারড সূচক থেকে মূল ক্ষেত্র রয়েছে।
    2. একই কাঠামোর দ্বিতীয় অস্থায়ী টেবিল (# কর্নেটসেট) তৈরি করুন।
    3. এর মাধ্যমে # ফুলসেটে .োকান SELECT TOP(n) KeyField1, KeyField2 FROM [huge-table] where deleted is null or deletedDate is null;

      TOP(n)টেবিল এর আকারের কারণে সেখানে রয়েছে। সারণীতে 100 মিলিয়ন সারি সহ, আপনাকে কীগুলির পুরো সেটটি দিয়ে কাতারি টেবিলটি প্রকৃতরূপে গড়ে তোলার দরকার নেই, বিশেষত যদি আপনি প্রায়শই এই প্রক্রিয়াটি প্রায়শই থামিয়ে দেওয়ার এবং পরে এটি পুনরায় চালু করার পরিকল্পনা করেন। সুতরাং সম্ভবত n1 মিলিয়ন সেট করা এবং এটি সম্পূর্ণরূপে চলতে দিন। আপনি সর্বদা এটি একটি এসকিউএল এজেন্ট চাকরিতে শিডিউল করতে পারেন যা 1 মিলিয়ন (বা সম্ভবত এর চেয়ে কম) এর সেট চালায় এবং তারপরে পরবর্তী সময় নির্ধারিত সময়ের জন্য আবার অপেক্ষা করতে অপেক্ষা করুন। তারপরে আপনি প্রতি 20 মিনিটে চালানোর জন্য সময় নির্ধারণ করতে পারেন তাই সেটগুলির সেটগুলির মধ্যে কিছু শ্বাস প্রশ্বাসের ঘর থাকবে nতবে এটি পুরো প্রক্রিয়াটি বিনা বাধায় শেষ করবে। তারপরে :-) করার মতো আর কিছু করার নেই, তখন কেবল চাকরীটি নিজেকে মুছুন।

    4. একটি লুপে, করুন:
      1. বর্তমান ব্যাচকে এমন কিছুর মাধ্যমে آباد করুন DELETE TOP (4995) FROM #FullSet OUTPUT Deleted.KeyField INTO #CurrentSet (KeyField);
      2. IF (@@ROWCOUNT = 0) BREAK;
      3. আপডেটের মতো কিছু ব্যবহার করে করুন: UPDATE ht SET ht.deleted = 0, ht.deletedDate='2000-01-01' FROM [huge-table] ht INNER JOIN #CurrentSet cs ON cs.KeyField = ht.KeyField;
      4. বর্তমান সেটটি সাফ করুন: TRUNCATE TABLE #CurrentSet;
  5. কিছু ক্ষেত্রে এটি অস্থির টেবিলের SELECTমধ্যে ফিডগুলি সহায়তা করতে একটি ফিল্টার সূচক যুক্ত করতে সহায়তা করে #FullSet। এই জাতীয় সূচক যুক্ত করার সাথে সম্পর্কিত কিছু বিবেচনা এখানে দেওয়া হয়েছে:
    1. আপনার কোয়েরীর শর্তটির সাথে WHERE শর্তটি মিলবে WHERE deleted is null or deletedDate is null
    2. প্রক্রিয়াটির শুরুতে, বেশিরভাগ সারিগুলি আপনার WHERE অবস্থার সাথে মিলবে, সুতরাং কোনও সূচকটি তেমন সহায়ক নয়। এটি যুক্ত করার আগে আপনি প্রায় 50% চিহ্নের আশেপাশে অপেক্ষা করতে চাইতে পারেন। অবশ্যই, এটি কতটা সহায়তা করে এবং যখন সূচক যুক্ত করা ভাল তখন বেশ কয়েকটি কারণের কারণে পরিবর্তিত হয়, তাই এটি কিছুটা পরীক্ষা এবং ত্রুটি।
    3. বেস ডেটা বেশ ঘন ঘন পরিবর্তিত হওয়ায় আপনাকে ম্যানুয়ালি স্ট্যাটস আপডেট করতে এবং / অথবা সূচিটি আপ টু ডেট রাখতে হবে might
    4. মনে রাখতে ভুলবেন না যে সূচকে, সহায়তা করার সময় SELECT, এটি ক্ষতিগ্রস্থ করবে UPDATEযেহেতু এটি অপারেশন চলাকালীন আপডেট হওয়া আবশ্যক, সুতরাং আরও I / O। এটি একটি ফিল্টার সূচক (যেগুলি কম সারিগুলি ফিল্টারটির সাথে মিলিত হওয়ার সাথে সাথে সারিগুলি আপডেট করার সাথে সাথে সঙ্কুচিত হয়) ব্যবহার করে উভয়ের মধ্যে খেলবে এবং সূচি যোগ করতে কিছুক্ষণ অপেক্ষা করতে হবে (যদি এটি শুরুতে সুপার সহায়ক না হয়, তবে ব্যয় করার কোনও কারণ নেই) অতিরিক্ত আই / ও)।

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


# 4 এ আপনার পরামর্শগুলি কিছু ক্ষেত্রে দ্রুত হতে পারে তবে এটি যুক্ত করার মতো কোড জটিলতার মত মনে হয়। আমি সহজ শুরু করতে চাই, এবং তারপরে যদি এটি আপনার চাহিদা পূরণ না করে তবে বিকল্পগুলি বিবেচনা করুন।
বেকন বিটস

@ বাকনবিটস সহজ শুরু করার বিষয়ে একমত হয়েছেন। ন্যায়সঙ্গতভাবে, এই পরামর্শগুলি সমস্ত পরিস্থিতিতে প্রয়োগ করার জন্য নয় to প্রশ্নটি একটি খুব বড় (100 মিলিয়ন + সারি) সারণী নিয়ে কাজ করার বিষয়ে।
সলোমন রুটজকি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.