Quantcast
Channel: SCN: Message List - SAP Adaptive Server Enterprise (SAP ASE) for Custom Applications
Viewing all articles
Browse latest Browse all 3587

Re: Efficient way to alter a large table with limited space on the server

$
0
0

NOTE: The following is an undocumented method which requires the direct update of the system table 'syscolumns'. All the usual disclaimers about "you are on your own if you screw this up" apply.

 

Yet another option you have available to you ... requires directly updating the syscolumns table and bouncing the dataserver.  [Definitely something you should test before implementing in production.]


First some background:

 

Different datatypes require different numbers of bytes for actual storage.  When accessing a data record the dataserver will use the contents of syscolumns to determine the offsets/lengths when parsing the string of bytes that make up the data record on a data page.

 

Let's see how many bytes are required for various numeric(#) columns ...

 

===========================

create table t1

(a numeric(10)   -- same as your identity column

,b numeric(11)

,c numeric(12)

,d numeric(13))

go

sp_help t1
go
Name Owner Object_type Object_status
---- ----- ----------- --------------
t1   dbo   user table  keep first tex

(1 row affected)
Column_name Type    Length Prec Scale
----------- ------- ------ ---- -----
a           numeric      6   10     0
b           numeric      6   11     0
c           numeric      6   12     0
d           numeric      7   13     0

===========================

 

Your current numeric(10)/identity column has a length of 6 (ie, requires 6 bytes).

 

From the t1 table we see that columns a/b/c, configured to use numeric(10/11/12) respectively, all have a length of 6 (ie, all require 6 bytes).  What this tells us is that you could define a column as numeric(10), numeric(11) or numeric(12) and you would end up using the same amount of storage space (ie, 6 bytes).  And it's this bit of info we can use to extend the size of your identity column.

 

Example:

In the following example I create a table with a numeric(10) column as the identity, insert a couple records, and show what happens if I try to set the 'next' ident value > 9,999,999,999 ...

 

===========================

create table t1

(a numeric(10) identity

,b varchar(30))

go

insert t1 (b) values ('a')

go

sp_chgattribute t1,'identity_burn_max',0,'9000000000'

go

insert t1 (b) values ('x')

go

select * from t1

go

a             b

------------- -

            1 a

   9000000001 x

 

-- try to set next ident to 10,000,000,000 (a numeric(11) value):

 

sp_chgattribute t1,'identity_burn_max',0,'10000000000'

go

 

Msg 12972, Level 16, State 1:

Server 'AIM1', Procedure 'sp_chgattribute', Line 1016:

Identity value '10000000000' overflow for table 't1'.

===========================

 

As expected, I can't set the 'next' ident to a value that does not fit within a numeric(10) column.

 

Since numeric(10) and numeric(12) require the same number of bytes for storage, we should be able to modify the ident column to use numeric(12) without requiring any additional space.

 

While we could trying using the alter tablecommand to change the ident column's datatype, this would require a datacopy of the entire table (basically the same thing that will occur for your select/into option).

 

The other option is to directly modify the syscolumns record for our ident column to change the precision from 10 to 12.  (Since numeric(10) and numeric(12) use the same number of bytes, we should be able to update syscolumns with no concern about corrupting the logic used to parse the string of bytes that make up the data record on a data page.)

 

===========================

sp_configure 'allow updates',1

go

begin tran

update syscolumns set prec = 12

where id = object_id('t1')

and name = 'a'

go

-- verify 1 row updated and prec = 12

-- if good then

commit tran

-- else

-- rollback tran

go

shutdown

go

 

-- restart dataserver

 

1> sp_help t1
2> go
Name Owner Object_type Object_status
---- ----- ----------- --------------
t1   dbo   user table  keep first tex

(1 row affected)
Column_name Type    Length Prec Scale
----------- ------- ------ ---- -----
a           numeric      6   12     0
b           varchar     30 NULL  NULL

 

sp_chgattribute t1,'identity_burn_max',0,'10000000000'

go

DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.

'identity_burn_max' attribute of object 't1' changed to 10000000000.

 

insert t1 (b) values ('z')

go

select * from t1

go

a               b

--------------- -

               1 a

      9000000001 x

     10000000001 z

===========================

 

Because I didn't increase the length (ie, # of storage bytes) for the ident column, I should able to safely access old rows because the offsets/lengths used for parsing the string of bytes that make up the data record haven't changed.

 

===========================

select * from t1 where a = 1
go
a               b
--------------- ------------------------------
               1 a

 

update t1 set b = 'zzz' where a = 1
go

select * from t1

go

a               b

--------------- ---

               1 zzz

      9000000001 x

     10000000001 z

===========================


Viewing all articles
Browse latest Browse all 3587

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>