I am continuing my series of talks on fundamental topics like data types. I am proud to be a United States Army Reservist (USAR) Veteran.
Just like boot camp I went to so long ago, I am going nick name the series BASIC TRAINING.
The most basic unit of any database is a TABLE which consists of COLUMNS. A vital decision during the initial database design is to choose the data types that will capture the information you want in the least amount of space.
Today, I am exploring date and time fields.
I am extenting the sample database named [BASIC] that contains a sample schema named [TRAINING]. The snippet below creates a sample table named [DATE_N_TIME] that contains one or more fields for each data type.
Books online describes six data types that are categorized as date, time or the combination of both. I created a field for each type in our new table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span style="color: #008000; font-size: small;">-- -- Create test tables (various date/time types) -- -- Delete existing table IF EXISTS ( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[TRAINING].[DATE_N_TIME]') AND type in (N'U')) DROP TABLE [TRAINING].[DATE_N_TIME] GO -- Create new table CREATE TABLE [TRAINING].[DATE_N_TIME] ( DT1 DATE, -- 3 BYTES DT2 SMALLDATETIME, -- 4 BYTES DT3 DATETIME, -- 8 BYTES DT4 DATETIME2, -- VARIES BY PRECISIONS - BETWEEN 6 & 8 BYTES DT5 TIME, -- 5 BYTES DT6 DATETIMEOFFSET(7) -- 10 BYTES ); GO </span> |
We should test the new created table with values that show the minimum and maximum data points that can be stored.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span style="color: #008000; font-size: small;">-- Insert lower range min values INSERT INTO [TRAINING].[DATE_N_TIME] VALUES ( '0001-01-01', '1900-01-01 00:00:00', '1753-01-01 00:00:00.000', '0001-01-01 00:00:00.0000000', '00:00:00.0000000', '1900-01-01 00:00:00+00:00' ); GO -- Insert upper range max values INSERT INTO [TRAINING].[DATE_N_TIME] VALUES ( '9999-12-31', '2079-06-06 23:58:59', '9999-12-31 23:59:59.997', '9999-12-31 23:59:59.9999999', '23:59:59.9999999', '9999-12-30 23:59:59.9999999+00:00' ); GO -- Return the data from the table SELECT * FROM [TRAINING].[DATE_N_TIME]; GO </span> |
As a database designer, you should always question the components that make up your database.
One question that you might have is ‘What is the maximum number of bytes that a row can have?’. This is important because data is stored in the *.MDF or *.NDF files as pages ~ 8k. Since a page can only save 8060 bytes, you can figure out how many records can fit on a page and how many bytes are wasted space.
The following code uses the sys.columns table to count the number of fields and calculate the maximum row size.
1 2 3 4 5 6 7 8 9 10 11 |
<span style="color: #008000; font-size: small;">-- -- Maximum row length (num cols, max bytes) SELECT OBJECT_NAME (c.object_id) tablename, COUNT (1) nr_columns, SUM (c. max_length) maxrowlength FROM sys.columns AS c WHERE OBJECT_NAME(c.object_id) = 'DATE_N_TIME' GROUP BY OBJECT_NAME (c.object_id) ORDER BY OBJECT_NAME (c.object_id); </span> |
We can see that 6 columns in the table have a maximum record length of 38 bytes and 212 records will fit into one page. This leaves 4 bytes of wasted space on each data page. The sp_spaceused stored procedure shows us that 1 data and 1 index page has been allocated for the table. This is called a mixed extent.
1 2 3 |
<span style="color: #008000; font-size: small;">-- Real life numbers (pages/extents) EXEC sp_spaceused 'TRAINING.DATE_N_TIME'; </span> |
Last but not least, the sp_help stored procedure displays the details of the table. This includes many different settings that can be choosen as a DDL designer such as computed column, field length, nullabilty, and collation to mention a few.
1 2 3 4 5 |
<span style="color: #008000; font-size: small;"> -- Display size details of table EXEC sp_help 'TRAINING.DATE_N_TIME'; GO </span> |
In summary, when designing a table to use exact date time types, choose the data type that will allow the storage of the information in the least amount of space. Most people choose DATETIME (8 bytes) as the default instead of a SMALLDATETIME (4 bytes). Selecting the correct data type can amount in savings of up to 50%. Next time, I will be going over types classified as binary strings.
Itˇs in reality a great and useful piece of information. Iˇm glad that you simply shared this useful info with us. Please keep us informed like this. Thank you for sharing.