powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / разница в размерах разных типов СУБД
21 сообщений из 21, страница 1 из 1
разница в размерах разных типов СУБД
    #38692790
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте. По роду своей деятельности используем 2 различных типа СУБД: MS SQL Server и PostgreSQL различных версий.
Структуры БД одинаковы. Данные также поступают одни и те же. Задачи решаются одинаковые. Но вызывает опасение разница в размерах БД. Для MS SQL Server - около 70 Гб (150-суточная информация), PostgreSQL около 30 Гб (10-суточная). Наиболее чувствительные объемы в таблицах, имеющих поля типа image (MS SQL Server) и bytea (PostgreSQL). Анализировал выборку данных из этих таблиц по количеству строк и размерам этих полей все нормально. Понимаю, что и способы хранения разные. Но уж очень чувствительная разница. Кто может помочь с ответом на данный вопрос?
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38692829
tadmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpcСтруктуры БД одинаковы. Данные также поступают одни и те же.
Индексы разные могут быть. Может вообще не быть индексов.
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38692848
Гость_0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alexpc,

вы сравниваете размер каталогов? Там же ещё WAL, временные файлы. Вообще postgres должен больше места занимать, такой у него формат хранения :-)
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38692852
Alexander A. Sak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так и получается, что PG больше занимает. У него 30Гб на 10 сутках против 70Гб на 150 сутках у MSSQL.
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38692940
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
спасибо за ответы. Немного поясню. Возьмем самую объемную по оличеству строк таблицу. Назовем ее tab. Она состоит из столбцов (по типам данных) bigserial, int, float, real, float, smallint - итог 38 байт. умножаем на количество строк 34 700 955. Едва больше гигабайта. А размер таблицы после вакуума и реиндексации 2.7 Гб + 3 индекса (всего) 4.8 Гб = 7.5 Гб. Напрягает 2.5 и 1. Индексы отдельная песня.
на всякий случай уточню. А после обслуживания WAL не чистится?
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38692945
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander A. Sak, почему так и получается, поясните пожалуйста?
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38693203
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38693406
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpcспасибо за ответы. Немного поясню. Возьмем самую объемную по оличеству строк таблицу. Назовем ее tab. Она состоит из столбцов (по типам данных) bigserial, int, float, real, float, smallint - итог 38 байт. умножаем на количество строк 34 700 955. Едва больше гигабайта. А размер таблицы после вакуума и реиндексации 2.7 Гб + 3 индекса (всего) 4.8 Гб = 7.5 Гб. Напрягает 2.5 и 1. Индексы отдельная песня.
на всякий случай уточню. А после обслуживания WAL не чистится?

так давайте по пунктам разбирать:
bigserial = bigint 8 байт
int 4 байт
float = double precision 8 байт
real = 4 байта
float = 8 байт
smallint = 2 байт
итого 34 байта данных
+ 24 байта обязательный заголовок строки (про который вы забыли)
+ 4байта в page header на строку
т.е. на строку выходит не 38 байта а 62 байта... 2.2GB получается что уже похоже на тот размер что у вас

