Arquivo da categoria: database

Oracle 11G IMPDP – TRANSFORM – Caso Compress

Olá PessoAll,

Não sei se todos conheciam isso, eu particularmente nunca tinha usado, resolvi compartilhar.

Eu precisava fazer um import de um owner que atualmente está em tablespace normal, e tem suas tabelas normais para que ele fosse importado em uma outra tablespace e já comprimido (COMPRESS).

Fiz o export normalmente, sem nenhum segredo. Na hora do import que seriam realizadas as mudanças.

No import, a primeira coisa é que eu precisava era colocar as tabelas e índices numa nova tablespace. Para isso, usei o REMAP_TABLESPACE, até aí sem nenhum segredo.

Porém, como faria para que as tabelas fossem criadas comprimidas?

O atributo de COMPRESS, geralmente usado nas tabelas não tinha como ser mudado na hora do import.

As alternativas eram:

1 – Importar assim mesmo e fazer um Redefinition depois.

2 – Fazer o import com METADATA_ONLY e mudar as tabelas para COMPRESS, só que desse jeito os índices vão junto e na hora do import com os dados (DATA_ONLY) vai demora muito mais, estoura UNDO etc.

3 – Gerar o script de criação das tabelas, uma por uma, e criar manualmente apenas a tabela na nova tablespace e com COMPRESS e só depois soltar o IMPDP.

 

Baseado nas possibilidades pensadas… A alternativa mais interessante e que resolvia era a 3, mas ia dar um trabalho enorme…. uma a uma, criar na mão…. muito trabalho!

Um dos dons (se bem usado) do ser humano é a “preguiça produtiva”, e usei deste dom… em vez de fazer assim, saí pesquisando.

Nas buscas, descobri então que o atributo de COMPRESS pode ser como default na tablespace… Aí sim… só criar a tablespace e informar a cláusula: “…default compress for oltp”, e toda tabela criada na tablespace que não informar nada sobre compressão, será assumida a compressão da tablespace! Aêêêê!!! Resolveu!  \o/

Só que não!

Fiz o import, e ao verificar as tabelas, todas estavam sem compressão! Mesmo a tablespace estando com o default COMPRESSION FOR OLTP.

Dica: Se você tem dúvida de como verifica isso na tabela, assim é possível: select table_name, compression, compress_for from dba_tables where owner='SEU_OWNER_AQUI'

Quebrou meu esquema!

Lá vem a preguiça voltando novamente e lá vou eu pesquisar novamente.

Gastei mais um tempo de pesquisa e descobri o porquê das tabelas não obedecerem ao default da tablespace, lembram quando falei lá em cima: “e toda tabela criada na tablespace que não informar nada sobre compressão”, pois é…. SE não informar nada! Só que quando o expdp é feito, o script gerado de criação da tabela vem com o atributo NOCOMPRESS, porque no banco de origem a tabela de fato não era comprimida, na hora do import a tabela era criada com o atributo original contido no script, NOCOMPRESS!

Voltamos então para a solução 3, gerando o script dos create table, mudando o script de cada uma das tabelas e criando todas as tabelas manualmente, com COMPRESS… mas minha preguiça produtiva é resistente e resiliente… pesquisei mais um pouco, para fazer de forma mais inteligente… e achei o tal atributo TRANSFORM do IMPDP!

Vamos lá… no IMPDP, com o TRANSFORM, você pode exatamente mudar atributos dos objetos a serem criados na hora do IMPDP, ficando diferente do que foi gerado no banco de origem.

Para o meu caso, eu precisava apenas remover o tal NOCOMPRESS do script de criação, e dizer para o banco que as tabelas deveriam ir para uma tablespace nova, isso é possível adicionando as seguintes clausulas, combinadas, no meu comando de IMPDP:

...transform=segment_attributes:n remap_tablespace=TBS_OLD:TBS_NEW_COMPRESS...

Desta forma, os atributos do segmento que estavam no banco antigo (e no script do IMPDP) não serão utilizados, fazendo com que o default da nova tablespace seja usado.

E a preguiça vence novamente!! Tabelas criadas com COMPRESS FOR OLTP e import rolando.

