Is ALTER TABLE … DROP COLUMN really a metadata only operation?Alter table modify column on a huge table containing more than 25 million recordsRunning out of Transaction Log space during Alter TableSQL Server : ALTER TABLE tablename SWITCH PARTITION 2 to tempemptyWill dropping text column on SQL Server 2014 lock the table?Changing a column from NOT NULL to NULL - What's going on under the hood?is it possible to alter the primary key of a table (from non clustered to clustered) in the subscriber only and not break the replication?What exactly is written to transaction log?Table size increase after data alterReclaim space from dropped column when there isn't enough space for index rebuildWhat makes ALTER TABLE X SET UNLOGGED; to be slow?

Compiling all Exception messages into a string

If two black hole event horizons overlap (touch) can they ever separate again?

Closest Proximity of Oceans to Freshwater Springs

13th chords on guitar

If you kill a Solar Angel can you use its Slaying Longbow?

Origin of the convolution theorem

How do I tell the reader that my character is autistic in Fantasy?

Word ending in "-ine" for rat-like

Why were the first airplanes "backwards"?

Adjective for 'made of pus' or 'corrupted by pus' or something of something of pus

Early 2000s movie about time travel, protagonist travels back to save girlfriend, then into multiple points in future

Why was p[:] designed to work differently in these two situations?

Story where diplomats use codes for emotions

Can European countries bypass the EU and make their own individual trade deal with the U.S.?

"I am [the / an] owner of a bookstore"?

Why wasn't ASCII designed with a contiguous alphanumeric character order?

Traversing Eurasia: A Cryptic Journey

List Manipulation : a,b,c,d,e,f,g,h into a,b,c,d,e,f,g,h

Can dual citizens open crypto exchange accounts where U.S. citizens are prohibited?

A* pathfinding algorithm too slow

Transferring Data From One Table to Another Using Multiple Keys in ArcPy?

Cooking a nice pan seared steak for picky eaters

How to describe POV characters?

How do ohm meters measure high resistances?



Is ALTER TABLE … DROP COLUMN really a metadata only operation?


Alter table modify column on a huge table containing more than 25 million recordsRunning out of Transaction Log space during Alter TableSQL Server : ALTER TABLE tablename SWITCH PARTITION 2 to tempemptyWill dropping text column on SQL Server 2014 lock the table?Changing a column from NOT NULL to NULL - What's going on under the hood?is it possible to alter the primary key of a table (from non clustered to clustered) in the subscriber only and not break the replication?What exactly is written to transaction log?Table size increase after data alterReclaim space from dropped column when there isn't enough space for index rebuildWhat makes ALTER TABLE X SET UNLOGGED; to be slow?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








5















I've found several sources that state ALTER TABLE ... DROP COLUMN is a meta-data only operation.



Source



How can this be? Does the data during a DROP COLUMN not need to be purged from the underlying non-clustered indexes and clustered index / heap?



In addition, why do the Microsoft Docs imply that it is a fully logged operation?




The modifications made to the table are logged and fully recoverable. Changes that affect all the rows in large tables, such as dropping a column or, on some editions of SQL Server, adding a NOT NULL column with a default value, can take a long time to complete and generate many log records. Run these ALTER TABLE statements with the same care as any INSERT, UPDATE, or DELETE statement that affects many rows.




As a secondary question: how does the engine keep track of dropped columns if the data isn't removed from the underlying pages?










share|improve this question



















  • 2





    Well, I think that language has survived through many versions of the product and many more iterations of the documentation. Over time, more and more operations involving columns have become online / metadata only changes. It's perhaps a bad specific example now, but the purpose of the sentence is simply to warn you that, in general, some alter operations might be size-of-data operations in certain scenarios, rather than list out every single specific scenario.

    – Aaron Bertrand
    7 hours ago


















5















I've found several sources that state ALTER TABLE ... DROP COLUMN is a meta-data only operation.



Source



How can this be? Does the data during a DROP COLUMN not need to be purged from the underlying non-clustered indexes and clustered index / heap?



In addition, why do the Microsoft Docs imply that it is a fully logged operation?