А вот 3 индекса на 4.8GB это как то совсем много... можно структуру индексов привести ? (у вас каждый индекс почти в размер таблицы... это не совсем нормально).

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38693571
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk, одно поле int-овое я пропустил. Поэтому 38 байт. Что включает в себя заголовок строки? Имеется ввиду oid? И что такое page_header строки?
Индексы:
у нас построено для этой таблицы 3 индекса: первый - это счетчик, как Вы понимаете. второй - составной уникальный индекс по полю вторичного ключа (int, таблица является дочерней) и полю float. третий - составной также по полю вторичного ключа и полю с типом smallint для повышения скорости выборки информации всвязи со спецификой задачи. Все индексы BTREE.
Вообще индексы у нас много "весят". Как Вы, по-видимому понимаете, использование СУБД PostgreSQL стало вынужденной мерой после MS SQL Server, где данное построение индексов себя оправдывало.
Вообще, пскольку приходится работать только с сертифицированными в МО РФ СУБД, то есть некоторые ограничения (в т.ч. и на саму версию СУБД) Максимум - 9.1. Как СУБД ни крутим выжать из нее что-то в три-четверти от MS SQL не удается
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38693602
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpcMaxim Boguk, одно поле int-овое я пропустил. Поэтому 38 байт. Что включает в себя заголовок строки? Имеется ввиду oid? И что такое page_header строки?
Индексы:
у нас построено для этой таблицы 3 индекса: первый - это счетчик, как Вы понимаете. второй - составной уникальный индекс по полю вторичного ключа (int, таблица является дочерней) и полю float. третий - составной также по полю вторичного ключа и полю с типом smallint для повышения скорости выборки информации всвязи со спецификой задачи. Все индексы BTREE.
Вообще индексы у нас много "весят". Как Вы, по-видимому понимаете, использование СУБД PostgreSQL стало вынужденной мерой после MS SQL Server, где данное построение индексов себя оправдывало.
Вообще, пскольку приходится работать только с сертифицированными в МО РФ СУБД, то есть некоторые ограничения (в т.ч. и на саму версию СУБД) Максимум - 9.1. Как СУБД ни крутим выжать из нее что-то в три-четверти от MS SQL не удается\

Заголовок строки это заголовок строки... у любой строки в базе есть заголовок...
детально см: http://www.postgresql.org/docs/9.1/interactive/storage-page-layout.html

PS: структура страниц базы одна и таже что на 8.0 что на 9.4 так что 9.1 или 9.3 тут без разницы

PPS: 9.1.0 и 9.1.13 как говорится две большие разницы... и насколько я знаю политику сертифицирования в МО у вас наверняка что то уровня окаменевших остатков мамонта с многими десятками известных багов (и хуже того известных дыр)... или что то патченное неизвестно кем и неизвестно как.

PPPS: пришлите размеры ваших этих 3х индексов... я скажу нормальные они или нет...


--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38693624
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpc,

я тут у себя тестовый пример на 34M строк сделал... получается по размерам:

index bigint - 728 MB
int+float индекс - 875 MB
int+smallint индекс - 728 MB

явно никак 4.8 GB не получается... даже 2.4GB не получается...

поставьте create extension pgstattuple;

и напишие что у вас показывает

select * from pgstattuple('ваша таблица');
и
select * from pgstatindex('ваш индекс'); - для всех трех индексов

или у вас забытая неделю назад открытая транзакция висит и строк у вас в таблице реально куда больше чем вам кажется
или у вас патченая версия postgresql и тогда я ничем вам помочь не смогу боюсь...

(в первом случае это по выводу pstattuple будет сразу видно).

PS: Использование postgreSQL в госпроектах идея правильная... плохо что понимающих консультантов не привлекают... :)

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38693713
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk, ксожалению на низкой версии не ставится (не поддерживается) , а на более высокой, информации не так много (этот сервер справляется). Но тем не менее , показывает версий 2. avg_leaf_density - NaN , leaf_fragmentation - NaN
Что касается сертифицированных версий. Сналача продвигал PostgreSQL ВНИИНС. Они все время брали какие-то "несвежие" версии с сайта, сами проводили сборку и т.д. Когда выходила версия уже сертифицированная, она была уже неактуальной, в ней обнаруживались те же ошибки, что были опубликованы на сайте. Первоначально они даже пытались название СУБД прятать, но потом "забили". Они остановились на 8.3.7.
Нас больше заинтересовали разработки AstraLinux с имеющейся в ней СУБД PostgreSQL версии 8.4 - 9.1 (это последний вариант).
К сожалению 9.1 пока на объектах не используется.
Специалистов, если будет необходимо, можно всегда привлечь. Но, повторюсь, есть проблемы с сертифицированием версий, поэтому приходится "ехать" на том, что есть.
Что касается таблицы. Она действительно очень нагружена и , возможно, существует несколько версий содержащихся в ней строк. Грубо говоря, ее используют несколько задач. Первоначально информация записывается из сеанса. Затем происходит слияние нескольких сеансов в один и переподчинение по связке главному сеансу. Может происходить наоборот их разъединение. Ну, и вдобавок ко всему этим могут заниматься несколько пользователей.

