Postgres: одна таблица с несколькими столбцами или несколько таблиц с меньшим количеством столбцов? - PullRequest
4 голосов
/ 02 февраля 2011

Мой вопрос связан с внутренними принципами работы Postgres:

У меня есть таблица:


CREATE TABLE A (
   id SERIAL,  
   name VARCHAR(32),
   type VARCHAR(32) NOT NULL, 
   priority SMALLINT NOT NULL,
   x SMALLINT NOT NULL,
   y SMALLINT NOT NULL,
   start timestamp with time zone,
   end timestamp with time zone,
   state Astate NOT NULL,
   other_table_id1 bigint REFERENCES W,
   other_table_id2 bigint NOT NULL REFERENCES S,
   PRIMARY KEY(id)
); 

с дополнительными индексами для other_table_id1, state и other_table_id2.

Таблица довольно большая и содержит очень много обновлений по столбцам: other_table_id1, state.Несколько обновлений для начального и конечного столбцов, но остальные являются неизменными.(Astate - это перечисляемый тип для состояния столбца.)

Мне интересно, имеет ли смысл разделять два наиболее часто обновляемых столбца на отдельную таблицу.То, что я надеюсь получить, это производительность, когда я просто просматриваю эту информацию, или чтобы уменьшить вес обновлений, потому что (возможно?) Чтение и запись более короткой строки дешевле.Но мне нужно сопоставить это со стоимостью объединений, когда им (иногда) необходимо иметь все данные для определенного элемента сразу.

В какой-то момент у меня сложилось впечатление, что каждый столбецхранится отдельно.Но позже я изменил свое мнение, когда где-то прочитал, что уменьшение ширины столбца на одной стороне таблицы положительно влияет на производительность при поиске данных с использованием другого столбца (поскольку строка хранится вместе, поэтому общая длина строки будетбыть короче).Теперь у меня сложилось впечатление, что все данные для строки физически хранятся вместе на диске;поэтому предложенное разделение таблицы звучит так, как будто это было бы полезно.Когда я в настоящее время пишу 4 байта для обновления состояния, могу ли я верить, что переписываю 64 байта текста (имя, тип), который на самом деле никогда не меняется?

Я не очень опытен с нормализацией таблицы "«Я не знаком с внутренностями Postgres, поэтому я ищу советы и особенно полезные практики для оценки компромисса без необходимости сначала выполнять работу, а затем определить, стоит ли эта работа.Изменение потребует немалых усилий при переписывании запросов, которые уже были высоко оптимизированы, поэтому я бы лучше понял, какого результата я могу ожидать.Спасибо, М.

Ответы [ 3 ]

4 голосов
/ 02 февраля 2011

Существует определенная стоимость обновления большего ряда.

Формула может помочь с этим. Если вы не разделите, ваши расходы

Стоимость = xU + yS

где:

U = обновление всей строки (таблица не разбита)

S = стоимость выбора

x, y = количество действий

Тогда, если вы разделите это, вы попытаетесь понять это:

Стоимость = gU1 + hU2 + xS1 + yS2

, где

U1 = обновление таблицы меньшего размера (более низкая стоимость)

U2 = обновление таблицы большего размера (более низкая стоимость)

S1 = выбрать из таблицы меньшего размера

S2 = выбрать из таблицы большего размера

g, h, x, y = как часто происходят отдельные действия

Так что, если g >> h, стоит их разбить. Особенно, если x >> y, тогда это действительно окупается.

РЕДАКТИРОВАТЬ: В ответ на комментарии, я бы также отметил, что эти затраты становятся гораздо более важными, если база данных находится под постоянной нагрузкой, без активности. Если вместо этого сервер не испытывает устойчивой нагрузки, он в основном неактивен с 1 или 2 trx в секунду, с длинными отрезками (где «long» = несколько секунд) бездействия, тогда, если бы это был я, я бы не усложнил мой код, потому что выигрыш в производительности не будет казаться реальной измеримой вещью.

2 голосов
/ 03 февраля 2011

Одна из деталей реализации Postgresql, которая имеет отношение к этому, заключается в том, что он никогда не «обновляет» строки, хранящиеся на диске, он всегда пишет новые версии.Таким образом, нет быстрого выигрыша, если в начале объединить столбцы фиксированной ширины, как в случае с Oracle, например (iirc).

Это правда, что группирование столбцов в разных таблицах основано на том, имеют ли ониобновление вместе может привести к меньшему количеству мусора, который необходимо пылесосить.Эксперимент и результаты измерений являются ключевыми здесь.Если у вас есть данные, которые часто обновляются, вам следует изучить, например, параметр «fillfactor» в таблице.Этот параметр заставляет PostgreSQL оставлять некоторое свободное пространство на страницах таблиц при вставке, что позволяет добавлять обновленные версии строк на ту же страницу, что и предыдущая версия, где это возможно: это может уменьшить нагрузку на обновление, поскольку это может означать, что индексы указывают настрока не должна обновляться, за счет того, что таблица занимает больше места на диске в целом.

Как уже упоминал Xaade, есть много материала, чтобы разобраться в этом вопросе.Я хотел бы подкрепить свой комментарий о необходимости измерения влияния любых внесенных изменений ... иногда то, что может показаться большой победой, оказывается нереальным.

0 голосов
/ 02 февраля 2011

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

Уменьшите влияние внутренних объединений, обманывая или позволяя просматривать столько строк одновременно.Вы можете обманывать, предоставляя интерфейс, вместо того, чтобы разрешать прямой поиск, отображая только внутренние объединенные данные на видимых строках (вы можете просматривать столько строк одновременно на экране), либо отображая дополнительные данные для выбранной в данный момент строки, либоразрешить только X строк для поиска с помощью кнопок обзора.Если вы используете чит, убедитесь, что вы кэшируете результаты расширенного поиска.

...