Espero que seja útil para vocês.

Podemos usar isso, por exemplo, nos refresh de bases que fazemos com EXPDP/IMPDP, devemos economizar uma área razoável nas bases de desenvolvimento e homologação com esse método.

É uma ideia!

As notas que encontrei nas pesquisas foram:

Internet:

http://www.dba-oracle.com/t_impdp_transform_segment_attributes.htm

https://docs.oracle.com/cd/E11882_01/server.112/e22490/dp_import.htm#SUTIL939

Metalink:

How To Import The Non-Compressed Tables Into A Compressed Tablespace And Obtain Compress Target Tables? (Doc ID 2174751.1)

E….. só para constar, vi que no 12c, tem muito mais atributos que poderão ser usados com o TRANSFORM, como pode exemplo, não precisar ter default da tablespace, no próprio comando de IMPDP poderemos substituir o valor dos parâmetros, por exemplo, trocar o NOCOMPRESS por COMPRESS FOR OLTP, vejam mais detalhes aqui:

https://docs.oracle.com/database/121/SUTIL/GUID-64FB67BD-EB67-4F50-A4D2-5D34518E6BDB.htm#SUTIL939

 

É isso gente.

Espero ter ajudado!

 

Abraços!

Cursos Oficiais Oracle com desconto

Fala PessoAll,

Atendendo ao pedido de um leitor do Site, o amigo Lander Poolk S. Herrera estou publicando estas ofertas da Oracle para cursos oficiais.

Tem diversos cursos interessantes e com descontos bem convidativos. Talvez seja a sua chance de fazer um curso oficial pagando menos ou sua chance de conseguir convencer seu chefe a liberar a verba para seu treinamento.

Só lembrando que para tornar-se OCP você precisa obrigatoriamente ter um curso oficial, então, é uma chance de já atender a este requisito.

Este é o link da Oracle sobre os treinamentos, tem tudo detalhado, turmas, descontos, etc.

Noticias sobre Capacitación y Certificación Oracle Database

 

Como dica: Acabei de fazer um treinamento oficial em São Paulo, no Centro de Treinamento En-Sof. O centro é bem interessante, tem uma boa estrutura, salas agradáveis e com bons equipamentos.

Além do local, o que interessa muito em um treinamento é o instrutor. O material a ser seguido e o ambiente do curso é tudo “engessado” pela Oracle, o que vai fazer a diferença é o instrutor que pode ser um simples “Leitor de slides” , ou pode ser um cara de mercado, com conhecimento e boa didática. Portanto, antes de fazer o treinamento, procure saber quem é o instrutor, pegue referências dele e verifique se é uma boa “aquisição”.

 

Abraços a todos!

 

Atc.

Gerson Júnior

gerson.vasconcelos@gmail.com

Erro na Instalação – 10.2.0.1 – OUI-10094

Olá PessoALL,

Ontem tive uma necessidade de instalação do Oracle 10gR2 em um cliente. Isso mesmo, estamos em 07/2013, e precisamos instalar um Oracle 10gR2! rsrs. Deixa eu contar um pouco da história:

O banco de produção é um 9.2.0.6 (acharam que não podia ser pior que o 10gR2 né), rodando em um HP-UX Itanium 64bits e que não tem mais suporte por parte da HP, ou seja, temos que nos virar com o que temos para migrar este banco de 9.2.0.6 urgente! Afinal, não temos mais suporte nem do banco nem da máquina onde ele está instalado. Depois de muitas e muitas tentativas de migração, inclusive usando Golden Gate em que não tivemos sucesso, a opção menos pior encontrada foi expdp e impdp, só que para isso precisávamos estar pelo menos no 10g! Sei que deve estar se perguntando… porque não 11g direto? Lembram que a máquina não tem mais suporte? Pois é, para instalar o 11g neste servidor, mesmo sendo certificado, precisava instalar alguns pacotes, e claro que sem suporte, sem contrato e sem nada, a HP não iria dar de mão beijada estes pacotes para nos ajudar a deixar de usar a plataforma deles! Por isso a escolha do passo a passo foi:

