Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Чесстный размер decimal  [new]
SergASh
Member

Откуда:
Сообщений: 167
Привет всем!

BOL утверждает, что значения типов decimal занимают пять байт при точности от 1 до 9 включительно, а начиная с точности 10 уже требуется 9 байт.

Однако функция DATALENGTH показывает, что при точности 10 все ещё требуется только 5 байт, а 9 байт нужно начиная с точности 11:
declare @dec_9 decimal(9) = 123456789
declare @dec_10 decimal(10) = 1234567890
declare @dec_11 decimal(11) = 12345678901

select datalength( @dec_9 ) [decimal(9)]
      ,datalength( @dec_10 ) [decimal(10)]
      ,datalength( @dec_11 ) [decimal(11)]

Получаем
decimal(9)decimal(10)decimal(11)
559

Чему верить?
6 сен 15, 20:41    [18115981]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
o-o
Guest
да все честно написано,
макс. размер проверяется запихиванием макс. возможного числа.
поменяйте свое 1234567890 на десять девяток: 9999999999
и снова замерьте
6 сен 15, 22:11    [18116358]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
SergASh
Member

Откуда:
Сообщений: 167
o-o,

Интересно... Следует ли из этого, что если есть две таблицы
CREATE TABLE Small
(
  Payload DECIMAL(5)
)
CREATE TABLE Large
(
  Payload DECIMAL(38)
)

и в них вставляются одни и те же числа, то места они на диске будут занимать одинаково?
При условии отсутствия переполнения при вставке в Small, естественно.

Если да, то какой тогда вообще смысл указывать precision меньше максимального?
6 сен 15, 22:40    [18116457]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
invm
Member

Откуда: Москва
Сообщений: 9402
SergASh,

Не путайте размер данных и размер хранения
create table dbo.t(v1 decimal(9), v2 decimal(10));

insert into dbo.t values (1, 1);

select
 datalength(v1), col_length('dbo.t', 'v1'),
 datalength(v2), col_length('dbo.t', 'v2')
from
 dbo.t;

drop table dbo.t;
6 сен 15, 23:13    [18116541]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
o-o
Guest
SergASh
и в них вставляются одни и те же числа, то места они на диске будут занимать одинаково?
При условии отсутствия переполнения при вставке в Small, естественно.

Если да, то какой тогда вообще смысл указывать precision меньше максимального?

конечно же разный объем займет.
ведь decimal -- тип фиксированного размера.

в вашем примере я вставляю по 1000 одинаковых значений в каждую из таблиц.
в Large 5 страниц; 1 IAM и 4 с данными, по 296 строк на странице,
в Small 3 страницы; 1 IAM и 2 с данными, по 550 строк на странице.
вот код, можете сами проделать
CREATE TABLE Small
(
  Payload DECIMAL(5)
)
CREATE TABLE Large
(
  Payload DECIMAL(38)
)

insert into dbo.Small
values (9995);
go 1000

insert into dbo.Large
values (9995);
go 1000

EXEC ('DBCC IND ( db1, Large, -1)'  );
--PageFID	PagePID	IAMFID	IAMPID	ObjectID	IndexID	PartitionNumber	PartitionID	iam_chain_type	PageType	IndexLevel	NextPageFID	NextPagePID	PrevPageFID	PrevPagePID
--1	94	NULL	NULL	5575058	0	1	72057594038976512	In-row data	10	NULL	0	0	0	0
--1	93	1	94	5575058	0	1	72057594038976512	In-row data	1	0	0	0	0	0
--1	109	1	94	5575058	0	1	72057594038976512	In-row data	1	0	0	0	0	0
--1	110	1	94	5575058	0	1	72057594038976512	In-row data	1	0	0	0	0	0
--1	114	1	94	5575058	0	1	72057594038976512	In-row data	1	0	0	0	0	0

