সম্পর্কিত প্রশ্নটির উত্তর দেওয়ার সময় আমি এই প্রশ্ন সম্পর্কে অবগত ছিলাম না ( লুপ করার সময় এগুলিতে কি স্পষ্ট লেনদেনের প্রয়োজন? ), তবে সম্পূর্ণতার স্বার্থে, আমি এই সমস্যাটি এখানে এখানে সম্বোধন করব কারণ এটি সেই লিঙ্কযুক্ত উত্তরে আমার পরামর্শের অংশ ছিল না ।
যেহেতু আমি এসকিউএল এজেন্ট কাজের মাধ্যমে এটি নির্ধারণ করার পরামর্শ দিচ্ছি (এটি সর্বোপরি 100 মিলিয়ন সারি), আমি মনে করি না যে ক্লায়েন্টকে (যেমন এসএসএমএস) স্থিতি বার্তা প্রেরণের কোনও ফর্ম আদর্শ হবে (যদিও তা যদি হয়) অন্য প্রকল্পগুলির জন্য সর্বদা প্রয়োজন হয়, তবে আমি ভ্লাদিমিরের সাথে একমত হই যে ব্যবহার RAISERROR('', 10, 1) WITH NOWAIT;
করা উপায় the
এই বিশেষ ক্ষেত্রে, আমি একটি স্ট্যাটাস টেবিল তৈরি করব যা এ পর্যন্ত আপডেট করা সারিগুলির সংখ্যা সহ প্রতিটি লুপে আপডেট করা যেতে পারে। এবং প্রক্রিয়াটিতে হার্ট বিট পেতে বর্তমান সময়ে ছোঁড়াতে আঘাত লাগে না।
প্রদত্ত যে আপনি প্রক্রিয়াটি বাতিল এবং পুনরায় চালু করতে সক্ষম হতে চান, আমি স্পষ্ট লেনদেনে স্থিতি সারণীর আপডেটের সাথে মুখ্য টেবিলের হালনাগাদটি लपेटতে ক্লান্ত am তবে, আপনি যদি মনে করেন যে স্থিতির টেবিলটি বাতিল হওয়ার কারণে কোনও সময়ের সাথে সিঙ্কের বাইরে চলে গেছে, কেবলমাত্র মানটির সাথে ম্যানুয়ালি আপডেট করে বর্তমান মানটি রিফ্রেশ করা সহজ COUNT(*) FROM [huge-table] WHERE deleted IS NOT NULL AND deletedDate IS NOT NULL
।এবং আপডেটের জন্য দুটি টেবিল রয়েছে (যেমন মূল টেবিল এবং স্থিতি সারণী), আমাদের সেই দুটি টেবিল সিঙ্কে রাখার জন্য একটি স্পষ্ট লেনদেন ব্যবহার করা উচিত , তবুও আপনি যদি কোনও প্রক্রিয়া বাতিল করেন তবে আমরা অনাথ লেনদেনের ঝুঁকি নিতে চাই না এটি লেনদেন শুরু হওয়ার পরেও এটি প্রতিশ্রুতিবদ্ধ হয়নি point যতক্ষণ আপনি এসকিউএল এজেন্ট কাজ বন্ধ না করেন এটি করা নিরাপদ হওয়া উচিত।
আপনি কীভাবে প্রক্রিয়াটি থামাতে পারবেন না? এটি বন্ধ করে জিজ্ঞাসা করে :-)। হাঁ। প্রক্রিয়াটিকে একটি "সিগন্যাল" ( kill -3
ইউনিক্সের অনুরূপ ) প্রেরণ করে আপনি অনুরোধ করতে পারেন এটি পরবর্তী সুবিধাজনক মুহূর্তে বন্ধ করার জন্য (যেমন কোনও সক্রিয় লেনদেন নেই যখন!) এবং এটি সমস্ত সুন্দর এবং পরিপাটি-মত নিজেকে পরিষ্কার করতে অনুরোধ করতে পারে।
অন্য সেশনে চলমান প্রক্রিয়াটির সাথে আপনি কীভাবে যোগাযোগ করতে পারেন? এটির বর্তমান অবস্থাটি আপনার কাছে ফিরে যোগাযোগ করার জন্য আমরা এটির জন্য তৈরি করেছি একই পদ্ধতিটি ব্যবহার করে: স্থিতি সারণী। আমাদের কেবল একটি কলাম যুক্ত করতে হবে যা প্রক্রিয়াটি প্রতিটি লুপের শুরুতে যাচাই করবে যাতে এটি জেনে যায় বা অগ্রাহ্য করতে হবে কিনা knows আর যেহেতু অভিপ্রায়টি এসকিউএল এজেন্ট কাজ হিসাবে এটি নির্ধারণ করা হয় (প্রতি 10 বা 20 মিনিটের মধ্যে চালানো হয়), প্রক্রিয়াটি কেবল চলতে থাকলে 1 মিলিয়ন সারি দিয়ে একটি টেম্প টেবিলটি পূরণ করার কোনও অর্থ নেই বলে আমাদেরও খুব প্রথম দিকে পরীক্ষা করা উচিত we এক মুহুর্ত পরে প্রস্থান করতে এবং সেই ডেটার কোনওটিই ব্যবহার না করা।
DECLARE @BatchRows INT = 1000000,
@UpdateRows INT = 4995;
IF (OBJECT_ID(N'dbo.HugeTable_TempStatus') IS NULL)
BEGIN
CREATE TABLE dbo.HugeTable_TempStatus
(
RowsUpdated INT NOT NULL, -- updated by the process
LastUpdatedOn DATETIME NOT NULL, -- updated by the process
PauseProcess BIT NOT NULL -- read by the process
);
INSERT INTO dbo.HugeTable_TempStatus (RowsUpdated, LastUpdatedOn, PauseProcess)
VALUES (0, GETDATE(), 0);
END;
-- First check to see if we should run. If no, don't waste time filling temp table
IF (EXISTS(SELECT * FROM dbo.HugeTable_TempStatus WHERE PauseProcess = 1))
BEGIN
PRINT 'Process is paused. No need to start.';
RETURN;
END;
CREATE TABLE #FullSet (KeyField1 DataType1, KeyField2 DataType2);
CREATE TABLE #CurrentSet (KeyField1 DataType1, KeyField2 DataType2);
INSERT INTO #FullSet (KeyField1, KeyField2)
SELECT TOP (@BatchRows) ht.KeyField1, ht.KeyField2
FROM dbo.HugeTable ht
WHERE ht.deleted IS NULL
OR ht.deletedDate IS NULL
WHILE (1 = 1)
BEGIN
-- Check if process is paused. If yes, just exit cleanly.
IF (EXISTS(SELECT * FROM dbo.HugeTable_TempStatus WHERE PauseProcess = 1))
BEGIN
PRINT 'Process is paused. Exiting.';
BREAK;
END;
-- grab a set of rows to update
DELETE TOP (@UpdateRows)
FROM #FullSet
OUTPUT Deleted.KeyField1, Deleted.KeyField2
INTO #CurrentSet (KeyField1, KeyField2);
IF (@@ROWCOUNT = 0)
BEGIN
RAISERROR(N'All rows have been updated!!', 16, 1);
BREAK;
END;
BEGIN TRY
BEGIN TRAN;
-- do the update of the main table
UPDATE ht
SET ht.deleted = 0,
ht.deletedDate = '2000-01-01'
FROM dbo.HugeTable ht
INNER JOIN #CurrentSet cs
ON cs.KeyField1 = ht.KeyField1
AND cs.KeyField2 = ht.KeyField2;
-- update the current status
UPDATE ts
SET ts.RowsUpdated += @@ROWCOUNT,
ts.LastUpdatedOn = GETDATE()
FROM dbo.HugeTable_TempStatus ts;
COMMIT TRAN;
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK TRAN;
END;
THROW; -- raise the error and terminate the process
END CATCH;
-- clear out rows to update for next iteration
TRUNCATE TABLE #CurrentSet;
WAITFOR DELAY '00:00:01'; -- 1 second delay for some breathing room
END;
-- clean up temp tables when testing
-- DROP TABLE #FullSet;
-- DROP TABLE #CurrentSet;
তারপরে আপনি নিম্নলিখিত কোয়েরিটি ব্যবহার করে যে কোনও সময় স্থিতিটি পরীক্ষা করতে পারেন:
SELECT sp.[rows] AS [TotalRowsInTable],
ts.RowsUpdated,
(sp.[rows] - ts.RowsUpdated) AS [RowsRemaining],
ts.LastUpdatedOn
FROM sys.partitions sp
CROSS JOIN dbo.HugeTable_TempStatus ts
WHERE sp.[object_id] = OBJECT_ID(N'ResizeTest')
AND sp.[index_id] < 2;
প্রক্রিয়াটি বিরতি দিতে চান, এটি কোনও এসকিউএল এজেন্ট চাকরিতে বা অন্য কারও কম্পিউটারে এসএসএমএসে চলছে কিনা? শেষ ঘন্টা:
UPDATE ht
SET ht.PauseProcess = 1
FROM dbo.HugeTable_TempStatus ts;
প্রক্রিয়াটি আবার ব্যাক আপ শুরু করতে সক্ষম হতে চান? শেষ ঘন্টা:
UPDATE ht
SET ht.PauseProcess = 0
FROM dbo.HugeTable_TempStatus ts;
হালনাগাদ:
চেষ্টা করার জন্য এখানে অতিরিক্ত কিছু জিনিস রয়েছে যা এই ক্রিয়াকলাপটির কার্যকারিতা উন্নত করতে পারে। কারওরও সহায়তার নিশ্চয়তা নেই তবে সম্ভবত এটি পরীক্ষার উপযুক্ত। এবং আপডেট করার জন্য 100 মিলিয়ন সারি সহ, আপনার কাছে কিছু বৈচিত্র্য পরীক্ষা করার জন্য প্রচুর সময় / সুযোগ রয়েছে ;-)।
- যোগ
TOP (@UpdateRows)
আপডেট কোয়েরি যাতে মত শীর্ষ লাইন দেখায়:
UPDATE TOP (@UpdateRows) ht
কখনও কখনও এটি অপটিমাইজার জানেন যে কত সারি সর্বোচ্চ তাই এটি সময় নষ্ট করবেন না খুঁজছেন আরো প্রভাবিত হবে সাহায্য করে।
#CurrentSet
অস্থায়ী সারণীতে একটি প্রাথমিক কী যুক্ত করুন । এখানে ধারণাটি হ'ল 100 মিলিয়ন সারি সারণিতে JOIN এর সাহায্যে অপ্টিমাইজারটিকে সহায়তা করা।
অস্পষ্ট না হওয়ার জন্য এটি কেবল বিবৃত করার জন্য, #FullSet
অস্থায়ী টেবিলটিতে কোনও পিকে যুক্ত করার কোনও কারণ থাকতে হবে না কারণ এটি কেবল একটি সারি সারণি যেখানে আদেশ অপ্রাসঙ্গিক।
- কিছু ক্ষেত্রে এটি অস্থির টেবিলের
SELECT
মধ্যে ফিডগুলি সহায়তা করতে একটি ফিল্টার সূচক যুক্ত করতে সহায়তা করে #FullSet
। এই জাতীয় সূচক যুক্ত করার সাথে সম্পর্কিত কিছু বিবেচনা এখানে দেওয়া হয়েছে:
- আপনার কোয়েরীর শর্তটির সাথে WHERE শর্তটি মিলবে
WHERE deleted is null or deletedDate is null
- প্রক্রিয়াটির শুরুতে, বেশিরভাগ সারিগুলি আপনার WHERE অবস্থার সাথে মিলবে, সুতরাং কোনও সূচকটি তেমন সহায়ক নয়। এটি যুক্ত করার আগে আপনি প্রায় 50% চিহ্নের আশেপাশে অপেক্ষা করতে চাইতে পারেন। অবশ্যই, এটি কতটা সহায়তা করে এবং যখন সূচক যুক্ত করা ভাল তখন বেশ কয়েকটি কারণের কারণে পরিবর্তিত হয়, তাই এটি কিছুটা পরীক্ষা এবং ত্রুটি।
- বেস ডেটা বেশ ঘন ঘন পরিবর্তিত হবার কারণে আপনাকে ম্যানুয়ালি স্ট্যাটস আপডেট করতে এবং / অথবা সূচিটি আপ টু ডেট রাখতে হবে might
- মনে রাখতে ভুলবেন না যে সূচকে, সহায়তা করার সময়
SELECT
, এটি ক্ষতিগ্রস্থ করবে UPDATE
যেহেতু এটি অপারেশন চলাকালীন আপডেট হওয়া আবশ্যক, সুতরাং আরও I / O। এটি একটি ফিল্টার সূচক (যেগুলি কম সারিগুলি ফিল্টারটির সাথে মিলিত হওয়ার সাথে সাথে সারিগুলি আপডেট করার সাথে সাথে সঙ্কুচিত হয়) ব্যবহার করে উভয়ের মধ্যে খেলবে এবং সূচি যোগ করতে কিছুক্ষণ অপেক্ষা করতে হবে (যদি এটি শুরুতে সুপার সহায়ক না হয়, তবে ব্যয় করার কোনও কারণ নেই) অতিরিক্ত আই / ও)।