Подскажите, возможно ли использовать СУБД PostgreSQL под хранилище данных. Др. словами, используя то, что есть, я смотрю в сторону облегчения БД путем сбрасывания устаревших данных в хранилище, оставляя только оперативную информацию.
Или же версия 9.1 обладает куда более высокими возможностями в части оперативности. Спасибо за ответы.
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694063
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk, я извиняюсь. У нас на сервере, где статистика установилась, никто ничего не считает, поэтому показатели нулевые. Я прочитал про pgstattuple. Установлю на низких версиях СУБД из дополнений, посмотрю и отвечу Вам. Извините за невежество.
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694515
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk, за половину дня размеры индексов менялись не существенно. Каждый из индексов оставался в пределах благоразумных , судя по pgstatindex. Размеры - 983146496, 700334080, 702513152. Однако размер индексов общий 3882 Мб, а не 2380 Мб.
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694533
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpcMaxim Boguk, за половину дня размеры индексов менялись не существенно. Каждый из индексов оставался в пределах благоразумных , судя по pgstatindex. Размеры - 983146496, 700334080, 702513152. Однако размер индексов общий 3882 Мб, а не 2380 Мб.

размерый индексов нормальные.
а вот как так "Однако размер индексов общий 3882 Мб, а не 2380 Мб" - вы когда цифры приводите приводите методологию как их получали... штатные телепаты все в отпуске.

еще раз прошу прислать результаты select * from pgstattuple('ваша таблица'); И для индексов тоже... а не вашу интерпретацию: "Каждый из индексов оставался в пределах благоразумных , судя по pgstatindex."

и \d+ ваша таблица

невозможно вам как то помочь если вы информацию вообще не выдаете...
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694633
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT 
     schemaname || '.' || indexname as name, 
     pg_size_pretty(pg_relation_size(schemaname || '.' || indexname)) as idxsize
   FROM 
     pg_indexes
   WHERE
     schemaname <> 'information_schema'
   ORDER BY
     pg_relation_size(schemaname || '.' || indexname) DESC
   LIMIT 10;



Результат:
"dbo.iux_izm","958 MB"
"dbo.uq_izm","958 MB"
...
"dbo.ix_izm","682 MB"
"dbo.ix2_izm","681 MB"
"dbo.pk_izm","681 MB"
...


Увидели что индексы дублируются в частности pk_izm у нас primary key и к нему создался еще индекс ix2_izm
и uq_izm уникальный к нему создался iux_izm это нормально? Вот код с PgAdmin :

