Когда использовать унаследованные таблицы в 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
Используйте его как можно меньше. И это обычно означает, что это никогда не происходит, оно сводится к созданию структур, которые нарушают реляционную модель, например, нарушая принцип информации и создавая пакеты вместо отношений.