1 – Instalar o Oracle 10GR2, 10.2.0.1.

2 – Aplicar o Patchset 10.2.0.4 e eliminar alguns possíveis bugs.

3 – Migrar o banco 9.2.0.6 para 10.2.0.4.

4 – Fazer expdp paralelizado para extrair os dados.

5 – Fazer impdp no novo, querido e parrudo servidor Linux com Oracle 11gR2!

Então, já no passo 1 encontramos um problema, o erro: OUI-10094.

A instalação ocorria normalmente, todas as configurações eram feitas e dava erro apenas na hora de registrar no inventário.

Pois é, na parte mais simples ocorria o erro.

Pesquisando no Metalink, encontrei uma nota que falava a respeito, em que a Oracle assumia sem nenhum pudor que o instalador do 10.2.0.1, versão base do 10gR2 tinha um “bug” que não conseguia fazer atualização de inventário caso tivessem outros Oracle Home´s  instalados com outros owners na mesma máquina. Por exemplo:

Tenho um Oracle 9.2.0.6 instalado com o owner ora96.

Tenho um Oracle 10gR1 instalado com o owner ora101.

No momento de instalar o Oracle 10gR2 com o owner ora102, ele vai ter que adicionar no inventário esta nova instalação, mas… quem criou o inventário não foi o owner ora102, por isso ocorre o problema, mas é um problema no instalador.

O grande aprendizado que quero passar neste post é sobre a recomendação da Oracle para corrigir o problema, que basicamente foi: “Instale o Oracle 10.2.0.1 com o instalador do 10.2.0.4!”, então, na hora de chamar o runInstaller, usar o executável da versão 10.2.0.4 chamando a instalação do 10.2.0.1. Como fazer isso… assim:


[ora10g@srvhp:/home/ora10g]: cd /ora10g/install/patch_10204/disk1/
[ora10g@srvhp:/home/ora10g]: ./runInstaller FROM_LOCATION="/ora10g/install/10201/disk1/stage/products.xml"

Então, o que fizemos foi ir até a pasta de instalação do Patchset 10.2.0.4 e chamar o instalador dele, só que informando que a instalação deveria pegar os produtos da versão base 10.2.0.1, usando o parâmetro FROM_LOCATION. Interessante não?! Você pode instalar um outro “produto” usando o instalador menos “bugado”.

A conclusão disso pra mim é: Que bom que a Oracle é muito boa de documentação, porque esses probleminhas tem de monte! Só que tudo tá documentado e geralmente tem uma solução de contorno!

Temos então nosso 10gR2 instalado e agora vamos a migração! Caso tenhamos mais novidades, mantenho vocês informados!

 

Abraços a todos.

 

 

Atc.

Gerson Júnior

gerson.vasconcelos@gmail.com

Oracle Tuning – Exportando Estatísticas de Tabelas

Fala PessoAll,

Depois de muito tempo sem postar, estou eu aqui de novo para falar de mais um recurso usado no nosso Diaadia.

Desta vez o problema foi o seguinte:

Temos uma base de produção 9i que está em plena fase de migração para 11g, claro que para que esta migração aconteça, temos que ter a homologação de vários sistemas em 11g, que atualmente rodam na nossa base de produção 9i. Em uma das homologações deste sistema, o analista nos acionou informando que um processo que rodava na base 9i em 10 minutos, já estava a mais de 1 hora rodando na base 11g, sem sucesso.

Vamos as análises…

Passo 1: Identificar que comando estava causando nosso problema, para isso solicitei ao analista rodar a rotina dele habilitando um trace, para tentarmos identificar. Foi solicitado adicionar os seguintes comandos na execução:

begin
--Habilita geracao do trace.
execute immediate('alter session set tracefile_identifier=''TRACE_PROC_LENTA''');
sys.dbms_support.start_trace(true, true);
-- Call the procedure
PROCEDURE_DO_ANALISTA_LENTA;
--Finaliza geracao do trace.
sys.DBMS_SUPPORT.STOP_TRACE;
end;
/

Após concluído o processo, temos que procurar na nossa pasta UDUMP o trace que foi gerado com o identificador “_TRACE_PROC_LENTA”.

