4

У меня есть DB «DB_One» с главной таблицей с именем t_d_gate_out с 8 индексами на нем. Я создал еще одну БД с секционированным t_d_gate_out (назовем его «DB_Two»). Она была разделена на месяц и год (например, детский стола: t_d_gate_out09-2013), который имеет два индекса (d _gate_out и новый столбец на каждом ребенке: i_trx_own)Табличное разбиение на таблицы без разделов со многими индексами

Это моя функция создания и вставок дочерних таблиц:

CREATE OR REPLACE FUNCTION ctm_test.gateout_partition_function() 
    RETURNS trigger AS 
$BODY$ 
DECLARE new_time text; 
tablename text; 
seqname text; 
seqname_schema text; 
bulantahun text; 
bulan text; 
bulan2 text; 
tahun text; 
enddate text; 
result record; 

BEGIN new_time := to_char(NEW.d_gate_out,'MM-YYYY'); 
bulan:=to_char(NEW.d_gate_out,'MM'); 
bulan2:=extract(month from NEW.d_gate_out); 
tahun:=to_char(NEW.d_gate_out,'YYYY'); 
bulantahun := new_time; 
tablename := 't_d_gate_out'||bulantahun; 
seqname := 't_d_gate_out'||bulantahun||'_seq'; 
seqname_schema := 'ctm_test.t_d_gate_out'||bulantahun||'_seq'; 

PERFORM 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE 

c.relkind = 'r' AND c.relname = tablename AND n.nspname = 'ctm_test'; 

IF NOT FOUND THEN EXECUTE 'CREATE TABLE ctm_test.' || quote_ident(tablename) || ' (i_trx_own 

serial PRIMARY KEY, CHECK (extract(month from d_gate_out)=' || bulan2 || ' AND extract(year from 

d_gate_out)=' || tahun || ')) INHERITS (ctm_test.t_d_gate_out)'; 

EXECUTE 'ALTER TABLE ctm_test.' || quote_ident(tablename) || ' OWNER TO postgres'; EXECUTE 'GRANT 

ALL ON TABLE ctm_test.' || quote_ident(tablename) || ' TO postgres'; 

EXECUTE 'CREATE INDEX ' || quote_ident(tablename||'_indx1') || ' ON ctm_test.' || quote_ident 

(tablename) || ' (i_trx_own);CREATE INDEX ' || quote_ident(tablename||'_indx2') || ' ON ctm_test.' || quote_ident 

(tablename) || ' (d_gate_out)'; END IF; 

EXECUTE 'INSERT INTO ctm_test.' || quote_ident(tablename) || ' VALUES ($1.*)' USING NEW; RETURN 

NULL; END; $BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
ALTER FUNCTION ctm_test.gateout_partition_function() 
    OWNER TO postgres; 

И это мой TRIGGER:

CREATE TRIGGER gateout_master_trigger 
    BEFORE INSERT 
    ON ctm_test.t_d_gate_out 
    FOR EACH ROW 
    EXECUTE PROCEDURE ctm_test.gateout_partition_function(); 

После вставки около 200к строк, я пытался сравнить скорость просмотра данных между этими 2 DBS. Запрос я использовал для сравнения:

select * from ctm_test."t_d_gate_out" 
where d_gate_out BETWEEN '2013-10-01' AND '2013-10-31' 

результат после того, как я попытался выполнить этот запрос несколько раз, время исполнения были ПОЧТИ ТАКОЙ ЖЕ. Таким образом, секционированная таблица неэффективна для быстрого просмотра данных.
Правильно ли я делал раздел?

+0

200k - это не так много, мы делаем около 20 миллионов в день в разделе за один месяц, в результате чего от 450 до 500 миллионов записей на раздел таблицы. –

+0

Спасибо, сэр. Я не очень разбираюсь в этом разделе. Могу ли я получить данные ребенка, выполнив запрос на MASTER TABLE. Я имею в виду вот так, когда я выполняю: Выберите * из master_table, где дата BETWEEN '2013-10-01' AND '2013-11-31'. Выбраны ли данные из главной таблицы или из дочерних таблиц? Я все еще смущен работой этого раздела. Я просто знаю, что это один из способов сделать базу данных легче ... :(И если я хочу раздел по месяцам и годам, правильно ли я создал свою «ПРОВЕРКУ» ?? Спасибо, сэр :) - –

+0

Поскольку вы разбиваете с наследованием ('INHERITS (ctm_test.t_d_gate_out)', данные из всех дочерних таблиц включены в запрос SELECT в главной таблице. [Прочтите руководство] (http://www.postgresql.org/docs/current/ interactive/ddl-inherit.html). Используйте «SELECT ... FROM ONLY tbl', чтобы исключить детей: http://stackoverflow.com/questions/27881745/errorkey-is-not-present-in-table/27881996#27881996 ** ** CHECK ** ограничение: хотя верно, это очень неэффективно **. Сначала представьте свой код в ** читаемом формате **. –

ответ

1

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

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

Если ваш стол огромный и запросы в основном на несколько разделов, вы можете начать видеть выгоду. Индекс для небольшого раздела намного меньше и намного легче вписывается в ОЗУ (и остается там). ОЗУ является ключевым компонентом производительности (в дополнение к сопоставлению индексов).

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

Если вы в основном заинтересованы в производительности чтения, то partial indexes на одной большой таблице может быть альтернативой.

Кроме того, ваша функция триггера может быть улучшена в нескольких местах. Начните с более читаемом формате, и этот намек:

Относящиеся ответ с функцией запуска:

+0

Спасибо, сэр. Я не совсем понимаю об этом разделе. Могу ли я получить данные ребенка, выполнив запрос на MASTER TABLE. Я имею в виду, когда я выполняю: Выберите * from master_table, где дата BETWEEN '2013-10-01' AND '2013-11-31'. Данные, взятые из главной таблицы или из дочерних таблиц? Я все еще смущен работой этого раздела. Я просто знаю, что это один из способов сделать базу данных легче ... :( И если я хочу раздел по месяцам и годам, правильно ли я создал свою «ПРОВЕРКУ» ?? спасибо сэру :) –

1

200K строк не очень много.

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