2010-06-19 2 views
3

Я создал набор секционированных таблиц в Документы на http://www.postgresql.org/docs/8.1/interactive/ddl-partitioning.htmlКак я вставлять и выбирать данные с секционированными таблицами?

CREATE TABLE t (year, a); 
CREATE TABLE t_1980 (CHECK (year = 1980)) INHERITS (t); 
CREATE TABLE t_1981 (CHECK (year = 1981)) INHERITS (t); 
CREATE RULE t_ins_1980 AS ON INSERT TO t WHERE (year = 1980) 
    DO INSTEAD INSERT INTO t_1980 VALUES (NEW.year, NEW.a); 
CREATE RULE t_ins_1981 AS ON INSERT TO t WHERE (year = 1981) 
    DO INSTEAD INSERT INTO t_1981 VALUES (NEW.year, NEW.a); 

В моем понимании, если я INSERT INTO т (год, а) VALUES (1980, 5), он будет идти к t_1980, и если я ВСТАВЯТСЯ в t (год, a) ЗНАЧЕНИЯ (1981, 3), он перейдет к t_1981. Но мое понимание кажется неправильным. Во-первых, я не могу понять следующее из документов.

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

Означает ли это, что, несмотря на установление ограничений CHECK и ПРАВИЛ, мне также необходимо создать TRIGGERs на главной таблице, чтобы INSERT перейдите к правильным таблицам? Если бы это было так, то какой смысл поддерживать разделение db? Я мог бы просто настроить отдельные таблицы самостоятельно? Я вставил кучу значений в главную таблицу, и эти строки все еще находятся в главной таблице, а не в унаследованных таблицах.

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

SELECT year, a FROM t WHERE year IN (1980, 1981); 

Update:. Кажется, я нашел ответ на мой собственный вопрос

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

Я действительно использовал COPY FROM для загрузки данных, поэтому ПРАВИЛА игнорировались. Попробуй с TRIGGER.

ответ

3

Определенно попробуйте триггеры.

Если вы считаете, что хотите реализовать правило, не делайте этого (единственное исключение - это обновляемые представления). См. Это great article by depesz для более подробного объяснения там.

В действительности Postgres поддерживает только разделение на стороне чтения вещей. Вы собираетесь настроить метод вставки в разделы самостоятельно - в большинстве случаев TRIGGERing. В зависимости от потребностей и приложений, иногда может быть быстрее научить ваше приложение вставлять непосредственно в разделы.

При выборе из разделенных таблиц вы действительно можете просто выбрать SELECT ... WHERE ... на главной таблице, если ваши ограничения CHECK правильно настроены (они приведены в вашем примере), и параметр constraint_exclusion устанавливается по-разному.

8,4:

SET constraint_exclusion = partition; 

< Для 8.4:

SET constraint_exclusion = on; 

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

1

Означает ли выше, что, несмотря на настройки ограничений CHECK, и правила, я также должен создать Триггеры на главном столе так, чтобы Вставки идти на правильные таблицы?

Да. Читать point 5 (section 5.9.2)

Если бы это было так, что бы точка дб опорной перегородки? Я мог бы просто настроить собственные таблицы ?

В принципе: ВСТАВКИ в дочерних таблицах должны выполняться явно (либо создавая TRIGGERS, либо задавая правильную дочернюю таблицу в запросе). Но разбиение прозрачно для SELECTS, и (учитывая преимущества хранения и индексирования этой схемы), это точка. (Кроме того, поскольку секционированные таблицы наследуются, схема наследуется от родителя, следовательно, выполняется последовательность ).

1

Триггеры определенно лучше правил. Сегодня я играл с разбиением материализованной таблицы представлений и сталкивался с проблемой решения триггеров. Почему? Я использую RETURNING и текущее решение возвращает NULL :) Но вот решение, которое работает для меня - исправьте меня, если я ошибаюсь. 1. У меня есть 3 таблицы, которые вставляются с некоторыми данными, есть вид (назовем его viewfoo), который содержит данные, которые должны быть материализованы. 2. Вставить в последнюю таблицу триггер, который вставляет в материализованную таблицу вида через INSERT INTO matviewtable SELECT * FROM viewfoo WHERE recno = NEW.recno; Это прекрасно работает, и я использую RETURNING recno; (recno - последовательность SERIAL).

Материализованный вид (таблица) необходимо разделить, потому что он огромен, и согласно моим тестам в этом случае, по крайней мере, на x10 быстрее для SELECT. Проблемы с разделением: * Текущее решение триггера RETURN NULL - поэтому я не могу использовать RETURNING recno. (Текущее решение триггера = триггер, объясненный на странице depesz).

Решение: Я изменил триггер моей 3 таблицы НЕ вставить в материализованном представлении таблицы (эта таблица является родителем секционированных таблиц), но создала новый триггер, который вставляет секционированной таблицы непосредственно из 3 таблицы и что триггер RETURN NEW. Материализованная таблица просмотра автоматически обновляется, а РЕЧЬ RECOM отлично работает. Буду рад, если это кому-нибудь поможет.