3 detalhes pentelhos na instalação do Oracle 11.2.0.3 no Solaris 11
5 de Março de 2013, 0:00 - sem comentários aindaEste artigo foi escrito por telles
Tem coisas que a gente perde um tempo inútil pesquisando por um motivo idiota: a documentação não é clara. Sim, a garbosa documentação da Oracle também dá suas derrapadas.
- Você não precisa baixar os 6 arquivos do Oracle 11.2.0.3
O Oracle 11.2.0.3 não é exatamente um patchset é uma distribuição completa. E como tal tem 4.2GB. Mas você não precisa baixar todos eles, se for instalar apenas o banco, precisa apenas dos 2 primeiros. Veja o conteúdo deles:
- Oracle Database (includes Oracle Database and Oracle RAC)
p10404530_112030_platform_1of6.zip (1,3GB)
p10404530_112030_platform_2of6.zip (1,1GB) - Oracle Grid Infrastructure (includes Oracle ASM, Oracle Clusterware, and Oracle Restart)
p10404530_112030_platform_3of6.zip (710MB) - Oracle Database Client
p10404530_112030_platform_4of6.zip (622MB) - Oracle Examples
p10404530_112030_platform_5of6.zip (467MB) - Deinstall
p10404530_112030_platform_6of6.zip (116MB) - Você não edita mais o /etc/sysctl.conf para alterar as configurações do kernel. Você deve criar uma entrada no /etc/project com as configurações e associar estas configurações com o Oracle:
# Rodar como root antes de criar o usuário 'oracle', mas depois de criar os grupos 'dba' e 'oinstall'. projadd group.dba projmod -sK "project.max-shm-memory=(privileged,1G,deny)" group.dba projmod -sK "project.max-sem-ids=(privileged,100,deny)" group.dba projmod -sK "project.max-shm-ids=(privileged,100,deny)" group.dba projmod -sK "project.max-sem-nsems=(privileged,256,deny)" group.dba useradd -g oinstall -G dba -m -d /export/home/oracle -s /bin/bash -K project=group.dba oracle
Para conferir se tudo funcionou adequadamente, o teste a seguir deve ter resultados semelhantes:
# projects -l group.dba group.dba projid : 100 comment: "" users : (none) groups : (none) attribs: project.max-sem-ids=(privileged,100,deny) project.max-sem-nsems=(privileged,256,deny) project.max-shm-ids=(privileged,100,deny) project.max-shm-memory=(privileged,1073741824,deny) # id -p oracle uid=101(oracle) gid=100(oinstall) projid=100(group.dba)
- Você não precisa instalar patchs adicionais no SOLARIS 11 para instalar o Oracle. Se for instalar remoto precisa apenas do pacote SUNWxwplt. O pulo do gato está no passo extra, que é exportar a seguinte variável:
export AWT_TOOLKIT=XToolkit
Pronto, agora eu não esqueço mais.
[]s
O artigo 3 detalhes pentelhos na instalação do Oracle 11.2.0.3 no Solaris 11 apareceu primeiro em Savepoint.
Particionamento de Tabelas no postgres – automatizando
22 de Fevereiro de 2013, 0:00 - sem comentários aindaEste artigo foi escrito por telles
Já falamos um bocado sobre particionamento de tabelas por aqui:
- Particionamento de Tabelas no postgres – Quando?
- Particionamento de Tabelas no postgres – Como
- Particionamento de Tabelas no postgres – Detalhes
Para encerrar a série, vamos juntar tudo numa única função para tornar o dia-a-dia mais simples. Claro, se você tem poucas tabelas particionadas e se criar novas partições é algo raro, então você não deve se preocupar com isso. Assim sendo, sei que estou escrevendo para um público bem pequeno, mas que vem crescendo conforme o postgres sai do cantinho dos fundos dos grandes CPDs para ocupar cada vez mais uma posição de destaque. Bom, uma função genérica para qualquer tipo de particionamento daria muito trabalho para implementar, portanto a função que vou apresentar apresenta algumas características particulares que você pode adaptar para necessidades específicas se quiser:
- Eu utilizo uma tabela para cadastrar o nome das tabelas que serão particionadas e algumas informações específicas sobre o particionamento de cada uma destas tabelas. Assim a nossa função vai sempre varrer esta tabela e criar todas as partições cadastradas de uma vez só;
- A chave será sempre num campo do tipo INTEGER e cada partição utilizará um valor único na chave e não uma série de valores. Então vamos ter coisas como CHAVE = VALOR;
- A função está preparada para trabalhar com versões a partir do 8.3 do postgres. Se você utiliza versões anteriores a 8.3… realmente está na hora de você migrar. E veja se vai logo para o 9.2, pois as vantagens são realmente recompensadoras. Faremos algumas checagens dentro da função para saber com qual versão estamos lidando e fazer os ajustes necessários;
- Não iremos apenas criar as partições. Vamos aproveitar para já fazer algumas manutenções de acordo com as informações cadastradas na nossa tabela de partições.
Ao executar a função vamos executar as seguintes tarefas nesta ordem:
- Verifica se alguma FK de tabela não particionada aponta para uma tabela particionada;
- Carrega dados no cadastro de particionamento;
- Verifica se a tabela mãe cadastrada existe?
- Verifica se o tablespace existe;
- Verifica se a partição a ser criada já existe;
- Cria a partição da tabela;
- Ajusta parâmetros de STORAGE na partição criada;
- Remove restrição NO INHERIT da tabela filha;
- Importa os dados da tabela mãe para a partição;
- Cria CHECK CONSTRAINT para a chave da partição;
- Ajusta o dono da partição criada;
- Ajusta GRANTs para a partição criada;
- Cria ou substitui função do gatilho;
- Ajusta o dono da função;
- Verifica se o gatilho ja existe;
- Cria constraints para tabelas não particionadas;
- Arquiva partição antiga;
- Apaga partição arquivada antiga;
- Apaga partição antiga;
Agora vejamos a nossa tabela para cadastrar os parâmetros de todas tabelas que serão particionadas numa tacada só.
DROP TABLE IF EXISTS parametro_particao; CREATE TABLE parametro_particao ( nome_tabela_esquema varchar(64) NOT NULL, nome_tabela varchar(64) NOT NULL, nome_coluna_chave varchar(64) NOT NULL, nome_tablespace varchar(64) NOT NULL DEFAULT 'pg_default', qt_chave_ativa integer DEFAULT 5, qt_chave_excluir integer, qt_chave_desfilhar integer, ordem_criacao integer, CONSTRAINT parametro_particao_pk PRIMARY KEY (nome_tabela_esquema , nome_tabela ), CONSTRAINT parametro_particao_ck1 CHECK (qt_chave_ativa > 1), CONSTRAINT parametro_particao_ck2 CHECK (qt_chave_excluir > qt_chave_ativa AND qt_chave_excluir < 100), CONSTRAINT parametro_particao_ck3 CHECK (qt_chave_desfilhar > qt_chave_ativa AND qt_chave_desfilhar < 100) ); ALTER TABLE parametro_particao OWNER TO postgres; COMMENT ON TABLE parametro_particao IS 'Cadastro de tabelas particionadas e parâmetros de ajuste de manutenção das mesmas'; COMMENT ON COLUMN parametro_particao.nome_tabela_esquema IS 'Nome do esquema da tabela particionada'; COMMENT ON COLUMN parametro_particao.nome_tabela IS 'Nome da tabela particionada'; COMMENT ON COLUMN parametro_particao.nome_coluna_chave IS 'Nome do campo da tabela que será utilizado como chave para o particionamento'; COMMENT ON COLUMN parametro_particao.nome_tablespace IS 'Nome do tablespace onde a partição será criada'; COMMENT ON COLUMN parametro_particao.qt_chave_ativa IS 'Quantidade de chaves ativas no gatilho de INSERT da tabela mãe'; COMMENT ON COLUMN parametro_particao.qt_chave_excluir IS 'Quantidade de partições a serem mantidas. Serão mantidas "qt_chaves_apagar" com "no_coluna_chave" maiores, as demais serão excluídas. O valor NULL desativa a esclusão de partições'; COMMENT ON COLUMN parametro_particao.qt_chave_desfilhar IS 'Quantidade de partições a serem desfilhadas (deixar de ser uma partição filha da tabela mãe). Serão mantidas "qt_chaves_desfilhar" com "no_coluna_chave" maiores, as demais serão desfilhadas. O valor NULL desativa a desfilhação.'; COMMENT ON COLUMN parametro_particao.ordem_criacao IS 'Órdem de processamento das tabelas. Utilizado para respeitar as FKs das partições.';
Para testar, vamos utilizar as tabelas DETALHE e DETALHE_PEDIDO criadas nos posts anteriores:
INSERT INTO parametro_particao VALUES ('app', 'pedido', 'ano_pedido', 'pedido', 5, 99, 50, 1); INSERT INTO parametro_particao VALUES ('app', 'pedido_detalhe', 'ano_pedido', 'pedido_detalhe', 5, 99, 50, 2);
E la vai a pedrada… segue o código a função
-- Function: public.cria_particao_tabela(integer, boolean, boolean) DROP FUNCTION IF EXISTS public.cria_particao_tabela(integer, boolean, boolean); CREATE OR REPLACE FUNCTION public.cria_particao_tabela( IN p_next_partition_key integer, --Número da nova partição IN p_archive boolean, --Colocar como NO INHERIT tabelas marcadas com 'qt_chaves_desfiliar' IN p_drop boolean, --Apagar partições mais antigas que 'qt_chaves_apagar' OUT v_cod_erro text, --Mensagem de erro OUT v_pos_erro integer) --Posição do erro no código RETURNS record AS $BODY$ -- -- Descrição: Cria novas partições nas tabelas cadastradas em 'parametro_particao' -- Autor: Fábio Telles Rodriguez -- DECLARE v_sql text; v_tmp integer; c_pp record; c_part record; -- Pegar FKs de tabelas não particionadas que apontam para tabelas particionadas c_loop_const_fora CURSOR FOR SELECT tc.conname AS const FROM pg_constraint AS tc, pg_class AS c, pg_class AS r WHERE tc.contype = 'f' AND tc.conrelid = c.oid AND tc.confrelid = r.oid AND c.relname NOT IN (SELECT nome_tabela FROM parametro_particao) AND r.relname IN (SELECT nome_tabela FROM parametro_particao); -- Criar FKs de tabelas particionadas que apontam para outras tabelas particionadas c_loop_const_part CURSOR FOR SELECT 'ALTER TABLE ' || pp.nome_tabela_esquema || '.' || pp.nome_tabela || '_' || p_next_partition_key || ' ADD CONSTRAINT ' || conname || '_' || p_next_partition_key || ' ' || replace(pg_get_constraintdef(tc.oid), nr.nspname || '.' || r.relname, nr.nspname || '.' ||r.relname || '_' || 2008) || ';' AS alter_c FROM pg_constraint AS tc, pg_class AS c, pg_class AS r, pg_namespace AS nc, pg_namespace AS nr, WHERE tc.contype = 'f' AND tc.conrelid = c.oid AND nc.oid = c.relnamespace AND c.relname = pp.nome_tabela AND tc.confrelid = r.oid AND nr.oid = r.relnamespace AND EXISTS (SELECT 1 FROM parametro_particao rpp WHERE nr.nspname = rpp.nome_tabela_esquema AND r.relname = rpp.nome_tabela); -- Criar FKs de tabelas particionadas que apontam para tabelas não particionadas c_loop_constraint CURSOR ( p_table_schema varchar, p_table_name varchar) FOR SELECT 'ALTER TABLE ' || p_table_schema || '.' || p_table_name || '_' || p_next_partition_key || ' ADD CONSTRAINT ' || conname || '_' || p_next_partition_key || ' ' || pg_get_constraintdef(tc.oid) || ';' AS alter_c FROM pg_constraint AS tc, pg_class AS c, pg_class AS r, pg_namespace AS nc, pg_namespace AS nr, parametro_particao AS pp WHERE tc.contype = 'f' AND tc.conrelid = c.oid AND nc.nspname = p_table_schema AND nc.nspname = pp.nome_tabela_esquema AND nc.oid = c.relnamespace AND c.relname = p_table_name AND c.relname = pp.nome_tabela AND tc.confrelid = r.oid AND nr.oid = r.relnamespace AND NOT EXISTS (SELECT 1 FROM parametro_particao rpp WHERE nr.nspname = rpp.nome_tabela_esquema AND r.relname = rpp.nome_tabela); -- Criar condições na função do gatilho para demais partições já existentes c_loop_partitions CURSOR ( p_part_col varchar, p_table_schema varchar, p_table_name varchar, p_key_active integer ) FOR SELECT 'ELSIF ( NEW.' || p_part_col || ' = ' || replace(r.relname, c.relname || '_', '') || ') THEN ' || chr(10) || ' INSERT INTO ' || p_table_schema || '.' || r.relname || ' VALUES (NEW.*);' || chr(10) AS sql FROM pg_inherits i JOIN pg_class c ON i.inhparent = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid JOIN pg_class r ON i.inhrelid = r.oid WHERE c.relname = p_table_name AND n.nspname = p_table_schema AND r.relname != (p_table_name || '_' || p_next_partition_key) ORDER BY to_number(replace(r.relname, c.relname || '_', ''),'999999') DESC LIMIT p_key_active -1; c_loop_grant CURSOR ( p_table_schema varchar, p_table_name varchar) FOR SELECT 'GRANT ' || privilege_type || ' ON ' || table_schema || '.' || table_name || '_' || p_next_partition_key || ' TO ' || grantee || CASE is_grantable WHEN 'YES' THEN ' WITH GRANT OPTION' ELSE '' END || ';' sql FROM information_schema.table_privileges WHERE table_schema = p_table_schema AND table_name = p_table_name; -- Desfiliar partições com mais de 'qt_chave_desfiliar' além da última c_loop_arc CURSOR ( p_table_schema varchar, p_table_name varchar, p_key_arc integer) FOR SELECT 'ALTER TABLE ' || p_table_schema || '.' || r.relname || ' NO INHERIT ' || p_table_schema || '.' || p_table_name || ';' AS sql FROM pg_inherits i JOIN pg_class c ON i.inhparent = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid JOIN pg_class r ON i.inhrelid = r.oid WHERE c.relname = p_table_name AND n.nspname = p_table_schema ORDER BY to_number(replace(r.relname, c.relname || '_', ''),'999999') DESC OFFSET p_key_arc; -- Apagar partições com mais de 'qt_chave_excluir' além da última c_loop_drop CURSOR ( p_table_schema varchar, p_table_name varchar, p_key_drop integer) FOR SELECT 'DROP TABLE IF EXISTS ' || p_table_schema || '.' || r.relname || ';' AS sql FROM pg_inherits i JOIN pg_class c ON i.inhparent = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid JOIN pg_class r ON i.inhrelid = r.oid WHERE c.relname = p_table_name AND c.relkind = 'r' AND n.nspname = p_table_schema ORDER BY to_number(replace(r.relname, c.relname || '_', ''),'999999') DESC OFFSET p_key_drop; -- Carregar dados de parametro_particao c_tabelas CURSOR FOR SELECT nome_tabela_esquema AS tbl_sch, nome_tabela AS tbl_nom, nome_coluna_chave AS par_col, nome_tablespace AS tbs_def, qt_chave_ativa AS key_act, qt_chave_excluir AS key_drp, qt_chave_desfilhar AS key_arc, ordem_criacao AS tbl_ord FROM parametro_particao ORDER BY ordem_criacao; -- Chega de declarações, vamos trabalhar!!! BEGIN v_cod_erro := 0; v_pos_erro := 0; RAISE NOTICE 'cria_particao_tabela|Begin'; -- Verifica se alguma FK de tabela não particionada aponta para uma tabela particionada FOR c_part IN c_loop_const_fora LOOP v_pos_erro := 10; RAISE EXCEPTION 'cria_particao_tabela| A constraint % aponta para uma tabela particionada mas não será particionada também!!!', c_part.const; END LOOP; -- Carrega dados no cadastro de particionamento v_pos_erro := 20; FOR c_pp IN c_tabelas LOOP -- A tabela mãe existe? v_pos_erro := 30; SELECT 1 INTO v_tmp FROM information_schema.tables WHERE table_catalog = current_database() AND table_schema = c_pp.tbl_sch AND table_name = c_pp.tbl_nom; IF NOT FOUND THEN v_pos_erro := 40; RAISE EXCEPTION 'cria_particao_tabela|A Tabela Mãe % configurada em tbom_parametro_particao não existe', c_pp.tbl_nom; END IF; -- Verifica se o tablespace existe v_pos_erro := 50; SELECT 1 INTO v_tmp FROM pg_catalog.pg_tablespace WHERE spcname = c_pp.tbs_def; IF NOT FOUND THEN v_pos_erro := 60; RAISE EXCEPTION 'cria_particao_tabela|A tablespace para a particao da tabela % não existe', c_pp.tbl_nom ; END IF; -- Verifica se a particao da tabela ja existe v_pos_erro := 70; SELECT 1 INTO v_tmp FROM information_schema.tables WHERE table_name = c_pp.tbl_nom || '_' || p_next_partition_key AND table_schema = c_pp.tbl_sch; IF FOUND THEN v_pos_erro := 80; RAISE EXCEPTION 'cria_particao_tabela|A partição da tabela % com chave % de valor % já existe', c_pp.tbl_sch, c_pp.par_col, p_next_partition_key ; END IF; -- Cria a partição da tabela v_pos_erro := 90; RAISE WARNING 'cria_particao_tabela|Cria particao %', c_pp.tbl_nom || '_' || p_next_partition_key; v_sql := 'CREATE TABLE ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || '_' || p_next_partition_key || '(LIKE ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || ' INCLUDING STORAGE INCLUDING INDEXES INCLUDING DEFAULTS INCLUDING CONSTRAINTS ) INHERITS (' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || ') TABLESPACE ' || c_pp.tbs_def; v_pos_erro := 100; EXECUTE v_sql; -- Ajusta parâmetros de STORAGE na partição criada v_pos_erro := 110; SELECT 'ALTER TABLE ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || '_' || p_next_partition_key || ' SET (' || array_to_string(c.reloptions,',') || ');' AS sql INTO v_sql FROM pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid WHERE c.relname = c_pp.tbl_nom AND n.nspname = c_pp.tbl_sch; IF FOUND AND v_sql IS NOT NULL THEN v_pos_erro := 120; EXECUTE v_sql; END IF; -- Remove restrição NO INHERIT da tabela filha; -- ### Só funciona a partir da versão 9.2 ### v_pos_erro := 130; SELECT 'ALTER TABLE ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || '_' || p_next_partition_key || ' DROP CONSTRAINT ' || conname || ';' INTO v_sql FROM pg_constraint cc JOIN pg_class c ON cc.conrelid = c.oid AND cc.connamespace = c.relnamespace JOIN pg_namespace n ON c.relnamespace = n.oid WHERE connoinherit AND contype = 'c' AND c.relname = c_pp.tbl_nom AND n.nspname = c_pp.tbl_sch; IF FOUND AND v_sql IS NOT NULL THEN v_pos_erro := 140; EXECUTE v_sql; END IF; -- Remove restrição NO INHERIT da tabela filha; v_pos_erro := 150; v_sql := 'INSERT INTO ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || '_' || p_next_partition_key || ' SELECT * FROM ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || ' WHERE ' || c_pp.par_col || ' = ' || p_next_partition_key || ';'; IF FOUND AND v_sql IS NOT NULL THEN v_pos_erro := 160; EXECUTE v_sql; v_sql := 'DELETE FROM ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || ' WHERE ' || c_pp.par_col || ' = ' || p_next_partition_key || ';'; v_pos_erro := 170; EXECUTE v_sql; END IF; -- Cria CHECK CONSTRAINT para a chave da partição v_pos_erro := 180; v_sql := 'ALTER TABLE ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || '_' || p_next_partition_key || ' ADD CONSTRAINT ' || c_pp.tbl_nom || '_' || p_next_partition_key || '_check_' || p_next_partition_key || ' CHECK (' || c_pp.par_col || ' = ' || p_next_partition_key || ');'; EXECUTE v_sql; -- Ajusta o owner da partição criada v_pos_erro := 190; SELECT 'ALTER TABLE ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || '_' || p_next_partition_key || ' OWNER TO ' || a.rolname || ';' INTO v_sql FROM pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid JOIN pg_authid a ON c.relowner = a.oid WHERE c.relname = c_pp.tbl_nom AND n.nspname = c_pp.tbl_sch; v_pos_erro := 200; EXECUTE v_sql; -- Ajusta GRANTs para a partição criada v_pos_erro := 210; FOR c_part IN c_loop_grant(c_pp.tbl_sch, c_pp.tbl_nom) LOOP v_pos_erro := 220; EXECUTE c_part.sql; END LOOP; -- Cria ou substitui função do gatilho v_pos_erro := 230; -- Inicio da funcao v_pos_erro := 240; v_sql := 'CREATE OR REPLACE FUNCTION ' || c_pp.tbl_sch || '.fc_tg_' || c_pp.tbl_nom || '()' || chr(10) || 'RETURNS TRIGGER AS $$' || chr(10) || 'BEGIN' || chr(10) || chr(10); -- Regra para a nova particao v_pos_erro := 250; v_sql := v_sql || 'IF ( NEW.' || c_pp.par_col || ' = ' || p_next_partition_key || ') THEN ' || chr(10) || ' INSERT INTO ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || '_' || p_next_partition_key || ' VALUES (NEW.*);' || chr(10); -- Regra para as particoes ja existentes v_pos_erro := 260; IF c_pp.key_act IS NULL THEN c_pp.key_act = 100; END IF; v_pos_erro := 270; FOR c_part IN c_loop_partitions (c_pp.par_col, c_pp.tbl_sch, c_pp.tbl_nom, c_pp.key_act) LOOP v_pos_erro := 280; v_sql := v_sql || c_part.sql; END LOOP; -- Final da funcao v_pos_erro := 290; v_sql := v_sql || 'ELSE' || chr(10) || ' RAISE EXCEPTION ''Valor de chave inválida para o gatilho de INSERT na tabela %!'',' || c_pp.tbl_nom || ';' || chr(10) || 'END IF;' || chr(10) || chr(10) || 'RETURN NULL;' || chr(10) || 'END;' || chr(10) || '$$' || chr(10) || 'LANGUAGE plpgsql;'; v_pos_erro := 300; EXECUTE v_sql; -- Ajusta o owner função v_pos_erro := 310; SELECT 'ALTER FUNCTION ' || c_pp.tbl_sch || '.fc_tg_' || c_pp.tbl_nom || '()' || ' OWNER TO ' || a.rolname || ';' INTO v_sql FROM pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid JOIN pg_authid a ON c.relowner = a.oid WHERE c.relname = c_pp.tbl_nom AND n.nspname = c_pp.tbl_sch; v_pos_erro := 320; EXECUTE v_sql; -- Verifica se o gatilho ja existe v_pos_erro := 330; SELECT 1 INTO v_tmp FROM information_schema.triggers WHERE trigger_name = 'tg_' || c_pp.tbl_nom AND trigger_schema = c_pp.tbl_sch; IF NOT FOUND THEN -- Cria o gatilho na tabela mãe v_pos_erro := 340; v_sql := 'CREATE TRIGGER tg_' || c_pp.tbl_nom || chr(10) || 'BEFORE INSERT ON ' || c_pp.tbl_sch || '.' || c_pp.tbl_nom || chr(10) || ' FOR EACH ROW EXECUTE PROCEDURE ' || c_pp.tbl_sch || '.fc_tg_' || c_pp.tbl_nom || '();'; v_pos_erro := 350; EXECUTE v_sql; END IF; -- Cria constraints para tabelas não particionadas v_pos_erro := 360; FOR c_part IN c_loop_constraint(c_pp.tbl_sch, c_pp.tbl_nom) LOOP v_pos_erro := 360; EXECUTE c_part.alter_c; END LOOP; -- Arquiva partição antiga v_pos_erro := 370; IF p_archive AND c_pp.key_arc IS NOT NULL THEN FOR c_part IN c_loop_arc(c_pp.tbl_sch, c_pp.tbl_nom, c_pp.key_arc) LOOP v_pos_erro := 380; EXECUTE c_part.sql; END LOOP; END IF; -- Apaga partição antiga v_pos_erro := 390; IF p_drop AND c_pp.key_drp IS NOT NULL THEN FOR c_part IN c_loop_drop(c_pp.tbl_sch, c_pp.tbl_nom, c_pp.key_drp) LOOP v_pos_erro := 400; EXECUTE c_part.sql; END LOOP; END IF; END LOOP; v_pos_erro := 410; FOR c_part IN c_loop_const_part LOOP v_pos_erro := 420; EXECUTE c_part.alter_c; END LOOP; RAISE WARNING 'cria_particao_tabela|Fim'; EXCEPTION WHEN OTHERS THEN v_cod_erro := SUBSTR(SQLERRM,1,2000); RAISE WARNING 'cria_particao_tabela|ERRO!!! POS: %, COD: %, MSG: %', v_pos_erro, SQLSTATE, v_cod_erro; END; $BODY$ LANGUAGE plpgsql VOLATILE SECURITY DEFINER COST 100000;
E por fim o teste no psql:
teste=# set client_min_messages = warning; SET teste=# select cria_particao_tabela(2015, true, true); WARNING: cria_particao_tabela|Cria particao pedido_2015 WARNING: cria_particao_tabela|Cria particao pedido_detalhe_2015 WARNING: cria_particao_tabela|Fim cria_particao_tabela ---------------------- (0,420) (1 row)
Você pode adaptar este script para trabalhar com intervalos ou outros tipos de dados alem de inteiros. Se tiver alguma sugestão para melhorar… é só comentar aqui.
Bom, acho que chega de particionamento por enquanto.
O artigo Particionamento de Tabelas no postgres – automatizando apareceu primeiro em Savepoint.
Chamada de trabalhos para o PGBR2013
14 de Fevereiro de 2013, 0:00 - sem comentários aindaEste artigo foi escrito por telles
Senhores, a chamada de trabalhos para o PGBR2013 deve abrir daqui a pouco… está na hora de colocar a vergonha de lado e mostrar o que você aprendeu nesses 2 anos. Tem muita novidade legal pintando por aí e gente fazendo diabruras. Então está na hora de compartilhar um pouco disso conosco,
[]s
O artigo Chamada de trabalhos para o PGBR2013 apareceu primeiro em Savepoint.
Campus Party, o evento mais quente do Brasil
4 de Fevereiro de 2013, 0:00 - sem comentários aindaEste artigo foi escrito por telles
Fui no Campus Party apresentar minha humilde palestra “Postgres Wonderland” na quinta-feira 31/01/2013. Cheguei muito cedo, pois minha palestra era às 10h da manhã e justo ontem era o dia do meu rodízio, então cheguei antes das 7h. Não pude ficar até muito tarde, mas ainda assim deu para curtir um pouco o clima do evento.
Pontos positivos
- O espaço físico amplo do Anhembi foi bastante adequado para o evento. A disposição física das mesas, sofás e palcos também facilitou bastante a circulação;
- As mesas enormes com cabos de rede espalhados facilita muito a reunião de grupos, seja para fazer uma lan-party, para se dedicar a um projeto, criar uma empresa ou mesmo papear com os amigos;
- A existência de palcos com temas bem variados como robótica, astronomia, games, programação, segurança, software livre, conteúdo digital, etc;
- O clima descontraído do local. Não vi nenhum campuseiro de roupa social. Bermudas e chinelos compunham o visual básico lá;
- A proporção equilibrada entre o público masculino e feminino foi algo inédito para mim. Nunca vi um evento de informática tão bem frequentado. As Linuxchix ficariam com inveja, certamente;
- Os simuladores de avião e carros pareciam bem legais. Pena que não tive tempo de testar.
- Os casemods são sempre um espetáculo à parte.
- A ênfase ao empreendedorismo foi gritante. A presença do SEBRAE foi bem agressiva, mas eu acredito que foi bem positiva;
- Os 2 links de 30 gibabits… que trouxe o bordão “todo download vale a pena quando a banda não é pequena”. Destaque para a quantidade de upload que estava bem alto também;
- A organização e a segurança, com credenciamento de equipamentos, etiquetas com códigos de barra, detectores de metal e tudo o mais. Parece que o pessoal deixa seus equipamentos sobre a mesa sem se preocupar muito;
- Ter encontrado os também palestrantes Christiano Anderson e o Fernando Ike, com quem almocei na praça de alimentação. O Renka que foi quem me convidou para o evento eu não encontrei. Dizem que ele estava com uma mega ressaca do dia anterior…
- A diversidade de grandes nomes que palestraram lá. São pessoas que atraem os mais diferentes tipos de pessoas. De astronautas a criadores de games, de defensores da liberdade digital a grandes programadores.
- A turma de Software Livre do Campus Party, que estavam em frente ao palco Sócrates e estavam fazendo um grande trabalho por lá.
Claro, como todo grande evento, algumas coisas ruins foram encontradas:
- O mais óbvio de todos, o calor. O Anhembi é um lugar complicado. No inverno tem um vento gelado e cortante, no verão parece uma grande estufa coberta de metal. No palco as luzes da filmagem triplicaram o calor. Com 30 minutos de palestra eu estava esgotado com o calor e quase perdendo a voz;
- A ênfase aos vídeo games era latente. O campeonato mundial de World Of Warcraft foi o evento mais concorrido no período que eu estive lá; Claro, se eu tivesse 20 anos é bem provável que eu quisesse participar/acompanhar também.
- As buzinas que tocavam eventualmente atrapalham um bocado quem está concentrado. Particularmente o esquema de arenas abertas, sem paredes, torna o trabalho do palestrante mais desafiador. É bem mais difícil prender a atenção do público.
No geral eu gostei muito do evento. Tem uma pegada mais leve e descontraída. Não sei se é tudo aquilo que alguns divulgam ou imaginam, mas é realmente algo para se conhecer. Se eu puder, espero voltar no ano que vem com mais tempo. Acho que dá próxima vez, trago meus filhos, com certeza eles vão curtir bastante,
O artigo Campus Party, o evento mais quente do Brasil apareceu primeiro em Savepoint.
Postgres no Campus Party Brasil 2013
25 de Janeiro de 2013, 0:00 - sem comentários aindaEste artigo foi escrito por telles
Quem me conhece sabe que há alguns anos eu tenho participado quase que exclusivamente de eventos relacionados ao PostgreSQL, ou seja: PGDays e PGBR. Faz um bom tempo que não vou ao FISL e outros eventos mais genéricos. Ano passado, como não houve o PGBR, nós decidimos intensificar os PGDays e também criamos uma trilha de banco de dados no Latinoware 2012. O evento é bem diferente dos eventos mais focados que nós organizamos, mas não deixou de ser interessante. Lá pintou o convite para algo realmente diferente, o Campus Party.
Às vezes eu acho que já estou um pouco velho para esse tipo de evento. Já faz tempo que eu não saio para acampar e coisa e tal. Mas acho que temos que estar abertos a coisas diferentes e confesso que sempre tive curiosidade para conhecer o evento. Espero poder passear um pouco e conhecer um pouco da pegada da nova geração,
Para quem estiver no evento minha palestra será no palco Sócrates, 31/01 às 10h, com o título “Postgres Wonderland“
O artigo Postgres no Campus Party Brasil 2013 apareceu primeiro em Savepoint.