অলটার টেবিলে কি… ড্রপ কলম আসলেই কেবল একটি মেটাডেটা অপারেশন হয়?


11

আমি বেশ কয়েকটি উত্স পেয়েছি যা টেবিলের পরিবর্তে বলা আছে ... ড্রপ কলাম একটি মেটা-ডেটা কেবলমাত্র অপারেশন।

উৎস

এটা কিভাবে হতে পারে? ড্রপ কলামের সময় থাকা ডেটাগুলিকে অন্তর্নিহিত অ-ক্লাস্টারযুক্ত সূচি এবং ক্লাস্টার ইনডেক্স / হিপ থেকে মুছে ফেলা দরকার নেই?

এছাড়াও, মাইক্রোসফ্ট ডক্স কেন এটি সম্পূর্ণরূপে লগ করা অপারেশন বলে বোঝায়?

টেবিলটিতে করা পরিবর্তনগুলি লগ এবং সম্পূর্ণ পুনরুদ্ধারযোগ্য। যেমন পরিবর্তনসমূহ যে বৃহৎ টেবিল সমস্ত সারি প্রভাব ফেলে, একটি কলাম ড্রপ বা, এসকিউএল সার্ভার কিছু সংস্করণ, একটি ডিফল্ট মান সঙ্গে একটি নাল কলাম যোগ সম্পূর্ণ করার জন্য একটি দীর্ঘ সময় নিতে এবং অনেক লগ রেকর্ড তৈরি করতে পারেন । এই ALTER TABLE স্টেটমেন্টগুলি যে কোনও INSERT, আপডেট, বা অনেকগুলি সারিগুলিকে প্রভাবিত করে এমন বিবৃতি মুছে ফেলুন care

একটি গৌণ প্রশ্ন হিসাবে: ইঞ্জিনটি যদি অন্তর্নিহিত পৃষ্ঠাগুলি থেকে ডেটা না সরানো হয় তবে কীভাবে ইঞ্জিন ড্রপড কলামগুলির ট্র্যাক রাখবে?


2
ভাল, আমি মনে করি যে পণ্যটি বিভিন্ন সংস্করণ এবং ডকুমেন্টেশনের আরও অনেক পুনরাবৃত্তির মাধ্যমে ভাষা বেঁচে আছে। সময়ের সাথে সাথে, কলামগুলি জড়িত আরও বেশি ক্রিয়াকলাপগুলি অনলাইনে / মেটাডেটা কেবল পরিবর্তন হয়ে উঠেছে। এটি সম্ভবত একটি খারাপ নির্দিষ্ট উদাহরণ, তবে বাক্যটির উদ্দেশ্যটি কেবল আপনাকে সতর্ক করা যে, সাধারণভাবে কিছু কিছু পরিবর্তিত ক্রিয়াকলাপ প্রতিটি একক নির্দিষ্ট দৃশ্যের তালিকা তৈরির পরিবর্তে নির্দিষ্ট পরিস্থিতিতে কিছুটা আকারের-ডেটা অপারেশন হতে পারে ।
অ্যারন বারট্র্যান্ড

উত্তর:


14

কিছু পরিস্থিতিতে রয়েছে যেখানে কলামটি বাদ দেওয়া কেবলমাত্র মেটা-ডেটা-অপারেশন হতে পারে। প্রদত্ত টেবিলের জন্য কলাম সংজ্ঞাগুলি প্রতিটি পৃষ্ঠাতে সারি সজ্জিত নয় যেখানে কলাম সংজ্ঞা কেবল ডাটাবেস মেটাডেটাতে sys.sysrowsets, sys.sysrscols ইত্যাদি অন্তর্ভুক্ত থাকে etc.

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

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

এমন পরিস্থিতিতে রয়েছে যেখানে আপনি কলামটি ড্রপ করতে পারবেন না, যেমন কলামটি যখন কোনও সূচীতে অন্তর্ভুক্ত থাকে বা যখন আপনি ম্যানুয়ালি কলামটির জন্য একটি পরিসংখ্যান অবজেক্ট তৈরি করেছিলেন। আমি একটি ব্লগ পোস্ট লিখেছিলাম যাতে সেই ত্রুটিটি উপস্থিত রয়েছে যা ম্যানুয়ালি তৈরি করা পরিসংখ্যান অবজেক্টের সাহায্যে একটি কলাম পরিবর্তন করার চেষ্টা করার সময় উপস্থিত হয়। কলামটি নামানোর সময় একই শব্দার্থবিজ্ঞান প্রয়োগ হয় - কলামটি যদি অন্য কোনও বস্তুর দ্বারা রেফারেন্স করা হয় তবে তা কেবল বাদ দেওয়া যায় না। প্রথমে রেফারেন্সিং অবজেক্টটি অবশ্যই পরিবর্তন করতে হবে, তারপরে কলামটি বাদ দেওয়া যাবে।

