|
|
|
SSCrazy
      
Group: General Forum Members
Last Login: Sunday, November 04, 2012 12:23 PM
Points: 2,087,
Visits: 3,932
|
|
|
|
|
|
SSC-Dedicated
           
Group: General Forum Members
Last Login: Today @ 5:13 AM
Points: 32,906,
Visits: 26,793
|
|
Florian Reischl (5/17/2009)
Why?  I use this since about 5 years. Long time before I joined SSC 
Heh... ok... then 5 bucks for posting a cursor solution to a set based problem .
--Jeff Moden "RBAR is pronounced "ree-bar" and is a "Modenism" for "Row-By-Agonizing-Row".
First step towards the paradigm shift of writing Set Based code: Stop thinking about what you want to do to a row... think, instead, of what you want to do to a column."
For better, quicker answers on T-SQL questions, click on the following... http://www.sqlservercentral.com/articles/Best+Practices/61537/
For better answers on performance questions, click on the following... http://www.sqlservercentral.com/articles/SQLServerCentral/66909/
|
|
|
|
|
SSChampion
        
Group: General Forum Members
Last Login: Today @ 1:02 AM
Points: 10,989,
Visits: 10,534
|
|
Hey Jeff & Flo,
Just a couple of things... 
1. This isn't a true 'quirky' update unless there's a clustered index to determine the order of the ID assignment. It is true that the current SQL Server behaviour is always to return rows from heaps in insertion order (at least with a new heap that has never had any update or delete activity on it), but still.
2. This method runs in less than half the time (2005 only):
SET NOCOUNT ON
--===== Conditionally drop the test table for test reruns IF OBJECT_ID(N'tempdb..#my_tab', N'U') IS NOT NULL DROP TABLE #my_tab; IF OBJECT_ID(N'tempdb..#my_tab2', N'U') IS NOT NULL DROP TABLE #my_tab2;
--===== Build the test table and populate it with data on the fly SELECT TOP 100000 ISNULL(CAST(0 AS INT), 0) AS ID, DATEADD(mi,-ABS(CHECKSUM(NEWID())%100000),GETDATE()) AS Any_Date INTO #My_Tab FROM Master.dbo.SysColumns t1 CROSS JOIN Master.dbo.SysColumns t2 DECLARE @now DATETIME; SET @now = GETDATE();
-- Bulk logged *temporary* IDENTITY addition SELECT id = IDENTITY(INT, 1000, 1), any_date INTO #my_tab2 FROM #my_tab WITH (TABLOCK);
-- Fast clear of the original table TRUNCATE TABLE #my_tab;
-- Metadata only change ALTER TABLE #my_tab2 SWITCH TO #my_tab;
PRINT 'Duration for 100000 values: ' + CONVERT(VARCHAR(20), DATEDIFF(MILLISECOND, @now, GETDATE()));
-- Tidy up DROP TABLE #my_tab, #my_tab2;
Paul
Paul White SQL Server MVP SQLblog.com @SQL_Kiwi
|
|
|
|
|
SSChampion
        
Group: General Forum Members
Last Login: Today @ 1:02 AM
Points: 10,989,
Visits: 10,534
|
|
In case you guys think I'm cheating by changing the nullability of the id column, this version is a true replacement, and is just as fast:
SET NOCOUNT ON;
-- Conditional drops IF OBJECT_ID(N'tempdb..#my_tab', N'U') IS NOT NULL DROP TABLE #my_tab; IF OBJECT_ID(N'tempdb..#my_tab', N'U') IS NOT NULL DROP TABLE #my_tab2; IF OBJECT_ID(N'tempdb..#my_tab', N'U') IS NOT NULL DROP TABLE #my_tab3;
-- Sample data SELECT TOP (100000) CAST(NULL AS INT) AS ID, DATEADD(mi,-ABS(CHECKSUM(NEWID())%100000),GETDATE()) AS Any_Date INTO #My_Tab FROM master.sys.all_columns T1, master.sys.all_columns T2, master.sys.all_columns T3;
-- Start timing DECLARE @now DATETIME; SET @now = GETDATE();
-- Bulk logged identity add (id column is NOT NULL) SELECT id = IDENTITY(INT, 1000, 1), any_date INTO #my_tab2 FROM #my_tab WITH (TABLOCK);
-- Intermediate table for nullability change CREATE TABLE #my_tab3 (id INT NOT NULL, any_date DATETIME NULL);
-- Lose the IDENTITY attribute ALTER TABLE #my_tab2 SWITCH TO #my_tab3;
-- Metadata change to id column nullability ALTER TABLE #my_tab3 ALTER COLUMN id INT NULL;
-- Fast clear original table TRUNCATE TABLE #my_tab;
-- Metadata switch data in ALTER TABLE #my_tab3 SWITCH TO #my_tab;
-- Show duration PRINT 'Duration for 100000 values: ' + CONVERT(VARCHAR(20), DATEDIFF(MILLISECOND, @now, GETDATE()));
-- Tidy up DROP TABLE #my_tab, #my_tab2, #my_tab3;
Paul White SQL Server MVP SQLblog.com @SQL_Kiwi
|
|
|
|
|
SSChampion
        
