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

Откуда: Питер
Сообщений: 55
Всем привет,

Есть задача вставить столбец rowversion во все таблицы.
Размер данных базы данных критичен, мы даже переделывали недавно long на int, datetime(7) на datetime(3).

Возможно, вопрос глупый :)
Есть ли разница, куда лучше вставить столбец - в начало списка столбцов или в конец?

В конец списка вставлять удобнее :)
Где-то слышал такую вещь, что если в конце записи находятся много NULL значений, то они не занимают место.
А если в конце записи находится много NULL значений и в самом конце не-NULL значение, то эти NULL - значения начинают "занимать место".

Кто что скажет?
22 июл 13, 16:10    [14599913]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37254
Shrek2
Где-то слышал такую вещь, что если в конце записи находятся много NULL значений, то они не занимают место.
А если в конце записи находится много NULL значений и в самом конце не-NULL значение, то эти NULL - значения начинают "занимать место".
Вы еще больше там послушайте, узнаете заодно, что земля таки плоская.
22 июл 13, 16:18    [14599978]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Shrek2
Member

Откуда: Питер
Сообщений: 55
А что - земля не плоская??? Вот это да!!!

Гавриленко Сергей Алексеевич,
Не подскажете, где об этом написано? А то что-то не найду я.
Может это про Оракл было...
22 июл 13, 16:32    [14600056]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Shrek2
Где-то слышал такую вещь, что если в конце записи находятся много NULL значений, то они не занимают место.
А если в конце записи находится много NULL значений и в самом конце не-NULL значение, то эти NULL - значения начинают "занимать место".

Кто что скажет?

Скажу, что для Оракла это так.
А для MSSQL это не так.
22 июл 13, 16:34    [14600068]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Shrek2
Member

Откуда: Питер
Сообщений: 55
Гость333
Shrek2
Где-то слышал такую вещь, что если в конце записи находятся много NULL значений, то они не занимают место.
А если в конце записи находится много NULL значений и в самом конце не-NULL значение, то эти NULL - значения начинают "занимать место".

Кто что скажет?

Скажу, что для Оракла это так.
А для MSSQL это не так.


Спасибо, вселяете уверенность... Пойду, наверное, править скрипты
22 июл 13, 16:51    [14600148]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Гость333
Member

Откуда:
Сообщений: 3683
Shrek2
Не подскажете, где об этом написано?

Про Оракл — написано в букваре по Ораклу (Oracle Concepts):
http://docs.oracle.com/cd/E11882_01/server.112/e25789/tablecls.htm
Storage of Null Values

A null is the absence of a value in a column. Nulls indicate missing, unknown, or inapplicable data.

Nulls are stored in the database if they fall between columns with data values. In these cases, they require 1 byte to store the length of the column (zero). Trailing nulls in a row require no storage because a new row header signals that the remaining columns in the previous row are null. For example, if the last three columns of a table are null, then no data is stored for these columns.


Для MSSQL ссылку искать лень. Вот скрипт, создающий две таблицы. В первой таблице — один столбец с типом int и 1000 строк, во второй таблице — также 1000 строк, но два столбца с типами int и char(4000), заполнены null'ами. Разница в занимаемом месте налицо.
+
create table #x (id int);

begin transaction;
declare @i int;
set @i = 1;
while @i <= 1000
begin
  insert #x (id) values(@i);
  set @i = @i + 1;
end;
commit transaction;

exec tempdb..sp_spaceused '#x';

drop table #x;
go
create table #x (id int, s char(4000));

begin transaction;
declare @i int;
set @i = 1;
while @i <= 1000
begin
  insert #x (id, s) values(null, null);
  set @i = @i + 1;
end;
commit transaction;

exec tempdb..sp_spaceused '#x';

drop table #x
go
22 июл 13, 17:04    [14600217]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Ennor Tiegael
Member

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

В MSSQL значения NULL могут не занимать место только в случае, если эти столбцы определены как sparse columns. Вроде бы.
23 июл 13, 03:24    [14601910]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Shrek2
Member

Откуда: Питер
Сообщений: 55
Гость333,

Да, провел также свои эксперименты, немного меняя ваш скрипт.
В-общем, мои опасения были напрасны :)

Спасибо.
23 июл 13, 11:07    [14602794]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
andrey odegov
Member

Откуда:
Сообщений: 473
Гость333
Для MSSQL ссылку искать лень. Вот скрипт, создающий две таблицы. В первой таблице — один столбец с типом int и 1000 строк, во второй таблице — также 1000 строк, но два столбца с типами int и char(4000), заполнены null'ами. Разница в занимаемом месте налицо.
а если заменить на varchar?
+
set nocount on
create table #x (id int null default 0);
begin transaction;
go
insert #x (id) values(default);
go 1000
commit transaction;
exec tempdb..sp_spaceused '#x';
drop table #x;
go
create table #x (id int null default 0, s varchar(4000) null);
begin transaction;
go
insert #x (id, s) values(null, null);
go 1000
commit transaction;
exec tempdb..sp_spaceused '#x';
drop table #x
23 июл 13, 12:14    [14603287]     Ответить | Цитировать Сообщить модератору
 Re: Где разместить столбец rowversion.  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 37254