The modifications made to the table are logged and fully recoverable. Changes that affect all the rows in large tables, such as dropping a column or, on some editions of SQL Server, adding a NOT NULL column with a default value, can take a long time to complete and generate many log records. Run these ALTER TABLE statements with the same care as any INSERT, UPDATE, or DELETE statement that affects many rows.




As a secondary question: how does the engine keep track of dropped columns if the data isn't removed from the underlying pages?










share|improve this question



















  • 2





    Well, I think that language has survived through many versions of the product and many more iterations of the documentation. Over time, more and more operations involving columns have become online / metadata only changes. It's perhaps a bad specific example now, but the purpose of the sentence is simply to warn you that, in general, some alter operations might be size-of-data operations in certain scenarios, rather than list out every single specific scenario.

    – Aaron Bertrand
    7 hours ago














5












5








5


0






I've found several sources that state ALTER TABLE ... DROP COLUMN is a meta-data only operation.



Source



How can this be? Does the data during a DROP COLUMN not need to be purged from the underlying non-clustered indexes and clustered index / heap?



In addition, why do the Microsoft Docs imply that it is a fully logged operation?




The modifications made to the table are logged and fully recoverable. Changes that affect all the rows in large tables, such as dropping a column or, on some editions of SQL Server, adding a NOT NULL column with a default value, can take a long time to complete and generate many log records. Run these ALTER TABLE statements with the same care as any INSERT, UPDATE, or DELETE statement that affects many rows.




As a secondary question: how does the engine keep track of dropped columns if the data isn't removed from the underlying pages?










share|improve this question
















I've found several sources that state ALTER TABLE ... DROP COLUMN is a meta-data only operation.



Source



How can this be? Does the data during a DROP COLUMN not need to be purged from the underlying non-clustered indexes and clustered index / heap?



In addition, why do the Microsoft Docs imply that it is a fully logged operation?




The modifications made to the table are logged and fully recoverable. Changes that affect all the rows in large tables, such as dropping a column or, on some editions of SQL Server, adding a NOT NULL column with a default value, can take a long time to complete and generate many log records. Run these ALTER TABLE statements with the same care as any INSERT, UPDATE, or DELETE statement that affects many rows.




As a secondary question: how does the engine keep track of dropped columns if the data isn't removed from the underlying pages?







sql-server transaction-log alter-table






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago







George.Palacios

















asked 8 hours ago









George.PalaciosGeorge.Palacios

3,5539 silver badges28 bronze badges




3,5539 silver badges28 bronze badges







  • 2





    Well, I think that language has survived through many versions of the product and many more iterations of the documentation. Over time, more and more operations involving columns have become online / metadata only changes. It's perhaps a bad specific example now, but the purpose of the sentence is simply to warn you that, in general, some alter operations might be size-of-data operations in certain scenarios, rather than list out every single specific scenario.

    – Aaron Bertrand
    7 hours ago













  • 2





    Well, I think that language has survived through many versions of the product and many more iterations of the documentation. Over time, more and more operations involving columns have become online / metadata only changes. It's perhaps a bad specific example now, but the purpose of the sentence is simply to warn you that, in general, some alter operations might be size-of-data operations in certain scenarios, rather than list out every single specific scenario.

    – Aaron Bertrand
    7 hours ago








2




2





Well, I think that language has survived through many versions of the product and many more iterations of the documentation. Over time, more and more operations involving columns have become online / metadata only changes. It's perhaps a bad specific example now, but the purpose of the sentence is simply to warn you that, in general, some alter operations might be size-of-data operations in certain scenarios, rather than list out every single specific scenario.

– Aaron Bertrand
7 hours ago






Well, I think that language has survived through many versions of the product and many more iterations of the documentation. Over time, more and more operations involving columns have become online / metadata only changes. It's perhaps a bad specific example now, but the purpose of the sentence is simply to warn you that, in general, some alter operations might be size-of-data operations in certain scenarios, rather than list out every single specific scenario.

– Aaron Bertrand
7 hours ago











1 Answer
1






active

oldest

votes


















6














