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

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

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

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

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

Ответ 1

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

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

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

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

Итак, что делает наследование непринужденной особенностью - почему приятно разбивать данные?

  • ПРОИЗВОДИТЕЛЬНОСТЬ: При выборе данных мы выбираем * FROM statistics WHERE date BETWEEN x и Y, а Postgres использует таблицы только там, где это имеет смысл. Например. SELECT * FROM statistics WHERE date BETWEEN '2010-04-01' AND '2010-04-15' только сканирует таблицу statistics_2010_04, все остальные таблицы не будут затронуты - быстро!
  • Размер индекса: у нас нет большой толстой таблицы с большим индексом жира в столбце. У нас небольшие таблицы в месяц, с небольшими индексами - быстрее читается.
  • Техническое обслуживание: мы можем запускать вакуумный полный, reindex, кластер на каждой таблице месяца без блокировки всех других данных.

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

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

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

Заполнитель для таблицы представляет собой процент от 10 до 100. 100 (полная упаковка) является значением по умолчанию

Ответ 2

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

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 делают именно это в фоновом режиме, когда вы прибегаете к наследованию класса ООП для создания семейств типов объектов.

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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