Код: sql
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.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
CREATE TABLE izm
(
  id_izm bigserial NOT NULL,
  id_seans_itnp integer NOT NULL,
  time_izm double precision NOT NULL,
  interval_osr real NOT NULL,
  modificator smallint NOT NULL,
  value_par double precision,
  CONSTRAINT pk_izm PRIMARY KEY (id_izm),
  CONSTRAINT fk_izm__seans_itnp FOREIGN KEY (id_seans_itnp)
      REFERENCES seans_itnp (id_seans_itnp) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE CASCADE,
  CONSTRAINT uq_izm UNIQUE (id_seans_itnp, time_izm)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE izm
  OWNER TO postgres;

-- Index: iux_izm

-- DROP INDEX iux_izm;

CREATE INDEX iux_izm
  ON izm
  USING btree
  (id_seans_itnp, time_izm);

-- Index: ix2_izm

-- DROP INDEX ix2_izm;

CREATE INDEX ix2_izm
  ON izm
  USING btree
  (id_izm);

-- Index: ix_izm

-- DROP INDEX ix_izm;

CREATE INDEX ix_izm
  ON izm
  USING btree
  (id_seans_itnp, modificator)



Результаты выполнения запросов:

select * from public.pgstattuple('izm'::text)
table_len tuple_count tuple_len tuple_percent dead_tuple_count dead_tuple_len dead_tuple_percent free_space free_percent2432925696 31256285 2250452520 92.5 181460 13065120 0.54 30266500 1.25

select * from public.pgstattuple('iux_izm'::text)
table_len tuple_count tuple_len tuple_percent dead_tuple_count dead_tuple_len dead_tuple_percent free_space free_percent10074275843159083875818011275.2610914026193600.2610603692410.53

select * from public.pgstattuple('ix2_izm'::text)
table_len tuple_count tuple_len tuple_percent dead_tuple_count dead_tuple_len dead_tuple_percent free_space free_percent7167344643173506550776104070.840007392214410.31

select * from public.pgstattuple('ix_izm'::text)
table_len tuple_count tuple_len tuple_percent dead_tuple_count dead_tuple_len dead_tuple_percent free_space free_percent7173406723148919750382715270.2421810734897120.497507070810.47

Изначально размер смотрели в PgAdmine. То что создается два индекса на одно поле, так надо? Или можно один из них удалить?
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694658
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Результат \d+ izm:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
                     Table "dbo.izm"
    Column     |       Type       |                      Modifiers                       | Storage | Description
---------------+------------------+------------------------------------------------------+---------+-------------
 id_izm        | bigint           | not null default nextval('izm_id_izm_seq'::regclass) | plain   |
 id_seans_itnp | integer          | not null                                             | plain   |
 time_izm      | double precision | not null                                             | plain   |
 interval_osr  | real             | not null                                             | plain   |
 modificator   | smallint         | not null                                             | plain   |
 value_par     | double precision |                                                      | plain   |
Indexes:
    "pk_izm" PRIMARY KEY, btree (id_izm)
    "uq_izm" UNIQUE, btree (id_seans_itnp, time_izm)
    "iux_izm" btree (id_seans_itnp, time_izm)
    "ix2_izm" btree (id_izm)
    "ix_izm" btree (id_seans_itnp, modificator)
Foreign-key constraints:
    "fk_izm__seans_itnp" FOREIGN KEY (id_seans_itnp) REFERENCES seans_itnp(id_seans_itnp) ON DELETE CASCADE
Has OIDs: no
Has MACs: no
Use columns MACs: no
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694663
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpc,

"То что создается два индекса на одно поле, так надо?"
это ошибка того кто структуру базы дизайнил + непонимание того что и как в Pg устроено

1)"CONSTRAINT uq_izm UNIQUE (id_seans_itnp, time_izm)" - всегда буде создавать уникальный индекс по (id_seans_itnp, time_izm)
так что
CREATE INDEX iux_izm
ON izm
USING btree
(id_seans_itnp, time_izm);
не нужен

2)аналогично с парой pk_izm и ix2_izm

т.е. просто ошибка дизайнка из-за которой 2 лишних индекса образовалось
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694671
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpc,

оооо
авторHas MACs: no
Use columns MACs: no

в базовом postgresql такого нет... так что какой там размер tuple header у вас я не знаю но вполне может быть что на 8-16 байт больше... исходников этого (не)счастья я не видел поэтому могу только гадать:

у вас реальная длинна строки выходит 72 байта (по моим расчетам должно было быть 58 байт на стандартной базе)
так что да... еще 14 байт в заголовке...
итого у вас 38 байт заголовок и 34 байта данных на строку.... не удивительно что размер больше чем я ожидал....
особенно весело будет таблица из 1 инта сморется... 38 байт заголовка + 4 байта данных + округлить до 8 байт вверх - 48 байт на хранение 1 строки из1 инта...

PS: именно по этому я недолюбливаю когда все эти форки тут обсуждают так как у них куча своих граблей и ведут они себя регуляро не так как привычный postgres (а особенно весело когда задают вопрос не указывая что это не стандартный postgresql в заголовке темы).
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38694698
alexpc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk,