কলামটি বাদ দেওয়ার পরে লেনদেনের লগের বিষয়বস্তু দেখে এটি দেখানো মোটামুটি সহজ। নীচের কোডটি একক 8,000 দীর্ঘ চর কলাম সহ একটি সারণী তৈরি করে। এটি একটি সারি যুক্ত করে, তারপরে এটি ড্রপ করে এবং ড্রপ ক্রিয়াকলাপে প্রযোজ্য লেনদেনের লগের সামগ্রী প্রদর্শন করে। লগ রেকর্ডগুলি বিভিন্ন সিস্টেম সারণিতে পরিবর্তনগুলি দেখায় যেখানে সারণী এবং কলাম সংজ্ঞা সঞ্চিত থাকে। যদি সারণীতে বরাদ্দকৃত পৃষ্ঠাগুলি থেকে কলামের তথ্যটি মুছে ফেলা হয় তবে আপনি প্রকৃত পৃষ্ঠার ডেটা রেকর্ডিং লগ রেকর্ড দেখতে পাবেন; এরকম কোনও রেকর্ড নেই।

DROP TABLE IF EXISTS dbo.DropColumnTest;
GO
CREATE TABLE dbo.DropColumnTest
(
    rid int NOT NULL
        CONSTRAINT DropColumnTest_pkc
        PRIMARY KEY CLUSTERED
    , someCol varchar(8000) NOT NULL
);

INSERT INTO dbo.DropColumnTest (rid, someCol)
SELECT 1, REPLICATE('Z', 8000);
GO

DECLARE @startLSN nvarchar(25);

SELECT TOP(1) @startLSN = dl.[Current LSN]
FROM sys.fn_dblog(NULL, NULL) dl
ORDER BY dl.[Current LSN] DESC;

DECLARE @a int = CONVERT(varbinary(8), '0x' + CONVERT(varchar(10),      LEFT(@startLSN, 8), 0), 1)
      , @b int = CONVERT(varbinary(8), '0x' + CONVERT(varchar(10), SUBSTRING(@startLSN, 10, 8), 0), 1)
      , @c int = CONVERT(varbinary(8), '0x' + CONVERT(varchar(10),     RIGHT(@startLSN, 4), 0), 1);

SELECT @startLSN = CONVERT(varchar(8), @a, 1) 
    + ':' + CONVERT(varchar(8), @b, 1) 
    + ':' + CONVERT(varchar(8), @c, 1)

ALTER TABLE dbo.DropColumnTest DROP COLUMN someCol;

SELECT *
FROM sys.fn_dblog(@startLSN, NULL)


--modify an existing data row 
SELECT TOP(1) @startLSN = dl.[Current LSN]
FROM sys.fn_dblog(NULL, NULL) dl
ORDER BY dl.[Current LSN] DESC;

SET @a = CONVERT(varbinary(8), '0x' + CONVERT(varchar(10),      LEFT(@startLSN, 8), 0), 1);
SET @b = CONVERT(varbinary(8), '0x' + CONVERT(varchar(10), SUBSTRING(@startLSN, 10, 8), 0), 1);
SET @c = CONVERT(varbinary(8), '0x' + CONVERT(varchar(10),     RIGHT(@startLSN, 4), 0), 1);

SELECT @startLSN = CONVERT(varchar(8), @a, 1) 
    + ':' + CONVERT(varchar(8), @b, 1) 
    + ':' + CONVERT(varchar(8), @c, 1)

UPDATE dbo.DropColumnTest SET rid = 2;

SELECT *
FROM sys.fn_dblog(@startLSN, NULL)

(ফলাফলটি এখানে দেখানোর জন্য খুব বড়, এবং dbfiddle.uk আমাকে fn_dblog অ্যাক্সেস করতে দেয় না)

