در این مطلب، تفاوتهای دستورات Delete و Truncate را بررسی میکنیم. هر دو دستور برای حذف رکوردها در SQL Server استفاده میشوند، اما تفاوتهای قابل توجهی دارند.
دستور Delete
- حذف رکوردها به صورت جداگانه: دستور Delete تمام رکوردها یا بخشی از رکوردها را به صورت جداگانه حذف میکند. (رکوردها تا زمان Commit تراکنش با علامت حذفشده مشخص میشوند)
- ثبت اطلاعات رکوردهای حذفشده: اطلاعات رکوردهای حذفشده در فایل تراکنش ثبت میشود.
- فعالسازی Delete Trigger: پس از حذف رکوردها، Delete Trigger فعال میشود.
- تغییر متادیتاهای ایندکسها: متادیتاهای Clustered Index یا Heap تغییر میکند.
- عدم تغییر مقدار Identity: مقدار Identity تغییر نمیکند.
دستور Truncate
- علامتگذاری Data Pageها: دستور Truncate تمامی Data Pageهای جدول یا ایندکس را با علامت حذف شده مشخص میکند تا زمان Commit تراکنش.
- ثبت شمارههای FileID و PageID: در هنگام علامتگذاری، شماره FileID و PageID در فایل تراکنش ثبت میشود.
- عدم فعالسازی Delete Trigger: پس از حذف Data Pageها، Delete Trigger فعال نمیشود.
- تغییر متادیتاهای ایندکسها: متادیتاهای Clustered Index یا Heap تغییر میکند.
- صفر شدن مقدار Identity: مقدار Identity به صفر میرسد.
مقایسه دستور DELETE و TRUNCATE در SQL Server
در مقایسه عملکرد این دو دستور، میتوان گفت که سرعت اجرای دستور Truncate به مراتب بیشتر از Delete است. این به دلیل نحوه علامتگذاری و حذف Data Pageها در دستور Truncate است که باعث کاهش زمان اجرا و افزایش کارایی میشود.
ویژگی | DELETE | TRUNCATE |
---|---|---|
نوع عملیات | DML (Data Manipulation Language) | DDL (Data Definition Language) |
نحوه حذف | حذف ردیف به ردیف | علامتگذاری کل Data Pageها |
ثبت در لاگ تراکنش | بله، بهصورت کامل (سطر به سطر) | بله، فقط FileID و PageID |
امکان فیلتر (WHERE) | ✅ دارد | ❌ ندارد |
سرعت اجرا | کندتر | سریعتر |
Trigger فعال میشود؟ | ✅ بله | ❌ خیر |
مقدار Identity | تغییر نمیکند | Reset میشود (به مقدار اولیه) |
میزان مصرف لاگ تراکنش | زیاد | کم |
امکان Rollback | ✅ دارد | ✅ دارد |
کاربرد اصلی | حذف بخشی از دادهها یا کنترل دقیق | پاکسازی کامل جدول |
نکات مهم درباره DELETE و TRUNCATE
اگر نیاز دارید فقط بخشی از دادهها رو حذف کنید (مثلاً رکوردهای یک ماه خاص)، باید از DELETE استفاده کنید.
اگر هدف پاکسازی کل جدول باشه و سرعت برات مهمه، TRUNCATE انتخاب بهتریه.
به خاطر Reset شدن Identity در TRUNCATE، اگه نمیخوای شمارنده ستون Identity صفر بشه باید بعدش دوباره با
DBCC CHECKIDENT
تنظیمش کنی.هر دو دستور قابل Rollback هستن (تا زمانی که تراکنش Commit نشده باشه).
مثال
کد زیر یک جدول با مقداری رکورد برای نمایش این موضوع میسازد:
-- کد ایجاد جدول و تراکنش نمونه
CREATE TABLE ExampleTable (
ID INT IDENTITY(1,1),
Data NVARCHAR(100)
);
INSERT INTO ExampleTable (Data)
VALUES ('Record1'), ('Record2'), ('Record3'), ('Record4'), ('Record5');
حال عکسالعمل SQL Server در مقابل دستور Delete را مشاهده کنید:
-- کد نمونه برای دستور Delete
BEGIN TRANSACTION;
DELETE FROM ExampleTable WHERE ID = 1;
-- بررسی وضعیت قفلها و Data Pageها
SELECT * FROM sys.dm_tran_locks WHERE resource_associated_entity_id = OBJECT_ID('ExampleTable');
COMMIT TRANSACTION;
SQL Server جدول را با نوع قفل Exclusive قفل میکند، که تنها با استفاده از دستور NOLOCK میتوان به دادهها دسترسی داشت. حالا یکبار دیگر جدول را پر از داده میکنیم و دستور Truncate را اجرا میکنیم:
-- کد نمونه برای دستور Truncate
TRUNCATE TABLE ExampleTable;
-- بررسی وضعیت قفلها و Data Pageها
SELECT * FROM sys.dm_tran_locks WHERE resource_associated_entity_id = OBJECT_ID('ExampleTable');
مثال تکمیلی برای Reset نشدن Identity بعد از TRUNCATE
پیشنهاد مطالعه: حذف ردیفهای تکراری در جداول SQL Server
نتیجه گیری
در نهایت، دستور Truncate قفلی از نوع Sch-M اعمال میکند که اجازه نوشتن و خواندن به تراکنشهای دیگر را نمیدهد. به همین دلیل، SQL Server دستور Truncate را به عنوان DDL در فایل تراکنش ذخیره میکند.
FAQ (پرسشهای متداول)
۱. آیا دستور TRUNCATE قابل Rollback است؟
بله، اگر داخل یک تراکنش اجرا شود و قبل از Commit کردن Rollback کنید، دادهها برمیگردند.
۲. آیا میتوان روی جدول دارای Foreign Key دستور TRUNCATE زد؟
خیر، اگر جدول با کلید خارجی به جدول دیگری مرتبط باشد، باید ابتدا Constraintها را غیرفعال کنید یا از DELETE استفاده کنید.
۳. کدام دستور سریعتر است؟ DELETE یا TRUNCATE؟
TRUNCATE بسیار سریعتر است چون رکورد به رکورد لاگ نمینویسد و فقط Data Pageها را علامتگذاری میکند.
۴. بعد از TRUNCATE ستون Identity از کجا شروع میشود؟
مقدار Identity به عدد اولیه (Seed) برمیگردد. میتوانید با دستور DBCC CHECKIDENT
آن را تغییر دهید.
۵. اگر بخواهم فقط بخشی از دادهها را پاک کنم، کدام دستور مناسبتر است؟
باید از DELETE استفاده کنید، چون TRUNCATE امکان استفاده از شرط (WHERE) را ندارد.
ارتباط و مشاوره
برای اطلاعات بیشتر و مشاوره میتوانید از طریق زیر با ما در ارتباط باشید:
نظری داده نشده