Ну откровенно говоря, мы не знали что это переделанный Postgres он везде отображается и ведет себя как PostgreSQL. Поэтому прошу меня извинить, если что было не точно сказано. Что такое форк я не знаю, поэтому не мог заранее сказать.

Спасибо большое за ответы!! Благодарю, что направили куда необходимо смотреть.
...
Рейтинг: 0 / 0
разница в размерах разных типов СУБД
    #38695330
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexpcMaxim Boguk,

Ну откровенно говоря, мы не знали что это переделанный Postgres он везде отображается и ведет себя как PostgreSQL. Поэтому прошу меня извинить, если что было не точно сказано. Что такое форк я не знаю, поэтому не мог заранее сказать.

Спасибо большое за ответы!! Благодарю, что направили куда необходимо смотреть.

В общем таблицы с узкими строками и большим количеством строк в PostgreSQL могут быть неожиданно дорогими.
Поэтому (хоть это и нарушение разнообразных нормальных форм) зачастую полезно (если есть возможность) группировать данные в одну строку (с использованием массивов для списков и/или json для более сложных структур).

Вот базовый тестовый пример:

есть таблица в миллион строк (2 поля integer pk + float value) созданная следующим образом:

create table table1 as select id, random() as val from generate_series(1,1000000) as g(id);
alter table table1 add primary key(id);

ее размер получается 55Mb

теперь предположим что у нас есть задача добавить для каждой записи поддержку расширяемого в будущем количества флагов флагов.
Для примера возьмем 16 флагов с номерами от 0 до 15. И опять же для примера возмьем шанст того что каждый из флагов установлен в 50%.

какие у нас есть варианты:

=========================================================================
вариант номер один (самый простой и самый часто применяемый):
create table table1_flags (id serial primary key, table1_id integer references table1(id), flag_id smallint);
create unique index table1_flags_uniq on table1_flags(table1_id, flag_id);

заполняем:
insert into table1_flags (table1_id, flag_id) select id, flag_id from table1 join generate_series(0,15) as g(flag_id) on random()>0.5;
получилось около 8M строк как и ожидалось...
размер таблицы table1_flags: 667 MB

т.е. добавление поддержки флагов нам обошлось в 667 байт !!!! на строку в table 1 (т.е. мы легким движением руки увеличили базу больше чем в 10 раз).


==========================================================================
варинат номер один с плюсом (чуть получше но почему то когда делают many to many постоянно зачем то добавляют искуственный PK):
учитываем что искуственный PK в этой задаче нам не нужен так как парал table1_id+flag_id прекрасно его заменяет
create table table1_flags (table1_id integer references table1(id), flag_id smallint, primary key (table1_id, flag_id));

заполняем:
insert into table1_flags (table1_id, flag_id) select id, flag_id from table1 join generate_series(0,15) as g(flag_id) on random()>0.5;
получилось около 8M строк как и ожидалось...
размер таблицы table1_flags: 500 MB

т.е. добавление поддержки флагов нам обошлось в 500 байт на строку... чуть лучше но всеравно рост в 10 раз... печально


==========================================================================
Вариант номер два (в принципе неплохой когда 16 флагов но становится ужасным когда флагов станет 100 да и alter table не добавляют радости)
Делаем по boolean полю на флаг:

create table table1 as select id, random() as val, case when random()>0.5 then true else false end as flag_0, case when random()>0.5 then true else false end as flag_1, case when random()>0.5 then true else false end as flag_2, case when random()>0.5 then true else false end as flag_3, case when random()>0.5 then true else false end as flag_4, case when random()>0.5 then true else false end as flag_5, case when random()>0.5 then true else false end as flag_6, case when random()>0.5 then true else false end as flag_7, case when random()>0.5 then true else false end as flag_8, case when random()>0.5 then true else false end as flag_9, case when random()>0.5 then true else false end as flag_10, case when random()>0.5 then true else false end as flag_11, case when random()>0.5 then true else false end as flag_12, case when random()>0.5 then true else false end as flag_13, case when random()>0.5 then true else false end as flag_14, case when random()>0.5 then true else false end as flag_15 from generate_series(1,1000000) as g(id);
alter table table1 add primary key(id);