DDL বিবৃতিটি কলামটি বাদ দেওয়ার ফলে প্রথম আউটপুট সেটটি লগটি দেখায়। আউটপুটের দ্বিতীয় সেটটি ডিএমএল স্টেটমেন্ট চালানোর পরে লগটি দেখায় যেখানে আমরা ridকলামটি আপডেট করি । দ্বিতীয় ফলাফলের সেটটিতে, আমরা লোগো রেকর্ডগুলি দেখতে পাচ্ছি যে ডিবিও.ড্রপ কলামটিস্টের বিপরীতে মুছুন, তারপরে ডিবিও.ড্রপ কলামটিস্টে সন্নিবেশ করানো হবে। প্রতিটি লগ রেকর্ড দৈর্ঘ্য 8116 হয় যা ইঙ্গিত করে যে আসল পৃষ্ঠাটি আপডেট হয়েছিল।

আপনি আউটপুট থেকে দেখতে পারেন fn_dblogউপরে পরীক্ষা কমান্ড সমগ্র অপারেশন করা হয় সম্পূর্ণরূপে লগ। এটি সাধারণ পুনরুদ্ধারের পাশাপাশি সম্পূর্ণ পুনরুদ্ধারের জন্য যায়। পরিভাষা "সম্পূর্ণরূপে লগড" হতে পারে ডেটা সংশোধন লগ না করায় ভুল ব্যাখ্যা করা যেতে পারে। পরিমার্জন - এই কি ঘটছে নয় হয় লগ, এবং সম্পূর্ণরূপে ফিরে ঘূর্ণিত করা যেতে পারে। লগটি কেবল কেবল সেই পৃষ্ঠাগুলিকেই রেকর্ড করে যা স্পর্শ করা হয়েছিল এবং যেহেতু সারণীর DROP COLUMNআকার-নির্বিশেষে কোনও টেবিলে ডেটা-পৃষ্ঠাগুলিই ডিডিএল অপারেশন দ্বারা লগ করা হয়নি ।

বিজ্ঞানের জন্য , নিম্নলিখিত কোডটি DBCC PAGE"3" শৈলী ব্যবহার করে উপরের কোডটিতে অন্তর্ভুক্ত থাকা সারণীর জন্য ডেটা পৃষ্ঠাগুলি ডাম্প করবে । স্টাইল "3" ইঙ্গিত দেয় যে আমরা পৃষ্ঠা শিরোনামের পাশাপাশি প্রতি সারি বিশদের ব্যাখ্যার বিশদ চাই । টেবিলের প্রতিটি পৃষ্ঠার বিশদ প্রদর্শনের জন্য কোডটি একটি কার্সার ব্যবহার করে , যাতে আপনি এটি নিশ্চিত করতে চাইতে পারেন যে আপনি এটি কোনও বৃহত টেবিলে চালাচ্ছেন না।

DBCC TRACEON(3604); --directs out from DBCC commands to the console, instead of the error log
DECLARE @dbid int = DB_ID();
DECLARE @fileid int;
DECLARE @pageid int;
DECLARE cur CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY
FOR
SELECT dpa.allocated_page_file_id
    , dpa.allocated_page_page_id
FROM sys.schemas s  
    INNER JOIN sys.objects o ON o.schema_id = s.schema_id
CROSS APPLY sys.dm_db_database_page_allocations(DB_ID(), o.object_id, NULL, NULL, 'DETAILED') dpa
WHERE o.name = N'DropColumnTest'
    AND s.name = N'dbo'
    AND dpa.page_type_desc = N'DATA_PAGE';
OPEN cur;
FETCH NEXT FROM cur INTO @fileid, @pageid;
WHILE @@FETCH_STATUS = 0
BEGIN
    DBCC PAGE (@dbid, @fileid, @pageid, 3);
    FETCH NEXT FROM cur INTO @fileid, @pageid;
END
CLOSE cur;
DEALLOCATE cur;
DBCC TRACEOFF(3604);

আমার ডেমো থেকে প্রথম পৃষ্ঠার আউটপুট দেখে (কলামটি বাদ পড়ার পরে, তবে কলামটি আপডেট হওয়ার আগে), আমি এটি দেখতে পাচ্ছি:

পৃষ্ঠা: (1: 100104)


বাফার:


BUF @ 0x0000021793E42040

বিপেজ = 0x000002175A7A0000 bhash = 0x0000000000000000 bpageno = (1: 100104)
বিডিবিড = 10 টি বিভাজন = 1 বিসিপুটিক্স = 0
bsampleCount = 0 bUse1 = 13760 bstat = 0x10b
ব্লগ = 0x212121 সিসি বেনেক্সট = 0x0000000000000000 বিডার্টি কনটেক্সট = 0x000002175004B640
bstat2 = 0x0                        

পেজের উপরের অংশ:


পৃষ্ঠা @ 0x000002175A7A0000

