Когда использовать унаследованные таблицы в PostgreSQL? - PullRequest
73 голосов
/ 19 июня 2010

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

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

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

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

Ответы [ 7 ]

100 голосов
/ 19 июня 2010

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

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

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

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

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

  • PERFORMANCE: при выборе данных мы ВЫБИРАЕМ * ИЗ СТАТИСТИКИ, ГДЕ ДАТА МЕЖДУ x и Y, а Postgres использует только таблицы, где это имеет смысл. Например. ВЫБРАТЬ * ИЗ СТАТИСТИКИ, ГДЕ ДАТА МЕЖДУ '2010-04-01' И '2010-04-15' только просматривает таблицу statistics_2010_04, все остальные таблицы не будут затронуты - быстро!
  • Размер индекса: у нас нет большой таблицы жирностей с большим индексом жирности на дату столбца. У нас есть маленькие таблицы в месяц, с небольшими индексами - более быстрое чтение.
  • Техническое обслуживание: мы можем запустить полный вакуум, переиндексировать, кластеризовать таблицу каждого месяца, не блокируя все остальные данные

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

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

UPDATE: коэффициент заполнения по умолчанию: 100, от http://www.postgresql.org/docs/9.1/static/sql-createtable.html:

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

32 голосов
/ 23 апреля 2013

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

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

5 голосов
/ 20 июня 2010

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

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

3 голосов
/ 08 апреля 2013

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

РЕДАКТИРОВАТЬ: другое хорошее применение: при обработке двух таблиц незарегистрированных пользователей , другие СУБД имеют проблемы с обработкой двух таблиц, но в PostgreSQL это легко - просто добавьте ONLY, когда вас не интересуетв данных в унаследованной таблице «незарегистрированный пользователь».

2 голосов
/ 19 июня 2010

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

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

0 голосов
/ 13 февраля 2018

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

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

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

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

0 голосов
/ 16 января 2017

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...