Когда использовать унаследованные таблицы в PostgreSQL?



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



Я думал, что это работает так:



стол users, который имеет все поля, необходимые для всех уровней пользователей. Таблицы, как moderators,admins,bloggers, etc но поля не проверено у родителя. Например users есть поле email и унаследовал bloggers и сейчас тоже, но это не уникально для обеих users и bloggers в то же время. то есть. так же, как я добавляю поле электронной почты в обе таблицы.



только использование я мог думать о это поля, которые обычно используются, как row_is_deleted, created_at, modified_at. Это единственное использование для унаследованных таблиц?

788   8  

8 ответов:

есть несколько основных причин для использования наследования таблиц в postgres.

допустим, у нас есть несколько таблиц, необходимых для статистики, которые создаются и заполняются каждый месяц:

statistics
    - statistics_2010_04 (inherits statistics)
    - statistics_2010_05 (inherits statistics)

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

Итак, что делает наследование классной функцией - почему это круто разделить данные?

  • производительность: при выборе данных мы выбираем * из статистики, где дата между x и Y, а Postgres использует только таблицы, где это имеет смысл. Например. Выберите * из статистики, где дата между '2010-04-01' и '2010-04-15' только сканирует таблицу statistics_2010_04, все остальные таблицы не будут затронуты-быстро!
  • размер индекса: мы не имеем никакую большую жирную таблицу с большим жирным индексом на дате столбца. У нас есть небольшие таблицы в месяц, с небольшими индексами-быстрее читает.
  • обслуживание: мы можем побежать вакуум вполне, reindex, группа на каждой таблице месяца без фиксировать все другие данные

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

Я активно использую наследование таблиц, особенно когда речь заходит о хранении данных журнала, сгруппированных по месяцам. Намек: Если вы храните данные, которые никогда не изменятся (данные журнала), создайте или индексируйте с помощью CREATE INDEX ON () WITH (fillfactor=100); это означает, что в индексе не будет зарезервировано место для обновлений - индекс меньше на диске.

обновление: значение по умолчанию fillfactor равно 100, начиная сhttp://www.postgresql.org/docs/9.1/static/sql-createtable.html:

коэффициент заполнения для таблицы-это процент от 10 до 100. 100 (полная упаковка) по умолчанию

"таблица наследования" означает что-то другое, чем "наследования классов" и они служат разным целям.

Postgres-это все об определениях данных. Иногда действительно сложные определения данных. ООП (в общем Java-Цветном смысле вещей) - это подчинение поведения определениям данных в одной атомной структуре. Цель и значение слова "наследование" здесь существенно отличаются.

в ООП земли я мог бы определить (будучи очень свободно с синтаксисом и семантикой здесь):

import life

class Animal(life.Autonomous):
  metabolism = biofunc(alive=True)

  def die(self):
    self.metabolism = False

class Mammal(Animal):
  hair_color = color(foo=bar)

  def gray(self, mate):
    self.hair_color = age_effect('hair', self.age)

class Human(Mammal):
  alcoholic = vice_boolean(baz=balls)

таблицы для этого может выглядеть так:

CREATE TABLE animal
  (name       varchar(20) PRIMARY KEY,
   metabolism boolean NOT NULL);

CREATE TABLE mammal
  (hair_color  varchar(20) REFERENCES hair_color(code) NOT NULL,
   PRIMARY KEY (name))
  INHERITS (animal);

CREATE TABLE human
  (alcoholic  boolean NOT NULL,
   FOREIGN KEY (hair_color) REFERENCES hair_color(code),
   PRIMARY KEY (name))
  INHERITS (mammal);

но где же поведения? Они никуда не годятся. Это не является целью "объектов", поскольку они обсуждаются в мире баз данных, поскольку базы данных связаны с данными, а не с процедурным кодом. Вы можете написать функции в базе данных, чтобы сделать вычисления для вас (часто очень хорошая идея, но не совсем то, что подходит для этого случая), но функции не являются то же самое, что и методы-методы, понимаемые в форме ООП, о которых вы говорите, преднамеренно менее гибки.

