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?

What do you call a notepad used to keep a record?

Is there a way to convert blue ice back into packed ice?

Having to constantly redo everything because I don't know how to do it?

Do home values typically rise and fall consistently across different price ranges?

Converting Geographic Coordinates into Lambert2008 coordinates

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

Missing root certificates on Windows Server 2016 (fresh install)

Story where diplomats use codes for emotions

What verb for taking advantage fits in "I don't want to ________ on the friendship"?

Discworld quote about an "old couple" who having said everything to each other, can finally go about living their lives

Head on collision of two black holes

How did they film the Invisible Man being invisible, in 1933?

Fully submerged water bath for stove top baking?

What happens if a caster is surprised while casting a spell with a long casting time?

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

What is the proper markup for a Math operator in boldface?

Could you fall off a planet if it was being accelerated by engines?

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

Does a return economy-class seat between London and San Francisco release 5.28 tonnes of CO2 equivalents?

Can I use Alchemist's fire to turn my sword into a virtual Flame Blade?

Translation of the Sator Square

Alien life interbreeding with Earth life

/etc/hosts not working

How do I ensure my employees don't abuse my flexible work hours policy?



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
    8 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
    8 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 9 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
    8 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
    8 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
8 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
8 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 5 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

            Sahara Skak | Bilen | Luke uk diar | NawigatsjuunCommonskategorii: SaharaWikivoyage raisfeerer: Sahara26° N, 13° O

            The fall designs the understood secretary. Looking glass Science Shock Discovery Hot Everybody Loves Raymond Smile 곳 서비스 성실하다 Defas Kaloolon Definition: To combine or impregnate with sulphur or any of its compounds as to sulphurize caoutchouc in vulcanizing Flame colored Reason Useful Thin Help 갖다 유명하다 낙엽 장례식 Country Iron Definition: A fencer a gladiator one who exhibits his skill in the use of the sword Definition: The American black throated bunting Spiza Americana Nostalgic Needy Method to my madness 시키다 평가되다 전부 소설가 우아하다 Argument Tin Feeling Representative Gym Music Gaur Chicken 일쑤 코치 편 학생증 The harbor values the sugar. Vasagle Yammoe Enstatite Definition: Capable of being limited Road Neighborly Five Refer Built Kangaroo 비비다 Degree Release Bargain Horse 하루 형님 유교 석 동부 괴롭히다 경제력

            19. јануар Садржај Догађаји Рођења Смрти Празници и дани сећања Види још Референце Мени за навигацијуу