There are certain circumstances where dropping a column can be a meta-data-only operation. The column definitions for any given table are not included in each and every page where rows are stored, column definitions are only stored in the database metadata, including sys.sysrowsets, sys.sysrscols, etc.



When dropping a column that is not referenced by any other object, the storage engine simply marks the column definition as no longer present by deleting the pertinent details from various system tables. When a query subsequently references that table, it skips the bytes stored in each page for that column, as if the column no longer exists.



When a subsequent DML operation occurs against the table, the pages that are affected are re-written without the data for the dropped column. If you rebuild a clustered index or a heap, all the bytes for the dropped column are naturally not written back to the page on disk. This effectively spreads the load of dropping the column over time, making it less noticeable.



There are circumstances where you cannot drop a column, such as when the column is included in an index, or when you've manually created a statistics object for the column. I wrote a blog post showing the error that is presented when attempting to alter a column with a manually created statistics object. The same semantics apply when dropping a column - if the column is referenced by any other object, it cannot simply be dropped. The referencing object must be altered first, then the column can be dropped.



This is fairly easy to show by looking at the contents of the transaction log after dropping a column. The code below creates a table with a single 8,000 long char column. It adds a row, then drops it, and displays the contents of the transaction log applicable to the drop operation. The log records show modifications to various system tables where the table and column definitions are stored. If the column data was actually being deleted from the pages allocated to the table, you'd see log records recording the actual page data; there are no such records.



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)