Размер таблицы стал 71MB... т.е. добавление флагов в виде полей обошлось нам в 16MB или всего 16байт на строку (как и ожидалось).


==========================================================================
Вариант номер два с плюсом (пытаемся сэкономить на том что NULL занимает 1бит а не 1 байт даже для boolean и храним false как NULL... полезный фокус когда надо место экономить)
Делаем по boolean полю на флаг:

create table table1 as select id, random() as val, case when random()>0.5 then true else NULL::boolean end as flag_0, case when random()>0.5 then true else NULL::boolean end as flag_1, case when random()>0.5 then true else NULL::boolean end as flag_2, case when random()>0.5 then true else NULL::boolean end as flag_3, case when random()>0.5 then true else NULL::boolean end as flag_4, case when random()>0.5 then true else NULL::boolean end as flag_5, case when random()>0.5 then true else NULL::boolean end as flag_6, case when random()>0.5 then true else NULL::boolean end as flag_7, case when random()>0.5 then true else NULL::boolean end as flag_8, case when random()>0.5 then true else NULL::boolean end as flag_9, case when random()>0.5 then true else NULL::boolean end as flag_10, case when random()>0.5 then true else NULL::boolean end as flag_11, case when random()>0.5 then true else NULL::boolean end as flag_12, case when random()>0.5 then true else NULL::boolean end as flag_13, case when random()>0.5 then true else NULL::boolean end as flag_14, case when random()>0.5 then true else NULL::boolean end as flag_15 from generate_series(1,1000000) as g(id);
alter table table1 add primary key(id);

Размер таблицы стал 69MB... т.е. добавление флагов нам обошлось в 14MB или 14байт на строку.... чуть лучше


==========================================================================
Вариант номер 3... задумались о том что всетаки когда станет 100 флагов станет грустно в такой реализации и решили использовать массив флагов ( smallint[]) который легко расширяется на любое количество флагов
( http://www.postgresql.org/docs/9.3/interactive/arrays.html ):

create table table1 as select id, random() as val, array_agg(flag_id)::smallint[] from generate_series(1,1000000) as g1(id) join generate_series(0,15) as g2(flag_id) on random()>0.5 group by id;
alter table table1 add primary key(id);

Размер таблицы получился 93MB что конечно хуже заметно чем 69MB и добавило нам не 14байт на строку а 38байт на строку но зато позволило расширять количество флагов настолько насколько нам удобно...
Кстати этот метод стал бы сравним с методом два если бы было выставлено не 50% флагов а 10% (или меньше) флагов...
Я обычно рекомендую для такой задачи именно этот метод (кроме экстремальных случаев где надо каждый байт экономить).


===========================================================================
Вариант номер 4: пробуем скрестить расширяемость третьего подхода и экономичность второго... для экстремальных случаев когда строк очень много и байты надо экономить.
Используем тип bit string http://www.postgresql.org/docs/9.3/interactive/datatype-bit.html + http://www.postgresql.org/docs/9.3/interactive/functions-bitstring.html

create table table1 as select *, random() as val from (select id, sum(1::integer<<flag_id)::bit(16) as flags from generate_series(1,1000000) as g1(id) join generate_series(0,15) as g2(flag_id) on random()>0.5 group by id) as _t;
alter table table1 add primary key(id);

Размер таблицы получился 63MB т.е. обошлось оно нам в 8байт на строку... вот он святой грааль :))
===========================================================================


Внимание: Если флагов или потенциальных значений сотни (а тем более тысячи и больше) а реально выставлено из них 1-2-3 на строку - тогда вариант три будет выигрывать у всех других вариантов.

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

Надеюсь это будет полезно не только автору топика но и другим читателям форума.

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / разница в размерах разных типов СУБД
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]