EXEC ('DBCC IND ( db1, Small, -1)'  );
--PageFID	PagePID	IAMFID	IAMPID	ObjectID	IndexID	PartitionNumber	PartitionID	iam_chain_type	PageType	IndexLevel	NextPageFID	NextPagePID	PrevPageFID	PrevPagePID
--1	89	NULL	NULL	2137058649	0	1	72057594038910976	In-row data	10	NULL	0	0	0	0
--1	78	1	89	2137058649	0	1	72057594038910976	In-row data	1	0	0	0	0	0
--1	90	1	89	2137058649	0	1	72057594038910976	In-row data	1	0	0	0	0	0

DBCC TRACEON (3604);
DBCC PAGE(db1, 1, 109, 3); -- Large: pminlen = 21                         m_slotCnt = 296 
DBCC PAGE(db1, 1, 78, 3);  -- Small: pminlen = 9                          m_slotCnt = 550  
6 сен 15, 23:23    [18116553]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
o-o
Guest
и размер записей соответственно:
Record Size = 24, Length (physical) 17
Record Size = 12, Length (physical) 5
6 сен 15, 23:31    [18116572]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
SimilarQuestion
Guest
Есть похожий вопрос про тип данных varchar(n). Из документации: "The storage size is the actual length of the data entered + 2 bytes". Функция DATALENGTH даёт результат без прибавления 2 байт (в приведённом примере 1 вместо 3):

declare @Value as varchar(5)
set @Value = 'a'
select DATALENGTH(@Value)


Кому верить?
7 сен 15, 15:19    [18119189]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
Glory
Member

Откуда:
Сообщений: 104760
SimilarQuestion
Кому верить?

Чиатать надо внимательнее хелп
The storage size is the actual length of the data entered + 2 bytes". - это размер хранения на диске. А не размер конкретного значения в отдельной записи
7 сен 15, 15:23    [18119217]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
SergASh
Member

Откуда:
Сообщений: 167
А в чем тогда физический смысл результата, который возвращает DATALENGTH() для DECIMAL типов?

Если я правильно понимаю, значение либо хранится в таблице, и тогда оно занимает свой storage size,
либо в переменной, которая на стеке будет расположена, и там тоже должно быть столько места, чтоб
хватило под максимальное допустимое значения заданного типа, то есть опять storage size.
17 сен 15, 15:02    [18161306]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
Glory
Member

Откуда:
Сообщений: 104760
SergASh
либо в переменной, которая на стеке будет расположена, и там тоже должно быть столько места, чтоб
хватило под максимальное допустимое значения заданного типа, то есть опять storage size.

И зачем для переменной иметь storage size ? если из памяти эта переменная никуда деться не может
17 сен 15, 15:15    [18161442]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
SergASh
Member

Откуда:
Сообщений: 167
Glory
И зачем для переменной иметь storage size ? если из памяти эта переменная никуда деться не может

Наверное затем, что анализируя код ХП невозможно в общем случае выяснить, какие значения будет переменная принимать в ходе выполнения.
Следовательно, если это стековая переменная, то под нее надо сразу выделять достаточное пространство в стеке.
А если она не стековая, то что, при каждом присваивании перевыделять память в куче?
17 сен 15, 15:23    [18161529]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
Glory
Member

Откуда:
Сообщений: 104760
SergASh
Наверное затем, что анализируя код ХП невозможно в общем случае выяснить, какие значения будет переменная принимать в ходе выполнения.
Следовательно, если это стековая переменная, то под нее надо сразу выделять достаточное пространство в стеке.
А если она не стековая, то что, при каждом присваивании перевыделять память в куче?

Еще раз вопрос - зачем для переменной, которая хранится в памяти, резервировать storage size ?
17 сен 15, 15:28    [18161554]     Ответить | Цитировать Сообщить модератору
 Re: Чесстный размер decimal  [new]
SergASh
Member

Откуда:
Сообщений: 167
Glory,

Мне кажется вы не прочитали что я ответил про стек. Ну вот пример
declare @var decimal(10)
set @var = 1
select datalength(@var)
set @var = 9999999999
select datalength(@var)

