Комментарии 13
Тут все просто, дело в выравнивании. Если у вас 64-разрядная архитектура, то поля в записи, имеющие длину 8 байт и более, будут выровнены по 8 байт.
То есть, если поле имеет длину 8 байт или больше восьми байт, то оно будет выровнено по 8 байт.
Так процессор умеет быстрее читать их из памяти. Поэтому 4-байтные int нужно складывать рядом, тогда они будут занимать вместе 8 байт.
4 байта меньше чем 8 байт, а в предыдущем предложении сказано, что выровнены будут поля, которе больше. Либо там ошибка, либо я не совсем понял его смысл.
Я вообще думал, что по 8 байт выравниваются любые поля. Не важно, больше они или меньше.
Гм, кажется я понял свою ошибку. Там в таблице 3 поля — два по 4 байта и одно 8 байт. В задаче порядок такой — сначала поле в 4 байта, потом поле в 8 байт, потом опять поле в 4 байта.
Так как поля размером 8 байт или больше должны быть выровнены по 8 байт — между первым четырёхбайтным полем и вторым полем размером в 8 байт будет дырка в 4 байта. И можно поставить последнее четырёхбайтное поле в эту дырку, тем самым сэкономив 4 байта.
Можете посмотреть с помощью pageinspect, или в докладе Шаплова, упоминавшемся в Статье.
select pg_index_has_property('index_name_or_oid', 'clusterable');
В номинации "Лучшие вопросы" я бы выделил 3 и 4. Уж больно интересные и полезные
За статью спасибо!
Победители викторины получили промокоды, которые они могут ввести вместо оплаты участия в PgConf.Russia 2018
Есть ещё какие-то способы попасть на конференцию?
Взрывоопасность темы предпочтений в GUI и отсутствие согласия — одна из причин отсутствия GUI в коробке постгреса. Однако в Postgres Pro Enterprise нам предстоит выпустить и GUI-шное средство управления.
https://habrahabr.ru/company/pgdayrussia/blog/325642/
Я лично из комментариев к этой статьи открыл для себя DBeaver и теперь нарадоваться не могу.
SELECT * FROM heap_page_items(get_raw_page('t1', 0)) limit 1;
ERROR: block number 0 is out of range for relation «t1»
Вероятно стоит добавить что для этого требуется в таблицу вставить хотя бы один кортеж.
Я пытаюсь разобрать приведённый вами пример:
CREATE TABLE t1(x int, y int);
CREATE TABLE t2(x int not null, y int not null);
INSERT INTO t1 VALUES (1, 1)
SELECT * FROM heap_page_items(get_raw_page('t1', 0)) limit 1;
Вывод:
lp lp_off lp_flags lp_len t_xmin t_xmax t_field3 t_ctid t_infomask2 t_infomask t_hoff t_bits t_oid t_data ----- --------- ----------- --------- --------- --------- ----------- --------- -------------- ------------- --------- --------- -------- ---------------- 1 8160 1 32 4302 0 0 (0,1) 2 2048 24 (null) (null) 0100000001000000
INSERT INTO t2 VALUES (1, 1)
SELECT * FROM heap_page_items(get_raw_page('t2', 0)) limit 1;
Вывод:
lp lp_off lp_flags lp_len t_xmin t_xmax t_field3 t_ctid t_infomask2 t_infomask t_hoff t_bits t_oid t_data ----- --------- ----------- --------- --------- --------- ----------- --------- -------------- ------------- --------- --------- -------- ---------------- 1 8160 1 32 4303 0 0 (0,1) 2 2048 24 (null) (null) 0100000001000000
Абсолютно одинаковые.
Пробую вставит null значения:
INSERT INTO t1 VALUES (null, null)
SELECT * FROM heap_page_items(get_raw_page('t1', 0)) limit 1;
lp lp_off lp_flags lp_len t_xmin t_xmax t_field3 t_ctid t_infomask2 t_infomask t_hoff t_bits t_oid t_data ----- --------- ----------- --------- --------- --------- ----------- --------- -------------- ------------- --------- --------- -------- ---------------- 1 8160 1 32 4302 0 0 (0,1) 2 2048 24 (null) (null) 0100000001000000
И всё равно всё то же самое.
На каком основании сделать какая из них занимает меньше места?
P.S. Форматированный вывод, который выроятно будет удобнее смотреть: paste.fedoraproject.org/paste/z50hMUVlKZ4Idh0mgqTEBQ
Разбор задач викторины Postgres Pro на PGDay'17