Analisando o trace…

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 791 0.02 1.25 0 3 0 0
Execute 72124 9.77 127.63 365 3759 75246 7469
Fetch 81349 109.26 2466.37 229643 14999926 0 75146
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 154264 119.05 2595.27 230008 15003688 75246 82615

Identificamos que o processo rodou em 2595.27 segundos, total!

E temos um comando único, que rodou em 2289.73 segundos. Ficou claro que este é o culpado não??


select COL1, COL2, COL3 from MINHA_TABELA

call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 5430 1.11 3.54 0 0 0 0
Fetch 5430 106.61 2286.19 222786 14703253 0 3431
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 10861 107.72 2289.73 222786 14703253 0 3431

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 214 (OWNER) (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
1 TABLE ACCESS BY INDEX ROWID MINHA_TABELA (cr=7 pr=0 pw=0 time=68 us cost=5 size=33 card=1)
13 INDEX RANGE SCAN MINHA_TABELA_IDX2 (cr=4 pr=0 pw=0 time=40 us cost=4 size=0 card=1)(object id 32870)

Como podemos ver, este select está sendo executado utilizando um índice, o MINHA_TABELA_IDX2. Ótimo, agora vamos comparar este plano de execução, com o plano de execução que temos em produção. Eis o plano de produção:


Rows Row Source Operation
------- ---------------------------------------------------
1 TABLE ACCESS BY INDEX ROWID MINHA_TABELA (cr=7 pr=0 pw=0 time=68 us cost=5 size=33 card=1)
13 INDEX RANGE SCAN MINHA_TABELA_PK (cr=4 pr=0 pw=0 time=40 us cost=4 size=0 card=1)

Opa…. qual a diferença? Nesta base a minha query acessa os dados pela PK, e não pelo índice! Matamos a parada!!!

Como resolver?

A base onde a homologação estava sendo feita era uma base 11g criada com uma cópia antiga de produção, que não vinha sendo coletada estatística, que estava sendo constantemente alterada pelos testes e que não estava 100%. Para coletar estatísticas novamente desta tabela, seria mais complicado e demorado, pois a tabela tem 667.000.000 de linhas, claro, o teste tem que ser agora!!!!

Lembramos então que tinhamos uma cópia fresquinha da base de produção, que tinha sido recém migrada para 11g, ou seja, estava em 11g, mas tinha as estatísticas certinhas de produção, onde a query estava rápida.

A solução encontrada foi: Exportar as estatísticas desta tabela.

Então, vamos lá…

Passo 1: Criar uma tabela de estatísticas na base origem, para receber as estatísticas atuais da tabela:


SQL> exec SYS.DBMS_STATS.CREATE_STAT_TABLE(ownname => 'DBAGABOS', stattab => 'TLISTENER_STATS');
Procedimento PL/SQL concluÝdo com sucesso.
SQL>

Passo 2: Exportar as estatísticas atuais da tabela na base de origem, para a tabela de esatísticas que você criou:


SQL> exec DBMS_STATS.EXPORT_TABLE_STATS(ownname => 'DBAGABOS', tabname => 'TLISTENER', stattab => 'TLISTENER_STATS', cascade => true);
Procedimento PL/SQL concluÝdo com sucesso.
SQL>

Passo 3: Exportar esta tabela gerada…


C:UsersGersonJr>exp dbagabos@orcl tables=TLISTENER_STATS file=dump_stats.dmp
Export: Release 10.2.0.3.0 - Production on Seg Ago 1 19:23:58 2011
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Senha:
Conectado a: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options
ExportaþÒo executada no conjunto de caracteres de WE8MSWIN1252 e no conjunto de caracteres de AL16UTF16 NCHAR
Sobre exportar tabelas especificadas ... via Caminho Convencional ...
. . exportando tabela TLISTENER_STATS 113 linhas exportadas
ExportaþÒo encerrada com sucesso, sem advertÛncias.
C:UsersGersonJr>

Passo 4: Importar a tabela de estatísticas que você exportou, no banco de destino…


C:UsersGersonJr>imp dbagabos@orcl_destino tables=TLISTENER_STATS file=dump_stats.dmp
Import: Release 10.2.0.3.0 - Production on Seg Ago 1 19:24:58 2011
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Senha:
Conectado a: Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options
Arquivo de exportaþÒo criado por EXPORT:V10.02.01 via caminho convencional
AdvertÛncia: os objetos foram exportados por DBAGABOS; nÒo por vocÛ
importaþÒo realizada nos conjuntos de caracteres WE8MSWIN1252 e NCHAR AL16UTF16
. importando objetos de DBAGABOS para DBAGABOS
. importando objetos de DBAGABOS para DBAGABOS
. . importando table "TLISTENER_STATS" 113 linhas importadas
ImportaþÒo encerrada com sucesso, sem advertÛncias.
C:UsersGersonJr>

Passo 5: Importar as estatísticas para a tabela, lendo da tabela de estatísticas que você importou.

exec DBMS_STATS.IMPORT_TABLE_STATS(ownname => 'DBAGABOS', tabname => ‘TLISTENER’, stattab => ‘TLISTENER_STATS’, cascade => true, no_invalidate => true);

E agora é só você testar seu plano de execução e verificar se na base nova a query está se comportando da mesma forma que na base antiga.

Algumas considerações:
1 – O problema ocorreu na base 11g, porém para criar o post refiz os comandos na base instalada no meu PC, que é 10.2.0.3, como podem ver nos comandos acima.

2 – Estes passos não querem dizer que há uma garantia 100% da sua query ficar igual a sua base de origem, lembre-se que em performance existem inúmeros outros pontos que são verificados para o banco montar um plano de execução.

3 – A idéia deste post é mostrar este recurso de export/import de estatísticas, que é simples e rápido de fazer, e pode ajudar-nos em vários casos.

Qualquer coisa, estou à disposição para dúvidas e/ou sugestões!

Grande abraço.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Dica EXPDP – COMPRESSION

Fala PessoAll,

Estive fazendo um EXPDP de uma base de aproximadamente 360Gb.


nohup expdp userid=myusr/mypwd directory=DIR_EXPORT_SCHEMA dumpfile=exp_MS_MSI_18032011.dmp logfile=exp_MS_MSI_18032011.log schemas=MS,MSI status=300

Iniciei o export, e o directory DIR_EXPORT_SCHEMA estava em uma partição que tinha 112Gb livre, imaginei que o export ocorreria sem problemas, porém… de repente… erro no log, ao verificar, disco estava em 100% de uso. Ou seja, ele gerou um arquivo de 112Gb!

Então, lembrei que no bom e velho EXP tinha um parâmetro COMPRESS e decidi ver como era agora no novo EXPDP. Verificando o Help (expdp help=y), encontrei o parâmetro COMPRESSION e passei a utilizá-lo no meu comando, ficando assim:


nohup expdp userid=myusr/mypwd directory=DIR_EXPORT_SCHEMA dumpfile=exp_MS_MSI_18032011.dmp logfile=exp_MS_MSI_18032011.log schemas=MS,MSI compression=ALL status=300

Depois da conclusão do processo, fui ver o tamanho do arquivo e tive um baita surpresa! O dump inteiro ficou com 31Gb! Ou seja, sem compressão, chegamos em 112Gb e estourou o disco, com a compressão ficou em 31Gb.

Fica a dica, caso alguém tenha alguma restrição de espaço, manda bala com o COMPRESSION do EXPDP que realmente funciona, e a compressão é BEM significativa!

Abraços.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Guida de referência de SQL Básico

Fala pessoAll,

Com a contribuição do nosso amigo e leitor Robson Cristovão, está aí um guia básico de SQL que pode ser bastante útil para quem está começando no mundo SQL e tem algumas dúvidas quanto ao uso e sitaxe de alguns comandos SQL! Fica a dica!

AND | OR:
SELECT nome_coluna(s)
FROM nome_tabela
WHERE condiçao
AND | OR condiçao

ALTER TABLE (add coluna):
ALTER TABLE nome_tabela
ADD nome_coluna datatype

ALTER TABLE (drop column):
ALTER TABLE nome_tabela
DROP COLUMN nome_coluna

AS (alias for column):
SELECT nome_coluna AS coluna_apelido
FROM nome_tabela

AS (alias for table):
SELECT nome_coluna
FROM nome_tabela AS tabela_apelido

BETWEEN:
SELECT nome_coluna(s)
FROM nome_tabela
WHERE nome_coluna
BETWEEN valor1 AND valor2

CREATE (database):
CREATE DATABASE nome_base_de_dados

CREATE (index):
CREATE INDEX nome_indice
ON nome_tabela (nome_coluna)

CREATE (table):
CREATE TABLE nome_tabela(
nome_coluna1 tipo_dado,
nome_coluna2 tipo_dado,...)

CREATE (unique index):
CREATE UNIQUE INDEX nome_indice
ON nome_tabela (nome_coluna)

CREATE (view):
CREATE VIEW nome_da_view AS
SELECT nome_coluna(s)
FROM nome_tabela
WHERE condiçao

DELETE:
DELETE FROM nome_tabela
OU
DELETE FROM nome_tabela
WHERE condiçao

DROP (database):
DROP DATABASE nome_base_de_dados

DROP (index):
DROP INDEX nome_tabela.nome_indice

DROP (table):
DROP TABLE nome_tabela

GROUP BY:
SELECT nome_coluna1,SUM(nome_coluna2)
FROM nome_tabela
GROUP BY nome_coluna1

HAVING:
SELECT nome_coluna1,SUM(nome_coluna2)
FROM nome_tabela
GROUP BY nome_coluna1
HAVING SUM(nome_coluna2) valor_da_condiçao

IN:
SELECT nome_coluna(s)
FROM nome_tabela
WHERE nome_coluna
IN (valor1,valor2,..)

INSERT:
INSERT INTO nome_tabela
VALUES (valor1, valor2,....)
OU
INSERT INTO nome_tabela
(nome_coluna1, nome_coluna2,...)
VALUES (valor1, valor2,....)

LIKE:
SELECT nome_coluna(s)
FROM nome_tabela
WHERE nome_coluna
LIKE padrao

ORDER BY:
SELECT nome_coluna(s)
FROM nome_tabela
ORDER BY nome_coluna [ASC | DESC

SELECT:
SELECT nome_coluna(s)
FROM nome_tabela

SELECT (all):
SELECT * FROM nome_tabela

SELECT (distinct):
SELECT DISTINCT nome_coluna(s)
FROM nome_tabela

SELECT (into - usado para criar cópias auxiliares das tabelas):
SELECT * INTO new_nome_tabela
FROM original_nome_tabela
OU
SELECT nome_coluna(s)
INTO new_nome_tabela
FROM original_nome_tabela

TRUNCATE:
TRUNCATE TABLE nome_tabela

UPDATE:
UPDATE nome_tabela
SET nome_coluna=novo_valor
[, nome_coluna=novo_valor]
WHERE nome_coluna = algum_valor

WHERE:
SELECT nome_coluna(s)
FROM nome_tabela
WHERE condiçao

Espero que gostem.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Dica: Como descobrir quem referencia uma coluna?

Fala PessoAll,

A dica de hoje é a respeito do seguinte…

Muitas vezes temos a necessidade de fazer algumas alterações nas nossas tabelas, nosso modelo, etc. E aí precisamos levantar quais tabelas recerenciam uma determinada tabela ou coluna, quais as filhas dessas colunas, quais as foreign key que fazem referência a elas e etc.

Aí, podemos usar o seguinte select:


select distinct c.table_name
from dba_constraints c,
dba_cons_columns cc
where c.constraint_type = 'R'
and cc.owner = c.owner
and cc.constraint_name = c.r_constraint_name
and cc.owner = &SCHEMA
and cc.table_name = &TABELA
and cc.column_name = &COLUNA

Claro que temos que mudar os parâmetros &SCHEMA, &TABELA e &COLUNA, para recuperar as tabelas que são filhas da tabela que você deseja.

Exemplo fica melhor não? Vamos lá:

Eu preciso descobrir quais as tabelas que fazem referência a alguma coluna da tabela SOURCE, para tal fazemos o seguinte select:


SQL> select DISTINCT C.TABLE_NAME
2 from dba_constraints c,
3 dba_cons_columns cc
4 where c.constraint_type = 'R'
5 and cc.owner = c.owner
6 and cc.constraint_name = c.r_constraint_name
7 and cc.owner = 'ORABUGIT'
8 and cc.table_name = 'SOURCES'
9 /
TABLE_NAME
------------------------------
PEOPLE_EQUIPS

Como podemos ver, obtemos como resposta a tabela PEOPLE_EQUIPS, portanto podemos ver que nesta tabela tem alguma coluna que referencia através de foreign key uma coluna da tabela SOURCE.

Espero que a dica seja útil!!

Abraços.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Potência / Expoentes em SQL e PL/SQL – Oracle

Fala Pessoal,

Hoje vai mais uma dica de SQL e PL/SQL.

Até o dia de hoje, eu nunca tinha necessitado usar expoente no SQL / PL/SQL, nunca tinha pego nenhum problema em desenvolvimento que precisasse ser usado potência, expoente e tal.

Porém, hoje uma amiga desenvolvedora, Leilah, precisou dessa funcionalidade e aí discutimos um pouco sobre o assunto. Descobri portanto, que no Oracle, não precisamos fazer muita conta e nem usar sintaxes esquisitas para usar potência e elevar um número a uma determinada potência, basta usarmos a função POWER, isso mesmo, funciona assim:

Exemplo SQL:

SQL> select power(2,3) from dual;
POWER(2,3)
----------
8

Neste exemplo, temos 2 elevado a 3, que nos dá 8 como resultado…

Exemplo PL/SQL:

SQL> declare
2 v_num number;
3 begin
4 v_num := power(2,3);
5 dbms_output.put_line('O numero 2 elevado a 3 é: '||to_char(v_num));
6 end;
7 /
O numero 2 elevado a 3 é: 8
Procedimento PL/SQL concluÝdo com sucesso.

Pronto pessoal, fica aí a dica de utilização de potência em PL/SQL.

Espero que gostem.

Grande abraço.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Oracle – SQL TRACE – TKPROF

Fala PessoAll,

Estamos aqui novamente para compartilhar mais uma experiência.

Dessa vez com algo bastante básico para quem quer se especializar em performance de aplicações, que é o meu caso!!

Em alguns momentos na nossa vida de DBA nos deparamos com processos que são um tanto quanto complexos de serem analisados, por exemplo: Uma procedure que demora muito ou uma query que demora demais para retornar ou um procedimento inteiro que tem todas as querys otimizadas mas demora muito entre outras coisas. Para que possamos analisar estes tipos de problemas, temos um grande aliado que é o SQL_TRACE, ele vai gerar uma espécie de “relatório” com todas as query´s envolvidas no processamento, e nos mostrar o que cada query fez, o plano de execução de cada uma, quanto tempo demorou para rodar, quanto de CPU consumiu, quantas vezes foi executada, isso nos dá uma visão exata do que está ocorrendo, podendo ser até um erro de lógica na aplicação, onde por exemplo, devido a um erro uma determinada query é executada milhares de vezes sem necessidade.

Hoje vou mostrar como fazemos para gerar um trace de uma determinada operação no banco e como formatar este trace de forma que possamos ler e entender o passo a passo da execução. Vamos lá!

O primeiro passo é alterar a sessão que o processo vai rodar para que o trace seja gerado, isso pode ser feito com o comando:

ALTER SESSION SET SQL_TRACE=TRUE;

Após este commando, podemos executar a nossa rotina lenta, que um arquivo será gerado com o que esta rotina fez.

Begin
Nossa_Rotina_Lenta(1,4,4);
End;

Após a conclusão do processamento, devemos ir até o local onde foi gerado o arquivo, no meu caso, o arquivo é gerado no caminho: {ORACLE_BASE}adminnegraodudump

Se você tentar abrir o arquivo gerado, possivelmente não vai conseguir entender nada! Para que nosso arquivo fique legível, vamos usar um utilitário chamado TKPROF. Esse utilitário tem como objetivo interpretar o trace e deixar ele num formato legível.

O uso do TKPROF é da seguinte forma: tkprof trace.trc arquivo_saida.txt explain=usuário/senha@banco

Depois deste comando executado, no seu arquivo de saída, terá um conteúdo parecido com este:

********************************************************************************
count = Numero de vezes que o procedimento foi executado
cpu = Tempo em segundos executando pelo CPU
elapsed = Tem em segundos para execução do procedimento
disk = Numero de leituras físicas no disco
rows = Numero de linhas processadas pelo comando
********************************************************************************

SELECT COUNT(*)
FROM dual

call count cpu elapsed disk query current rows
——- —– —– ——- ——- ——- ——- ——-
Parse 1 0.02 0.02 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 1 4 1
——- —– —– ——- ——- ——- ——- ——-
total 4 0.02 0.02 0 1 4 1

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 121

Rows Row Source Operation
——- —————————————————
1 SORT AGGREGATE
1 TABLE ACCESS FULL DUAL

Neste exemplo, conseguimos ler e ver o que aconteceu com a query, além do plano de execução que ela utilizou para executar.

Depois disso é analisar as query´s mais complexas e atacar na mudança delas, em muitos casos é necessário a mudança da lógica da rotina, para que se possa ganhar alguma performance!

É isso pessoal. Espero que ajude vocês!

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com

Utilizando Compartilhamento Windows no Linux

Fala PessoAll,

Bom, hoje tivemos mais um desafio bem interessante.

Recebemos um dump de um determinado cliente, o arquivo de dump (X.dmp) veio com 260Gb em um único arquivo. Infelizmente, na máquina Linux onde a base está instalada não tinha nenhum disco com esta quantidade de espaço livre. E agora pra importar esse dump??

Vasculhamos nossos servidores e achamos um servidor com mais de 260Gb livre, dando sopa! Que beleza, problema resolvido!

Idéia 1: Descompactamos os 260Gb neste servidor e a partir dele fazemos o import na máquina destino, tudo certo! NÃO! Este servidor roda Oracle 10G e o servidor de destino roda Oracle 9i, não funciona! Que falta de sorte!

Idéia 2: Descompactamos neste servidor e através da rede, criamos um mapeamento da máquina onde será importado, para esta máquina que tem espaço sobrando e tudo certo! Ok? NÃO de novo. O servidor que tem esse espaço é um Windows 2003 Server, e a máquina onde a base está rodando e o dump teria que ser importada, estava rodando Linux… Red Hat Enterprise.

Mas… porque não? Será que não tem como fazer? Pesquisando na internet achei alguns sites que explicavam como fazer e aí decidi testar. E, para alegrar ainda mais minha sexta-feira, funcionou beleza! Como se fosse uma pasta na máquina Linux.

Segue o passo a passo:


Inicialmente deve-se verificar os compartilhamentos disponíveis na máquina destino
[oracle@oracle9i oracle]$ smbclient -L 192.168.0.13 -U oracle
Password:
Sharename Type Comment
--------- ---- -------
IPC$ IPC IPC remoto
D$ Disk Recurso compartilhado padrão
RV Disk
SQLLDR Disk
ADMIN$ Disk Administração remota
C$ Disk Recurso compartilhado padrão

Em seguida deve-se conectar como SU
[oracle@oracle9i oracle]$ su -
Password:

Depois deve ser criada a pasta que irá exibir os dados do compartilhamento
[root@oracle9i root]# mkdir /mnt/Dump

Depois deve ser executado o commando que efetivamente vai criar o link
[root@oracle9i root]# mount -t smbfs -o username=oracle,password=oracle01 //192.168.0.13/SQLLDR /mnt/Dump

Depois disso já podemos listar o conteúdo da pasta, que já será exibido o conteúdo do mapeamento em questão
[root@oracle9i root]# ls /mnt/Dump
IN

É isso!

Espero que seja útil também pra vocês!

Grande abraço.

Atc.
Gerson Júnior
gerson.vasconcelos@gmail.com