Наводящие вопросы:
  • @var одна и та же в обоих присваиваниях?
  • место под нее в стеке отведено один раз при запуске батча или дважды?
  • если один раз, то сколько нужно отвести, чтобы второе присваивание выполнилось без переполнения?
  • если переменная выделена не в стеке, а в куче, и в момент первого присваивания под нее отведено 5 байт, то как правильно обработать второе присваивание?
  • 17 сен 15, 16:08    [18161817]     Ответить | Цитировать Сообщить модератору
     Re: Чесстный размер decimal  [new]
    Glory
    Member

    Откуда:
    Сообщений: 104760
    SergASh
    Мне кажется вы не прочитали что я ответил про стек.

    Т.е. вы какой придуманный вами стек приравниваете к storage size ?
    17 сен 15, 16:38    [18161982]     Ответить | Цитировать Сообщить модератору
     Re: Чесстный размер decimal  [new]
    Jovanny
    Member

    Откуда:
    Сообщений: 1195
    SergASh,

    Вы так обеспокоены, сколько места займут переменные в стеке? Думаете, это окажет значительное влияние на производительность?
    17 сен 15, 16:46    [18162030]     Ответить | Цитировать Сообщить модератору
     Re: Чесстный размер decimal  [new]
    alexeyvg
    Member

    Откуда: Moscow
    Сообщений: 31435
    SergASh
    Следовательно, если это стековая переменная, то под нее надо сразу выделять достаточное пространство в стеке.
    А если она не стековая, то что, при каждом присваивании перевыделять память в куче?
    Думаю, что при веделении памяти для переменной выделяется размер, достаточный для хранения переменной максимального размера.
    И думаю, что это правило действует для всех типов, кроме BLOB.
    17 сен 15, 17:03    [18162155]     Ответить | Цитировать Сообщить модератору
     Re: Чесстный размер decimal  [new]
    SergASh
    Member

    Откуда:
    Сообщений: 167
    Glory, alexeyvg,

    Давайте оставим стек в покое.
    Все, что я хотел узнать, это в чем состоит физический смысл результата, который возвращает DATALENGTH() для DECIMAL типов.
    Буду признателен если кто-то сможет объяснить.
    17 сен 15, 19:00    [18162711]     Ответить | Цитировать Сообщить модератору
     Re: Чесстный размер decimal  [new]
    alexeyvg
    Member

    Откуда: Moscow
    Сообщений: 31435
    SergASh
    Все, что я хотел узнать, это в чем состоит физический смысл результата, который возвращает DATALENGTH() для DECIMAL типов.
    Буду признателен если кто-то сможет объяснить.
    declare @dec_10_1 decimal(10) = 1234567890
    declare @dec_10_2 decimal(10) = 9234567890
    
    select datalength( @dec_10_1 ) [decimal(10)]
          ,datalength( @dec_10_2 ) [decimal(10)]
    
    Функция datalength возвращает минимальное количество байт, которые необходимы для хранения значения выражения в данном базовом типе.

    Т.е. в общем для не-строковых типов эта функция не6 всегда возвращает осмысленое значение.

    http://dba.stackexchange.com/questions/7872/column-size-with-datatype-decimal
    17 сен 15, 19:53    [18162885]     Ответить | Цитировать Сообщить модератору
     Re: Чесстный размер decimal  [new]
    Glory
    Member

    Откуда:
    Сообщений: 104760
    SergASh
    Давайте оставим стек в покое.
    Все, что я хотел узнать, это в чем состоит физический смысл результата, который возвращает DATALENGTH() для DECIMAL типов.
    Буду признателен если кто-то сможет объяснить.

    BOL
    DATALENGTH (Transact-SQL)

    Returns the number of bytes used to represent any expression.
    17 сен 15, 20:34    [18162994]     Ответить | Цитировать Сообщить модератору
    Все форумы / Microsoft SQL Server Ответить