Reputation: 953
I want to know about the storage SQL Server data types in memory.
How is the money
data type in SQL Server stored in memory? I know that money
is stored in 8 bytes and smallmoney
is stored in 4 bytes. But I don't know how?
For example when you have 123400.93 for the money, how is it stored in 8 bytes?
I have the same question about the decimal
and DATE
data types.
Especially for DATE
, the format is YYYY-MM-DD, but how is it stored in 3 bytes? Is it stored as described here: http://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html
or the number of days from a specific day is stored?
Upvotes: 9
Views: 6477
Reputation: 88064
Just adding a bit here...
A single byte
is made up of 8 bits
. A bit
can hold 2 values (0 or 1).
So 4 bytes is 32 bits (4 x 8). Which means the numeric range of what can be stored is from 0 to 2^32 which gives a total range of 4,294,967,296 values.
smallmoney
is signed so we drop one of the bits to be used for the sign, which leaves 2^31, or 2,147,483,648 possible values and the +/- sign.
Now we take into account that the last 4 digits of a money type are always after the decimal point and we end up with a range of -214,748.3648 to 214,748.3647
Technically, money and smallmoney values are stored by flipping bits in a word or byte just like everything else. If you need more info, read http://computer.howstuffworks.com/bytes.htm
Or you might see this for the possible value range of money and smallmoney: http://technet.microsoft.com/en-us/library/ms179882.aspx
update
For the DATETIME
data type, it's the same concept with a little twist. In MS SQL a DATETIME
is stored using 2 numbers. The first is number of days since 1/1/1900 and the second is number of ticks since midnight:
See
http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/how-are-dates-stored-in-sql-server and When storing a datetime in sql server (datetime type), what format does it store it in?
Upvotes: 10
Reputation: 1
How are the "money" [...] data types in SQL Server stored in memory?
If you want to see how is stored a MONEY (8 bytes) value then you could execute following script step/step:
CREATE DATABASE TestMoneyDT;
GO
USE TestMoneyDT;
GO
CREATE TABLE dbo.MyMoney -- :-)
(
Col1 CHAR(5) NOT NULL,
Col2 MONEY NOT NULL,
Col3 CHAR(5) NOT NULL
);
GO
INSERT dbo.MyMoney (Col1, Col2, Col3)
VALUES ('AAAAA',12345678.0009,'BBBBB');
GO
-- Install http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-sp_allocationmetadata-putting-undocumented-system-catalog-views-to-work/
EXEC sp_AllocationMetadata 'dbo.MyMoney'
GO
/*
Stored procedure output:
Object Name Index ID Alloc Unit ID Alloc Unit Type First Page Root Page First IAM Page
----------- -------- ----------------- --------------- ---------- --------- --------------
MyMoney 0 72057594039697408 IN_ROW_DATA (1:147) (0:0) (1:150)
*/
SELECT DB_ID() AS DBID
GO
/*
DBID
----
13
*/
-- Reading data from page (1:147) (file id 1, page number 147)
DBCC TRACEON(3604); -- http://technet.microsoft.com/en-us/library/ms187329.aspx
DBCC PAGE(13, 1, 147, 3); -- http://blogs.msdn.com/b/sqlserverstorageengine/archive/2006/06/10/625659.aspx
DBCC TRACEOFF(3604); -- http://technet.microsoft.com/en-us/library/ms174401.aspx
GO
-- See [Memory dump @0x0000000014AEA060] of DBCC PAGE output
/*
Memory Dump @0x000000000E76A060
0000000000000000: 10001600 41414141 41e9f698 be1c0000 †....AAAAAéö.¾...
0000000000000010: 00424242 42420300 00†††††††††††††††††.BBBBB...
41414141 41 = AAAAA <- Col1 CHAR(5)
e9f698 be1c0000 <- Col2 MONEY take this string and run following script (look at SumOverAll values)
424242 4242 = BBBBB <- Col3 CHAR(5)
*/
GO
DECLARE @HexString VARBINARY(8) = 0xE9F698BE1C; -- One MONEY value consumes 8 bytes
WITH N10
AS
(
SELECT *
FROM (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) x(Num)
)
SELECT src.*,
SUM(src.IntValueMultipliedByte) OVER() AS SumOverAll
FROM
(
SELECT n.Num,
SUBSTRING(@HexString, n.Num, 2) AS HexValue,
CONVERT(INT, SUBSTRING(@HexString, n.Num, 1)) AS IntValue,
POWER(CONVERT(NUMERIC(38,0), 256), n.Num-1) AS Byte,
CONVERT(INT, SUBSTRING(@HexString, n.Num, 1)) * POWER(CONVERT(NUMERIC(38,0), 256), n.Num-1) AS IntValueMultipliedByte
FROM N10 n
WHERE n.Num <= LEN(@HexString)
) src;
GO
/*
NumHexValue IntValue Byte IntValueMultipliedByte SumOverAll
----------- ----------- ---------- ---------------------- ------------
1 0xE9F6 233 1 233 123456780009
2 0xF698 246 256 62976 123456780009
3 0x98BE 152 65536 9961472 123456780009
4 0xBE1C 190 16777216 3187671040 123456780009
5 0x1C 28 4294967296 120259084288 123456780009
*/
Note: I used SQL2008R2.
Upvotes: 3
Reputation: 172448
I think you may find this interesting Performance / Storage Comparisons : MONEY vs. DECIMAL
The person arguing for MONEY showed the space used by MONEY compared to the same information stored in a DECIMAL(20,4) column. Not all that surprisingly, the latter was slightly larger. But is that the whole story? No, for two reasons. One is that the performance of these choices was not compared, and the other is that DECIMAL(20,4) is not a very realistic requirement for storing currency data. Unless you are storing the pricing information for luxury yachts or aircraft carriers, in which case you can probably drop the decimal places altogether and use INT or BIGINT. For the rest of us, a better choice would be DECIMAL(8,2) or DECIMAL(10,2).
Also check this related question: Should you choose the MONEY or DECIMAL(x,y) datatypes in SQL Server?
Upvotes: 1