Если мне не изменяет память:
  • для типов фиксированного размера место выделяется в любом случае, null или нет;
  • для типов переменного размера место выделяется в соответствии с размером данных;
  • для каждого nullable-поля хранится один бит (null/not null), т.е. для каждых восьми nullable полей выделяется один байт.
  • 23 июл 13, 12:27    [14603377]     Ответить | Цитировать Сообщить модератору
     Re: Где разместить столбец rowversion.  [new]
    Гавриленко Сергей Алексеевич
    Member

    Откуда: Moscow
    Сообщений: 37254
    З.Ы. Char относится к полям фиксированного размера, а varchar - нет.
    23 июл 13, 12:28    [14603381]     Ответить | Цитировать Сообщить модератору
     Re: Где разместить столбец rowversion.  [new]
    Гость333
    Member

    Откуда:
    Сообщений: 3683
    andrey odegov
    а если заменить на varchar?

    Давайте заменим.
    +
    -- Попутно заменили кое-что ещё :-)
    set nocount on
    create table #x (a char(4039) null);
    begin transaction;
    go
    insert #x default values;
    go 1000
    commit transaction;
    exec tempdb..sp_spaceused '#x';
    drop table #x;
    go
    create table #x (a char(4039) null, b varchar(4000) null, c varchar(4000) null, d varchar(4000) null, e varchar(4000) null, f varchar(4000) null, g varchar(4000) null, h varchar(4000) null, i varchar(4000) null);
    begin transaction;
    go
    insert #x default values;
    go 1000
    commit transaction;
    exec tempdb..sp_spaceused '#x';
    drop table #x
    go
    
    23 июл 13, 12:30    [14603405]     Ответить | Цитировать Сообщить модератору
     Re: Где разместить столбец rowversion.  [new]
    Гость333
    Member

    Откуда:
    Сообщений: 3683
    Гавриленко Сергей Алексеевич
  • для каждого nullable-поля хранится один бит (null/not null), т.е. для каждых восьми nullable полей выделяется один байт.

  • Именно для nullable полей биты выделялись в какой-то старой версии. Начиная с 2005, биты выделяются для всех полей, даже для not null. Подтверждение этому можно найти, например, в BOL, в статьях "Estimating the Size of a Heap/Clustered Index". Там размер null bitmap определяется как "Null_Bitmap = 2 + ((Num_Cols + 7) / 8)", где "Num_Cols = total number of columns (fixed-length and variable-length)".
    23 июл 13, 12:37    [14603475]     Ответить | Цитировать Сообщить модератору
     Re: Где разместить столбец rowversion.  [new]
    andrey odegov
    Member

    Откуда:
    Сообщений: 473
    Гость333
    Давайте заменим.
    в первом случае в страницу легло 2 строки, а во 2 - одна, что подтверждается dbcc page. но ни в 1 ни во 2 вариантах колонок со значением null в записи строки на странице нет.
    +
    set nocount on
    --dbcc traceon(3604);
    create table #x (a char(4039) null default replicate('a',4039));
    begin transaction;
    go
    insert #x default values;
    go 1000
    commit transaction;
    --dbcc ind(tempdb,#x,-1)
    --dbcc page(tempdb,1,148,1);
    exec tempdb..sp_spaceused '#x';
    drop table #x;
    go
    create table #x (a char(4039) null default replicate('a',4039)
    , b varchar(4000) null
    , c varchar(4000) null
    , d varchar(4000) null
    , e varchar(4000) null
    , f varchar(4000) null
    , g varchar(4000) null
    , h varchar(4000) null
    , i varchar(4000) null);
    begin transaction;
    go
    insert #x default values;
    go 1000
    commit transaction;
    /*
    dbcc ind(tempdb,#x,-1)
    dbcc page(tempdb,1,114,1);
    
    SELECT name, column_id, max_inrow_length, pc.system_type_id, leaf_offset
    FROM tempdb.sys.system_internals_partition_columns pc
    JOIN tempdb.sys.partitions p
    ON p.partition_id = pc.partition_id
    JOIN tempdb.sys.columns c
    ON column_id = partition_column_id AND c.object_id = p.object_id
    WHERE p.object_id=object_id('tempdb..#x');
    
    SELECT object_id, type_desc,
    indexproperty(object_id, name, 'minlen') as minlen
    FROM tempdb.sys.indexes where object_id=object_id('tempdb..#x');
    */
    exec tempdb..sp_spaceused '#x';
    drop table #x
    
    23 июл 13, 13:50    [14604044]     Ответить | Цитировать Сообщить модератору
     Re: Где разместить столбец rowversion.  [new]
    Гость333
    Member

    Откуда:
    Сообщений: 3683
    andrey odegov,

    Да я понял, и произошло это из-за увеличения размера null bitmap с 3 байт до 4 байт :)
    Да, действительно, null'овые значения varchar не занимают места, причём неважно, находятся ли они в начале, конце или середине списка столбцов
    23 июл 13, 14:35    [14604442]     Ответить | Цитировать Сообщить модератору
     Re: Где разместить столбец rowversion.  [new]
    andrey odegov
    Member

    Откуда:
    Сообщений: 473
    а если во 2 варианте убрать одну колонку из b..i, то результаты выполнения sp_spaceused будут одинаковы.
    23 июл 13, 14:41    [14604479]     Ответить | Цитировать Сообщить модератору
    Все форумы / Microsoft SQL Server Ответить