(The output is too big to show here, and dbfiddle.uk won't allow me to access fn_dblog)



The first set of output shows the log as a result of the DDL statement dropping the column. The second set of output shows the log after running the DML statement where we update the rid column. In the second result set, we see log records indicating a delete against dbo.DropColumnTest, followed by an insert into dbo.DropColumnTest. Each Log Record Length is 8116, indicating the actual page was updated.



As you can see from the output of the fn_dblog command in the test above, the entire operation is fully logged. This goes for simple recovery, as well as full recovery. The terminology "fully logged" maybe misinterpreted as the data modification is not logged. This is not what happens - the modification is logged, and can be fully rolled back. The log is simply only recording the pages that were touched, and since none of the table's data-pages were logged by the DDL operation, both the DROP COLUMN, and any rollback that might occur will happen extremely quickly, regardless of the size of the table.






share|improve this answer



























    Your Answer








    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "182"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f241563%2fis-alter-table-drop-column-really-a-metadata-only-operation%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    6














    There are certain circumstances where dropping a column can be a meta-data-only operation. The column definitions for any given table are not included in each and every page where rows are stored, column definitions are only stored in the database metadata, including sys.sysrowsets, sys.sysrscols, etc.



    When dropping a column that is not referenced by any other object, the storage engine simply marks the column definition as no longer present by deleting the pertinent details from various system tables. When a query subsequently references that table, it skips the bytes stored in each page for that column, as if the column no longer exists.



    When a subsequent DML operation occurs against the table, the pages that are affected are re-written without the data for the dropped column. If you rebuild a clustered index or a heap, all the bytes for the dropped column are naturally not written back to the page on disk. This effectively spreads the load of dropping the column over time, making it less noticeable.



    There are circumstances where you cannot drop a column, such as when the column is included in an index, or when you've manually created a statistics object for the column. I wrote a blog post showing the error that is presented when attempting to alter a column with a manually created statistics object. The same semantics apply when dropping a column - if the column is referenced by any other object, it cannot simply be dropped. The referencing object must be altered first, then the column can be dropped.



    This is fairly easy to show by looking at the contents of the transaction log after dropping a column. The code below creates a table with a single 8,000 long char column. It adds a row, then drops it, and displays the contents of the transaction log applicable to the drop operation. The log records show modifications to various system tables where the table and column definitions are stored. If the column data was actually being deleted from the pages allocated to the table, you'd see log records recording the actual page data; there are no such records.



    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)


    (The output is too big to show here, and dbfiddle.uk won't allow me to access fn_dblog)



    The first set of output shows the log as a result of the DDL statement dropping the column. The second set of output shows the log after running the DML statement where we update the rid column. In the second result set, we see log records indicating a delete against dbo.DropColumnTest, followed by an insert into dbo.DropColumnTest. Each Log Record Length is 8116, indicating the actual page was updated.



    As you can see from the output of the fn_dblog command in the test above, the entire operation is fully logged. This goes for simple recovery, as well as full recovery. The terminology "fully logged" maybe misinterpreted as the data modification is not logged. This is not what happens - the modification is logged, and can be fully rolled back. The log is simply only recording the pages that were touched, and since none of the table's data-pages were logged by the DDL operation, both the DROP COLUMN, and any rollback that might occur will happen extremely quickly, regardless of the size of the table.






    share|improve this answer





























      6














      There are certain circumstances where dropping a column can be a meta-data-only operation. The column definitions for any given table are not included in each and every page where rows are stored, column definitions are only stored in the database metadata, including sys.sysrowsets, sys.sysrscols, etc.



      When dropping a column that is not referenced by any other object, the storage engine simply marks the column definition as no longer present by deleting the pertinent details from various system tables. When a query subsequently references that table, it skips the bytes stored in each page for that column, as if the column no longer exists.



      When a subsequent DML operation occurs against the table, the pages that are affected are re-written without the data for the dropped column. If you rebuild a clustered index or a heap, all the bytes for the dropped column are naturally not written back to the page on disk. This effectively spreads the load of dropping the column over time, making it less noticeable.



      There are circumstances where you cannot drop a column, such as when the column is included in an index, or when you've manually created a statistics object for the column. I wrote a blog post showing the error that is presented when attempting to alter a column with a manually created statistics object. The same semantics apply when dropping a column - if the column is referenced by any other object, it cannot simply be dropped. The referencing object must be altered first, then the column can be dropped.



      This is fairly easy to show by looking at the contents of the transaction log after dropping a column. The code below creates a table with a single 8,000 long char column. It adds a row, then drops it, and displays the contents of the transaction log applicable to the drop operation. The log records show modifications to various system tables where the table and column definitions are stored. If the column data was actually being deleted from the pages allocated to the table, you'd see log records recording the actual page data; there are no such records.



      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)


      (The output is too big to show here, and dbfiddle.uk won't allow me to access fn_dblog)



      The first set of output shows the log as a result of the DDL statement dropping the column. The second set of output shows the log after running the DML statement where we update the rid column. In the second result set, we see log records indicating a delete against dbo.DropColumnTest, followed by an insert into dbo.DropColumnTest. Each Log Record Length is 8116, indicating the actual page was updated.



      As you can see from the output of the fn_dblog command in the test above, the entire operation is fully logged. This goes for simple recovery, as well as full recovery. The terminology "fully logged" maybe misinterpreted as the data modification is not logged. This is not what happens - the modification is logged, and can be fully rolled back. The log is simply only recording the pages that were touched, and since none of the table's data-pages were logged by the DDL operation, both the DROP COLUMN, and any rollback that might occur will happen extremely quickly, regardless of the size of the table.






      share|improve this answer



























        6












        6








        6







        There are certain circumstances where dropping a column can be a meta-data-only operation. The column definitions for any given table are not included in each and every page where rows are stored, column definitions are only stored in the database metadata, including sys.sysrowsets, sys.sysrscols, etc.



        When dropping a column that is not referenced by any other object, the storage engine simply marks the column definition as no longer present by deleting the pertinent details from various system tables. When a query subsequently references that table, it skips the bytes stored in each page for that column, as if the column no longer exists.



        When a subsequent DML operation occurs against the table, the pages that are affected are re-written without the data for the dropped column. If you rebuild a clustered index or a heap, all the bytes for the dropped column are naturally not written back to the page on disk. This effectively spreads the load of dropping the column over time, making it less noticeable.



        There are circumstances where you cannot drop a column, such as when the column is included in an index, or when you've manually created a statistics object for the column. I wrote a blog post showing the error that is presented when attempting to alter a column with a manually created statistics object. The same semantics apply when dropping a column - if the column is referenced by any other object, it cannot simply be dropped. The referencing object must be altered first, then the column can be dropped.



        This is fairly easy to show by looking at the contents of the transaction log after dropping a column. The code below creates a table with a single 8,000 long char column. It adds a row, then drops it, and displays the contents of the transaction log applicable to the drop operation. The log records show modifications to various system tables where the table and column definitions are stored. If the column data was actually being deleted from the pages allocated to the table, you'd see log records recording the actual page data; there are no such records.



        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)


        (The output is too big to show here, and dbfiddle.uk won't allow me to access fn_dblog)



        The first set of output shows the log as a result of the DDL statement dropping the column. The second set of output shows the log after running the DML statement where we update the rid column. In the second result set, we see log records indicating a delete against dbo.DropColumnTest, followed by an insert into dbo.DropColumnTest. Each Log Record Length is 8116, indicating the actual page was updated.



        As you can see from the output of the fn_dblog command in the test above, the entire operation is fully logged. This goes for simple recovery, as well as full recovery. The terminology "fully logged" maybe misinterpreted as the data modification is not logged. This is not what happens - the modification is logged, and can be fully rolled back. The log is simply only recording the pages that were touched, and since none of the table's data-pages were logged by the DDL operation, both the DROP COLUMN, and any rollback that might occur will happen extremely quickly, regardless of the size of the table.






        share|improve this answer















        There are certain circumstances where dropping a column can be a meta-data-only operation. The column definitions for any given table are not included in each and every page where rows are stored, column definitions are only stored in the database metadata, including sys.sysrowsets, sys.sysrscols, etc.



        When dropping a column that is not referenced by any other object, the storage engine simply marks the column definition as no longer present by deleting the pertinent details from various system tables. When a query subsequently references that table, it skips the bytes stored in each page for that column, as if the column no longer exists.



        When a subsequent DML operation occurs against the table, the pages that are affected are re-written without the data for the dropped column. If you rebuild a clustered index or a heap, all the bytes for the dropped column are naturally not written back to the page on disk. This effectively spreads the load of dropping the column over time, making it less noticeable.



        There are circumstances where you cannot drop a column, such as when the column is included in an index, or when you've manually created a statistics object for the column. I wrote a blog post showing the error that is presented when attempting to alter a column with a manually created statistics object. The same semantics apply when dropping a column - if the column is referenced by any other object, it cannot simply be dropped. The referencing object must be altered first, then the column can be dropped.



        This is fairly easy to show by looking at the contents of the transaction log after dropping a column. The code below creates a table with a single 8,000 long char column. It adds a row, then drops it, and displays the contents of the transaction log applicable to the drop operation. The log records show modifications to various system tables where the table and column definitions are stored. If the column data was actually being deleted from the pages allocated to the table, you'd see log records recording the actual page data; there are no such records.



        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)


        (The output is too big to show here, and dbfiddle.uk won't allow me to access fn_dblog)



        The first set of output shows the log as a result of the DDL statement dropping the column. The second set of output shows the log after running the DML statement where we update the rid column. In the second result set, we see log records indicating a delete against dbo.DropColumnTest, followed by an insert into dbo.DropColumnTest. Each Log Record Length is 8116, indicating the actual page was updated.



        As you can see from the output of the fn_dblog command in the test above, the entire operation is fully logged. This goes for simple recovery, as well as full recovery. The terminology "fully logged" maybe misinterpreted as the data modification is not logged. This is not what happens - the modification is logged, and can be fully rolled back. The log is simply only recording the pages that were touched, and since none of the table's data-pages were logged by the DDL operation, both the DROP COLUMN, and any rollback that might occur will happen extremely quickly, regardless of the size of the table.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 4 hours ago

























        answered 5 hours ago









        Max VernonMax Vernon

        54k13 gold badges117 silver badges242 bronze badges




        54k13 gold badges117 silver badges242 bronze badges



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Database Administrators Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f241563%2fis-alter-table-drop-column-really-a-metadata-only-operation%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

            Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

            199年 目錄 大件事 到箇年出世嗰人 到箇年死嗰人 節慶、風俗習慣 導覽選單