m_pageId = (1: 100104) m_headerVersion = 1 মি_ টাইপ = 1
m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0xc000
m_objId (AllocUnitId.idObj) = 300 m_indexId (AllocUnitId.idInd) = 256 
মেটাডেটা: AllocUnitId = 72057594057588736                                
মেটাডেটা: পার্টিশনআইডি = 72057594051756032 মেটাডেটা: সূচিপত্র = 1
মেটাডেটা: অবজেক্টআইডি = 174623665 মি_প্রিভ পেজ = (0: 0) মি_নেক্সটপেজ = (0: 0)
পিনম্লেন = 8 মি_স্লটসিএনটি = 1 মি_ফ্রিচেন্ট = 79
মি_ফ্রিডাটা = 8111 মি_ রিজার্ভড সিএনটি = 0 এম_এলএসএন = (616: 14191: 25)
m_xactRe محفوظ = 0 মি_এক্সডিড আইডি = (0: 0) এম_ঘোস্টআরসিএনটি = 0
m_tornBits = 0 ডিবি ফ্রেগ আইডি = 1                      

বরাদ্দ স্থিতি

গ্যাম (1: 2) = অলোকড এসজিএএম (1: 3) = অলকৃত নয়          
পিএফএস (1: 97056) = 0x40 সীমাবদ্ধ 0_PCT_FULL DIFF (1: 6) = পরিবর্তন
এমএল (1: 7) = এমএলএলজিড নয়           

স্লট 0 অফসেট 0x60 দৈর্ঘ্য 8015

রেকর্ডের প্রকার = PRIMARY_RECORD রেকর্ড বৈশিষ্ট্য = NULL_BITMAP VARIABLE_COLUMNS
রেকর্ড আকার = 8015                  
মেমরি ডাম্প @ 0x000000B75227A060

0000000000000000: 30000800 01000000 02000001 004f1f5a 5a5a5a5a 0 ............ ও.জেডজেডজেড
0000000000000014: 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a ZZZZZZZZZZZZZZZZZZZZZ
।
।
।
0000000000001F2C: 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a5a ZZZZZZZZZZZZZZZZZZZZ
0000000000001F40: 5a5a5a5a 5a5a5a5a 5a5a5a5a 5a5a5a ZZZZZZZZZZZZZZZZ

স্লট 0 কলাম 1 অফসেট 0x4 দৈর্ঘ্য 4 দৈর্ঘ্য (শারীরিক) 4

মুক্তি = 1                             

স্লট 0 কলাম 67108865 অফসেট 0xf দৈর্ঘ্য 0 দৈর্ঘ্য (দৈহিক) 8000

ড্রপড = নাল                      

স্লট 0 অফসেট 0x0 দৈর্ঘ্য 0 দৈর্ঘ্য (শারীরিক) 0

কীহ্যাশভ্যালু = (8194443284a0)       

আমি ব্রিভটির জন্য উপরে প্রদর্শিত আউটপুট থেকে বেশিরভাগ কাঁচা পৃষ্ঠা ডাম্প সরিয়ে ফেলেছি। আউটপুট শেষে আপনি ridকলামটির জন্য এটি দেখতে পাবেন :

স্লট 0 কলাম 1 অফসেট 0x4 দৈর্ঘ্য 4 দৈর্ঘ্য (শারীরিক) 4

মুক্তি = 1                             

উপরের শেষ লাইনটি, rid = 1কলামটির নাম এবং পৃষ্ঠার কলামে সঞ্চিত বর্তমান মান প্রদান করে।

পরবর্তী, আপনি এটি দেখতে পাবেন:

স্লট 0 কলাম 67108865 অফসেট 0xf দৈর্ঘ্য 0 দৈর্ঘ্য (দৈহিক) 8000

ড্রপড = নাল                      

আউটপুট দেখায় যে স্লট 0-এ একটি মুছে ফেলা কলাম রয়েছে, DELETEDপাঠ্যের গুণে যেখানে কলামের নামটি সাধারণত থাকবে। NULLকলামটি মুছে ফেলা হয়েছে বলেই কলামটির মান ফিরে আসবে । যাইহোক, আপনি কাঁচা তথ্যতে দেখতে পাচ্ছেন, 8,000 অক্ষরের দীর্ঘ মান, REPLICATE('Z', 8000)সেই কলামটির জন্য এখনও পৃষ্ঠাটিতে বিদ্যমান। এটি ডিবিসিসি পৃষ্ঠার আউটপুট অংশের একটি নমুনা:

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