Group: General Forum Members
Last Login: Today @ 1:02 AM
Points: 10,989,
Visits: 10,534
|
|
Jeff Moden (5/17/2009) .. if, for some reason, you cannot use IDENTITY and you're stuck with SQL Server 2000 or less which prevents the use of ROW_NUMBER and the like, then the "quirky" update Flo used is absolutely the fastest method available. Heh
Paul White SQL Server MVP SQLblog.com @SQL_Kiwi
|
|
|
|
|
SSC-Dedicated
           
Group: General Forum Members
Last Login: Today @ 5:13 AM
Points: 32,906,
Visits: 26,793
|
|
This isn't a true 'quirky' update unless there's a clustered index to determine the order of the ID assignment
I kind of agree and kind of don't. In the code Flo posted, order meant nothing. A clustered index was not required to establish the order. And, it's still a "quirky update" in that a 3 part SET statement was used... if you don't think so, ask an Oracle user. 
Paul White (9/6/2009)
Jeff Moden (5/17/2009) .. if, for some reason, you cannot use IDENTITY and you're stuck with SQL Server 2000 or less which prevents the use of ROW_NUMBER and the like, then the "quirky" update Flo used is absolutely the fastest method available.Heh 
Heh? Good idea and good code but you forgot to copy things like indexes, privs, restrictions, triggers, and named constraints to the new table. If I recall correctly, you may also need to find and recompile any views due to the table changes but that might only be if you change the number of columns or their datatypes. 
I will admit that even with those additions, the copy job you built may be quicker. I just can't verify your findings for the next week because I won't have access to an SQL computer for that time.
--Jeff Moden "RBAR is pronounced "ree-bar" and is a "Modenism" for "Row-By-Agonizing-Row".
First step towards the paradigm shift of writing Set Based code: Stop thinking about what you want to do to a row... think, instead, of what you want to do to a column."
For better, quicker answers on T-SQL questions, click on the following... http://www.sqlservercentral.com/articles/Best+Practices/61537/
For better answers on performance questions, click on the following... http://www.sqlservercentral.com/articles/SQLServerCentral/66909/
|
|
|
|
|
SSChampion
        
Group: General Forum Members
Last Login: Today @ 1:02 AM
Points: 10,989,
Visits: 10,534
|
|
Heh - because the whole thing was kinda jokey - a bit of fun for an otherwise fairly tedious Monday at work.
I agree with what you say about the quirkiness (order not being important) and about the object permissions, indexes, constraints and so on. But it was just funny - to me anyway 
Paul
Paul White SQL Server MVP SQLblog.com @SQL_Kiwi
|
|
|
|
|
SSChampion
        
Group: General Forum Members
Last Login: Today @ 1:02 AM
Points: 10,989,
Visits: 10,534
|
|
|
|
|
|
SSChampion
        
Group: General Forum Members
Last Login: Today @ 1:02 AM
Points: 10,989,
Visits: 10,534
|
|
|
|
|
|
SSCrazy
      
Group: General Forum Members
Last Login: Sunday, November 04, 2012 12:23 PM
Points: 2,087,
Visits: 3,932
|
|
|
|
|