есть еще одна вещь, чтобы указать на наследование как схематическое устройство: с Postgres 9.2 нет никакого способа ссылаться на ограничение внешнего ключа во всех разделах/членах семейства таблиц сразу. Вы можете написать чеки, чтобы сделать это или обойти его другим способом, но это не встроенная функция (это сводится к проблемам со сложным индексированием, действительно, и никто не написал биты, необходимые для того, чтобы сделать это автоматически). Вместо использования наследования таблиц для этой цели часто лучшим соответствием в базе данных для наследования объектов является создание схематических расширений для таблиц. Что-то вроде этого:

CREATE TABLE animal
  (name       varchar(20) PRIMARY KEY,
   ilk        varchar(20) REFERENCES animal_ilk NOT NULL,
   metabolism boolean NOT NULL);

CREATE TABLE mammal
  (animal      varchar(20) REFERENCES animal PRIMARY KEY,
   ilk         varchar(20) REFERENCES mammal_ilk NOT NULL,
   hair_color  varchar(20) REFERENCES hair_color(code) NOT NULL);


CREATE TABLE human
  (mammal     varchar(20) REFERENCES mammal PRIMARY KEY,
   alcoholic  boolean NOT NULL);

Теперь у нас есть каноническая ссылка на экземпляр животного, которую мы можем надежно использовать в качестве ссылки на внешний ключ, и у нас есть столбец "ilk", который ссылается на таблицу определений xxx_ilk, которая указывает на "следующий" таблица расширенных данных (или указывает, что их нет, если ilk является самим универсальным типом). Записи таблицы функций, представлений и т. д. против такого рода схемы настолько легко, что большинство фреймворков ORM делают именно такие вещи в фоновом режиме, когда вы прибегаете к наследованию класса в стиле ООП для создания семейств типов объектов.

наследование может использоваться в парадигме ООП до тех пор, пока вам не нужно создавать внешние ключи в родительской таблице. Например, если у вас есть абстрактный класс vehicle, хранящийся в таблице vehicle, и таблица car, которая наследует от нее, все автомобили будут видны в таблице vehicle, но внешний ключ из таблицы driver в таблице vehicle не будет соответствовать этим записям.

наследование также может использоваться как partitionning. Это особенно полезно, когда вы есть таблицы, предназначенные для вечного роста (таблицы журналов и т. д.).

основное использование наследования - это секционирование, но иногда это полезно в других ситуациях. В моей базе данных есть много таблиц, отличающихся только внешним ключом. Мой" абстрактный класс "таблица" изображение "содержит" идентификатор " (первичный ключ для него должен быть в каждой таблице) и растр PostGIS 2.0. Унаследованные таблицы, такие как "site_map" или "artifact_drawing" имеют столбец внешнего ключа (текстовый столбец"site_name" для "site_map", целочисленный столбец "artifact_id" для таблицы "artifact_drawing" и т. д.) и первичный и ограничения внешнего ключа; остальное наследуется от таблицы "изображение". Я подозреваю, что в будущем мне придется добавить столбец "описание" во все таблицы изображений, поэтому это может сэкономить мне довольно много работы, не создавая реальных проблем (ну, база данных может работать немного медленнее).

EDIT: другое хорошее использование: с обработка двух таблиц незарегистрированных пользователей, другие СУБД имеют проблемы с обработкой двух таблиц, но в PostgreSQL это легко-просто добавьте ONLY когда вы не заинтересованы в данных в унаследованной таблице "незарегистрированный пользователь".

единственный опыт, который я имею с унаследованными таблицами, заключается в разделении. Он отлично работает, но это не самая сложная и простая в использовании часть PostgreSQL.

на прошлой неделе мы искали ту же проблему ООП, но у нас было слишком много проблем с Hibernate (не понравилась наша настройка), поэтому мы не использовали наследование в PostgreSQL.

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

https://swth.ch/2016/12/03/postgresql-inheritance/

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

Пример: Предположим, вы хотите сохранить расположение объектов на карте с атрибутами x, y, вращение, масштаб.

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

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

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

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

Comments

    Ничего не найдено.