<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- iMasters Gerador RSS 2.0 -->
<rss version="2.0">
    <channel>
        <title>iMasters - Seção: oracle</title>
        <description>iMasters - Comunidade de profissionais, estudantes e mestres em tecnlogias e ferramentas voltadas para o desenvolvimento web</description>
        <link>http://imasters.uol.com.br/</link>
        <lastBuildDate>Wed, 10 Feb 2010 08:37:30 +0100</lastBuildDate>
        <generator>iMasters Gerador RSS 2.0</generator>
        <item>
            <title>RMAN: customizando o seu backup</title>
            <link>http://imasters.uol.com.br/artigo/15435/oracle/rman_customizando_o_seu_backup/</link>
            <description>&lt;p&gt;Um dos pontos fortes de trabalhar com o Recovery Manager (RMAN) é a possibilidade de alocar uma determinada quantidade de canais necessários no processo de Backup para melhorar o desempenho de I/O durante a tarefa, diminuindo o tempo do backup.&lt;/p&gt;

&lt;p&gt;Os administradores de banco de dados (DBA) muitas vezes gostam de utilizar a alocação de canal manual para efetuar o backup e, com isso, torna-se necessário mencionar a cada canal (channel) alocado o caminho em que deverá ser gerado o backup set. Como o script abaixo:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;run {&lt;br /&gt;allocate channel t1 type disk format '/u02/app/oracle/backup/rman/bkp_%d_%t_%s.rman';&lt;br /&gt;backup current controlfile tag 'BKP_CF';&lt;br /&gt;release channel t1;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Perceba que durante a alocação do canal t1, é utilizada a cláusula FORMAT, que posteriormente menciona o caminho e o nome do backupset que será gerado pelo RMAN. Pois bem, se você costuma utilizar 3, 4, 5 ou mais canais, em um único caminho de backup e usando sempre a mesma máscara de nomenclatura de backup set, tornando os scripts frágeis.&lt;/p&gt;

&lt;p&gt;Vamos analisar o exemplo e dividir as tarefas e customizar o RMAN, a partir da cláusula FORMAT. Veja:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Quantidade de canais = 3&lt;/li&gt;

	&lt;li&gt;Caminho de Backup = /u02/app/oracle/backup/rman&lt;/li&gt;

	&lt;li&gt;Nomenclatura de Backup set = bkp_%d_%t_%s.rman&lt;/li&gt;

&lt;/ol&gt;&lt;p&gt;Sobre a nomenclatura utilizada, segue a explicação:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;bkp_ = Nome inicial dos backupsets gerados, ou seja, definido por mim, é um valor fixo.&lt;/li&gt;

	&lt;li&gt;%d = Variável do RMAN para identificar o nome do banco de dados.&lt;/li&gt;

	&lt;li&gt;%t = Variável do RMAN para o Time Stamp do backup set.&lt;/li&gt;

	&lt;li&gt;%s = Variável do RMAN para identificar a sequência do backup set.&lt;/li&gt;

&lt;/ul&gt;&lt;p&gt;Agora, vamos colocar na prática essa customização.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;01. Logue-se no banco de dados usando o RMAN&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;[oracle@ORA11G ~]$ &lt;strong&gt;rman target /&lt;/strong&gt;&lt;em&gt;&lt;br /&gt;Recovery Manager: Release 11.1.0.6.0 - Production on Thu Aug 6 &lt;br /&gt;10:57:15&lt;br /&gt;Copyright&lt;br /&gt; (c) 1982, 2007, Oracle. All rights reserved.&lt;br /&gt;connected&lt;br /&gt; to target&lt;br /&gt; database: RADB (DBID=1241100324)&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;02. Configure o caminho e o nome do backup set no control file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As informações sobre a customização do RMAN serão armazenadas no control file. Para configurar emita o comando abaixo:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;&lt;strong&gt;CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT '/u02/app/oracle/backup/rman/bkp_%d_%t_%s.rman';&lt;/strong&gt;&lt;em&gt;&lt;br /&gt;new RMAN configuration parameters:&lt;/em&gt;&lt;strong&gt;&lt;br /&gt;CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT '/u02/app/oracle/backup/rman/bkp_%d_%t_%s.rman';&lt;/strong&gt;&lt;em&gt;&lt;br /&gt;new RMAN configuration parameters are successfully stored&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;03. Defina a quantidade de alocação de canal automático&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para definir a quantidade de alocação de canais automáticos, quando executado qualquer script do RMAN para o banco de dados alvo, a estratégia é utilizar o PARALELISMO. E para configurar essa opção, basta executar o passo abaixo:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;&lt;strong&gt;CONFIGURE DEVICE TYPE DISK PARALLELISM 3 BACKUP TYPE TO BACKUPSET;&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;new RMAN configuration parameters:&lt;/em&gt;&lt;br /&gt;&lt;strong&gt;CONFIGURE DEVICE TYPE DISK PARALLELISM 3 BACKUP TYPE TO BACKUPSET;&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;new RMAN configuration parameters are successfully stored&lt;/em&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;04. Verifique as configurações alteradas&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;&lt;strong&gt;show all;&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;using target database control file instead of recovery catalogRMAN configuration parameters for database with db_unique_name RADB are:&lt;br /&gt;CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default&lt;br /&gt;CONFIGURE BACKUP OPTIMIZATION OFF; # default&lt;br /&gt;CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default&lt;br /&gt;CONFIGURE CONTROLFILE AUTOBACKUP ON;&lt;br /&gt;CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default&lt;br /&gt;CONFIGURE DEVICE TYPE DISK PARALLELISM 3 BACKUP TYPE TO BACKUPSET;&lt;br /&gt;CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default&lt;br /&gt;CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default&lt;br /&gt;CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT '/u02/app/oracle/backup/rman/bkp_%d_%t_%s.rman';&lt;br /&gt;CONFIGURE MAXSETSIZE TO UNLIMITED; # default&lt;br /&gt;CONFIGURE ENCRYPTION FOR DATABASE OFF; # default&lt;br /&gt;CONFIGURE ENCRYPTION ALGORITHM 'AES128'; # default&lt;br /&gt;CONFIGURE COMPRESSION ALGORITHM 'BZIP2'; # default&lt;br /&gt;CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default&lt;br /&gt;CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/u01/app/oracle/product/11.1.0/db_1/dbs/snapcf_RADB.f'; # default&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;05. Teste o novo script&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agora, veja como ficou o script com as customizações que foram feitas. Em negrito estão as novas configurações realizadas para o RMAN.&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;&lt;strong&gt;run {&lt;br /&gt;shutdown immediate;&lt;br /&gt;startup mount;&lt;br /&gt;backup database include current controlfile tag 'BKP_FULL';&lt;br /&gt;alter database open;&lt;br /&gt;}&lt;/strong&gt;&lt;em&gt;&lt;br /&gt;database closeddatabase dismounted&lt;br /&gt;Oracle instance shut down&lt;br /&gt;connected to target database (not started)&lt;br /&gt;Oracle instance started&lt;br /&gt;database mounted&lt;br /&gt;Total System Global Area 644468736 bytes&lt;br /&gt;Fixed Size 1301840 bytes&lt;br /&gt;Variable Size 293601968 bytes&lt;br /&gt;Database Buffers 343932928 bytes&lt;br /&gt;Redo Buffers 5632000 bytes&lt;br /&gt;Starting backup at 06/08/2009 11:26:16&lt;br /&gt;allocated channel: ORA_DISK_1allocated channel: ORA_DISK_2allocated channel: ORA_DISK_3/u02/app/oracle/backup/rman/bkp_RADB_694178799_15.rman tag=BKP_FULL comment=NONE&lt;br /&gt;channel ORA_DISK_3: backup set complete, elapsed time: 00:03:16&lt;br /&gt;channel ORA_DISK_3: starting full datafile backup set&lt;br /&gt;channel ORA_DISK_3: specifying datafile(s) in backup set&lt;br /&gt;including current control file in backup set&lt;br /&gt;channel ORA_DISK_3: starting piece 1 at 06/08/2009 11:30:43&lt;br /&gt;channel ORA_DISK_3: finished piece 1 at 06/08/2009 11:31:23&lt;br /&gt;piece handle=/u02/app/oracle/backup/rman/bkp_RADB_694179009_16.rman tag=BKP_FULL comment=NONE&lt;br /&gt;channel ORA_DISK_3: backup set complete, elapsed time: 00:00:40&lt;br /&gt;channel ORA_DISK_1: finished piece 1 at 06/08/2009 11:34:13&lt;br /&gt;piece handle=/u02/app/oracle/backup/rman/bkp_RADB_694178778_13.rman tag=BKP_FULL comment=NONE&lt;br /&gt;channel ORA_DISK_1: backup set complete, elapsed time: 00:07:48&lt;br /&gt;channel ORA_DISK_2: finished piece 1 at 06/08/2009 11:35:04&lt;br /&gt;piece handle=/u02/app/oracle/backup/rman/bkp_RADB_694178786_14.rman tag=BKP_FULL comment=NONE&lt;br /&gt;channel ORA_DISK_2: backup set complete, elapsed time: 00:08:30&lt;br /&gt;Finished backup at 06/08/2009 11:35:04&lt;br /&gt;Starting Control File and SPFILE Autobackup at 06/08/2009 11:35:04&lt;br /&gt;piece handle=/u01/app/oracle/flash_recovery_area/RADB/autobackup/2009_08_06/o1_mf_s_694178760_57otk638_.bkp comment=NONE&lt;br /&gt;Finished Control File and SPFILE Autobackup at 06/08/2009 11:35:29&lt;br /&gt;database opened&lt;br /&gt;channel ORA_DISK_1: SID=154 device type=DISK&lt;br /&gt;&lt;br /&gt;channel ORA_DISK_2: SID=153 device type=DISK&lt;br /&gt;&lt;br /&gt;channel ORA_DISK_3: SID=151 device type=DISK&lt;br /&gt;channel ORA_DISK_1: starting full datafile backup set&lt;br /&gt;channel ORA_DISK_1: specifying datafile(s) in backup set&lt;br /&gt;input datafile file number=00001 name=/u02/app/oracle/oradata/RADB/system01.dbf&lt;br /&gt;channel ORA_DISK_1: starting piece 1 at 06/08/2009 11:26:26&lt;br /&gt;channel ORA_DISK_2: starting full datafile backup set&lt;br /&gt;channel ORA_DISK_2: specifying datafile(s) in backup set&lt;br /&gt;input datafile file number=00002 name=/u02/app/oracle/oradata/RADB/sysaux01.dbf&lt;br /&gt;input datafile file number=00004 name=/u02/app/oracle/oradata/RADB/users01.dbf&lt;br /&gt;channel ORA_DISK_2: starting piece 1 at 06/08/2009 11:26:34&lt;br /&gt;channel ORA_DISK_3: starting full datafile backup set&lt;br /&gt;channel ORA_DISK_3: specifying datafile(s) in backup set&lt;br /&gt;input datafile file number=00005 name=/u02/app/oracle/oradata/RADB/example01.dbf&lt;br /&gt;input datafile file number=00003 name=/u02/app/oracle/oradata/RADB/undotbs01.dbf&lt;br /&gt;channel ORA_DISK_3: starting piece 1 at 06/08/2009 11:26:47&lt;br /&gt;channel ORA_DISK_3: finished piece 1 at 06/08/2009 11:30:03&lt;br /&gt;piece handle=&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;PRONTO! &lt;/p&gt;

&lt;p&gt;Deste modo conseguimos definir regras de backup mais customizadas para cada banco de dados. É válido lembrar que, nos exemplos, realizei os testes de backup diretamente para disco, porém, é possível configurar os mesmos parâmetros para FITA, de acordo com a sua configuração MML no ambiente.&lt;/p&gt;

&lt;p&gt;Abraços,&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.rodrigoalmeida.net/material/RA/assinatura.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
            <author>dbarodrigo@gmail.com (Rodrigo Almeida)</author>
            <pubDate>Mon, 08 Feb 2010 10:30:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/15435</guid>
        </item>
        <item>
            <title>Ignorando acentos no Oracle</title>
            <link>http://imasters.uol.com.br/artigo/15814/oracle/ignorando_acentos_no_oracle/</link>
            <description>&lt;p&gt; Hoje vamos falar um pouco sobre usabilidade utilizando o Oracle. É muito comum vermos
em grande sites de e-commerce, buscas e relacionamentos, entre outros,
que mesmo digitando uma palavra, sem sua acentuação correta, ou até
mesmo com acento colocado errado, encontramos a informação
desejada. Pois bem, veremos como isso é possível utilizando um banco
de dados Oracle.&lt;/p&gt;


&lt;p&gt;Para
a consulta funcionar, devemos alterar os parâmetros &lt;strong&gt;nls_comp
e nls_sort.&lt;/strong&gt;&lt;/p&gt;


&lt;p&gt;O
parâmetro nls_comp
determina qual método de comparação será considerado na consulta.
Após a instalação do banco de dados seu valor inicial é &quot;binary&quot;.&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;
Binary: todo SQL executado e baseado no
método binário, exatamente da forma que está escrita a
informação.&lt;/li&gt;

&lt;li&gt;
Linguistic: todo SQL executado e baseado no Método lingüístico, considerando
a busca e a ordenação como a palavra e falada.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;O
Parâmetro nls_sort
define qual combinação lingüística será utilizada. Para
instalações em que o idioma escolhido é o Português
(nls_language= portuguese),
o valor para o padrão lingüístico é o &quot;Binário&quot; (nls_sort
= binary).&lt;/p&gt;


&lt;p&gt;Por
exemplo, utilizando a combinação binária, temos as seguintes
opções:&lt;/p&gt;


&lt;p&gt;O
sufixo &lt;strong&gt;_ci&lt;/strong&gt; indica que será utilizada a combinação binária
com &lt;strong&gt;Case-Insensitive Sort&lt;/strong&gt;.&lt;/p&gt;


&lt;p&gt;O
sufixo &lt;strong&gt;_ai&lt;/strong&gt; indica que será utilizada a combinação binária
com &lt;strong&gt;Accente Insensitive Sort&lt;/strong&gt;. Pode haver outros valores para o
parâmetro como, por exemplo, &lt;strong&gt;xspanish_ia&lt;/strong&gt;, mas isso já é
assunto para outro artigo.&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;Binary: segue
exatamente da mesma forma que foi escrita.&lt;/li&gt;

&lt;li&gt;
Binary_ci: o algoritmo compara exatamente como a palavra foi
escrita, desconsiderando  as letras maiúsculas e minúsculas.
(Case-Insensitive Sort).&lt;/li&gt;

&lt;li&gt;
Binary_ai: o algoritmo compara as palavras ignora a acentuação
e os maiúsculos e minúsculos. (Accent Insensitive Sort). 
&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;
Por exemplo:&lt;/p&gt;


&lt;p&gt; 	A letra &quot;a&quot;
pode ser comparada com as letras &quot;ã,á,ä,à,â,ä&quot;; a
letra &quot;é&quot; pode ser comparada com as letras &quot;e,è,ê,ë&quot;,
dentre outras acentuações.&lt;/p&gt;


&lt;p&gt;Estes
parâmetros podem ser definidos para todo o banco de dados ou somente
para uma seção. O ideal é utilizar em locais apenas onde há real
necessidade, pois se utilizado para todo ambiente, pode degradar a
performance do banco de dados.&lt;/p&gt;


&lt;p&gt;Vamos praticar.&lt;/p&gt;


&lt;p&gt;Em
nosso cenário vamos considerar um cadastro de produto, que será
utilizando em um E-Commerce.&lt;/p&gt;


&lt;p&gt;	Logo, se um cliente
digitar o nome do produto sem a acentuação necessária ou com a
acentuação errada, o sistema deve ser capaz de identificar e
retornar o produto que ele procura.	&lt;/p&gt;


&lt;p&gt;	Vamos criar um simples
cadastro de produtos:&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;create table tb_produto(nome varchar2(40), valor number(16,4));&lt;br /&gt;insert into tb_produto(nome,valor) values ('Fogão 4 bocas',300);&lt;br /&gt;insert into tb_produto(nome,valor) values ('Fogao 6 bocas',600);&lt;br /&gt;insert into tb_produto(nome,valor) values ('Lava-louças',800);&lt;br /&gt;insert into tb_produto(nome,valor) values ('Jogo de Faca',120);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Primeira
situação:&lt;/h4&gt;


&lt;p&gt;Digamos
que o cliente digitou o nome do produto com a acentuação correta,
mas toda a palavra em minúscula, e que estamos utilizando o método
binário para consulta. Logo, ele não encontrará o produto que
procura!&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; select * from tb_produto where nome = 'lava-louças';&lt;br /&gt;&lt;br /&gt;NOME                                                  VALOR&lt;br /&gt;---------------------------------------- ------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Vamos
mudar os nossos parâmetros para não diferenciar maiúsculos e
minúsculos.&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; alter session set nls_comp=linguistic;&lt;br /&gt;&lt;br /&gt;Session &lt;br /&gt;altered&lt;br /&gt;&lt;br /&gt;SQL&amp;gt; alter session set nls_sort=binary_ai;&lt;br /&gt;&lt;br /&gt;Session&lt;br /&gt; altered&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Veja
que agora o Oracle encontra o produto solicitado.&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt;  select * from tb_produto where nome = 'lava-louças';&lt;br /&gt;&lt;br /&gt;NOME                                                  VALOR&lt;br /&gt;---------------------------------------- ------------------&lt;br /&gt;Lava-louças                                        800,0000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;h4&gt;Segunda
situação:&lt;/h4&gt;


&lt;p&gt;	Vamos
simular que o usuário digitou o nome do produto sem a acentuação
devida.&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; select * from tb_produto where nome = 'lava-louças';&lt;br /&gt;&lt;br /&gt;NOME                                                  VALOR&lt;br /&gt;---------------------------------------- ------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;	Agora
vamos mudar o método de comparação para lingüístico, na seção
que estamos trabalhando.&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; alter session set nls_comp=linguistic;&lt;br /&gt;&lt;br /&gt;Session altered&lt;br /&gt;&lt;br /&gt;SQL&amp;gt; alter session set nls_sort=binary_ai;&lt;br /&gt;&lt;br /&gt;Session altered&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Veja
que o Oracle interpretou a letra &quot;c&quot;
sendo a mesma que &quot;ç&quot;.
Ou seja, ignorou o acento.&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; select * from tb_produto where nome = 'lava-loucas';&lt;br /&gt;&lt;br /&gt;NOME                                                  VALOR&lt;br /&gt;---------------------------------------- ------------------&lt;br /&gt;Lava-louças                                        800,0000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;	Veja que, mesmo se
forçarmos um acento indevido, poderemos saber o preço da
lava-louça.&lt;/p&gt;


&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; select * from tb_produto where nome = 'lava-loucás';&lt;br /&gt;&lt;br /&gt;NOME                                                  VALOR&lt;br /&gt;---------------------------------------- ------------------&lt;br /&gt;Lava-louças                                        800,0000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Assim chegamos ao final
de mais um artigo, espero que tenham gostado!&lt;/p&gt;

</description>
            <author>leonardo.litz@gmail.com (Leonardo Litz)</author>
            <pubDate>Fri, 05 Feb 2010 10:00:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/15814</guid>
        </item>
        <item>
            <title>Achei um ORA-600, o que faço?</title>
            <link>http://imasters.uol.com.br/artigo/15434/oracle/achei_um_ora-600_o_que_faco/</link>
            <description>&lt;p&gt;O título deste artigo já diz muita coisa, &quot;Achei um ORA-600, o que faço?&quot;.
Muitos gostariam de ter o botão EJECT na cadeira, outros de ser ninjas
e jogar o pó para desaparecer e alguns gostariam de ser o novo David
Blaine. Na verdade, esse número &quot;cabalístico&quot; de erro pode ser o início
de uma longa jornada.&lt;/p&gt;

&lt;p&gt;O RDBMS (Relational Database Management System) Oracle possui dois códigos de erros que assustam qualquer DBA, o bendito ORA-600 e ORA-7445. Neste momento vamos refletir sobre o ORA-600, o que ele realmente significa para nós.&lt;/p&gt;

&lt;p&gt;Quando
o encontramos no alert.log ou diretamente pelo Oracle Server (via
SQL*PLUS ou qualquer outra aplicação), significa que temos um problema
na aceitação do comando no kernel do RDBMS ou temos uma inconsistência
em um determinado processo, que, geralmente, pode estar associado a um
BUG. &lt;strong&gt;Mas&lt;/strong&gt; nem sempre é um BUG, por isso que temos que ter muita calma nessa hora. O &lt;a href=&quot;http://metalink.oracle.com/&quot; class=&quot;ext&quot;&gt;Metalink&lt;/a&gt; disponibiliza uma ferramenta de pesquisa para esse específico erro, o chamado ORA-600 Lookup tool. Através dele, pode ser encontrada a solução para seu específico erro, se existe um patch off -  uma correção para o determinado problema -, patch set, que é um conjunto de correções dos produtos, ou se há um simples workarround &quot;gambiarra&quot; para realizar.&lt;/p&gt;

&lt;p&gt;O ORA-600 pode ser um problema causado por diversos fatores, como:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Falta de recurso de hardware:&lt;/strong&gt; a falta de recursos de memória, problemas de disco ou problemas no funcionamento do hardware podem auxiliar seu aparecimento.&lt;/li&gt;

&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Configuração do Sistema Operacional&lt;/strong&gt;&lt;strong&gt;:&lt;/strong&gt; uma
má instalação e falta de patchs no sistema operacional pode causar o
ORA-600, e quando digo má instalação, gosto de me referir aquela
instalação, NEXT-NEXT-FINISH.&lt;/li&gt;

&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Falta de atualização do banco de dados&lt;/strong&gt;&lt;strong&gt;:&lt;/strong&gt; podem
perceber que a Oracle, quando lança um produto, possui diversos Patch
sets, que é um conjunto de correções (Patch offs) que é detectado pelo
suporte da Oracle em acompanhamento de seus clientes. A falta de
atualização só aumenta a sua chance de ter um amigo ORA-600.&lt;/li&gt;

&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Utilização de News Features&lt;/strong&gt;&lt;strong&gt;:&lt;/strong&gt; sempre que é lançada uma versão nova de banco de dados, com por exemplo, versão, 8.1.0, 9.1.0, 10.1.0 ou 11.1.0,
(lógico, em suas respectivas épocas) e na sua aplicação começa a
utilizar as features da versão (novos recursos de desenvolvimento ou
banco de dados), **COM CERTEZA**, encontrará um ORA-600 em
algum momento de sua humilde vida. Isso é porque o Kernel do RDBMS
ainda não está &quot;amadurecido&quot; para executar &quot;tal&quot; tarefa, sobre &quot;tal&quot; hardware, com &quot;tal&quot; sistema operacional com &quot;tal&quot; linguagem de programação.&lt;/li&gt;

&lt;/ul&gt;&lt;p&gt;Como sempre digo, ter um ORA-600 na
base de dados nem sempre é uma questão de desespero ou assinar a
sebtença de morte. Tudo bem que talvez você vire algumas noites na
empresa, mas isso passa. O ORA-600 pode vir a qualquer momento, porque ele é resultante de diversos fatores como dito acima e **SIM**, para alguns tipos de ORA-600, podem ser resolvidos rapidamente.&lt;/p&gt;

&lt;p&gt;Toda vez que se tem um ORA-600, é gerado um arquivo de trace no servidor, no diretório USER_DUMP_DEST ou BACKGROUND_DUMP_DEST(depende
qual será o processo afetado). Nesse arquivo de trace, para quem é mais
experiente, poderá encontrar as raízes dos problemas. Pode ser um
&quot;LAZARENTO&quot; de uma instrução de SELECT que faz join com uma INLINE
VIEW, que também faz um hash join com uma Materialized view e tem uma
view com dblink que força o aparecimento do ORA-600, ou como
pode ser um simples INSERT em tabelas IOT e assim vai, só com bastante
analise iremos saber as causas. Mas onde quero chegar com isso?&lt;/p&gt;

&lt;p&gt;Quando se tem o erro ORA-600 em mãos, devemos tentar entendê-lo, como mostra um exemplo de mensagem abaixo:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;ORA-00600: internal error code, arguments: [kcbz_check_objd_typ_3], [0], [0], [1], [], [], [], []&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ou&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;ORA-00600: internal error code, arguments: [12209], [498], [], [], [], [], [], []&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Podemos
ter uma idéia de onde vem o possível problema, a mensagem de erro é
sempre composta por ORA-600 [argumento1] [argumento2] até o
[argumento8]. Se estudarem a arquitetura interna do Oracle, o kernel é
composto por diversas travas que fazem o controle, acesso e utilização
dos dados.&lt;/p&gt;

&lt;p&gt;Ninguém
sabe dizer com 100% de certeza se o kernel do Oracle é puramente
escrito na linguagem C, mas dizem que possui algumas coisas em Java
para os releases superiores ao 9i. Pois bem, isso não interessa até o
momento, eu quero apenas exemplificar como o kernel trabalha.&lt;/p&gt;

&lt;p&gt;Analisando
o trace gerado, podemos ter a idéia de onde ele vem, como eu disse
acima (por SELECT, INSERT, CREATE e etc), e sempre devemos prestar atenção no primeiro argumento, pois é ele que dirá em qual momento
ou trava ocorreu o problema.&lt;/p&gt;

&lt;p&gt;No primeiro erro mencionado, nosso primeiro argumento foi o kcbz_check_objd_typ_3, que internamente para o Oracle a trava KCBZ quer dizer Kernel Cache Buffer, então já podemos ir mais profundamente e pensar que ocorreu um erro no tratamento da informação durante sua passagem pelo SGA.&lt;/p&gt;

&lt;p&gt;No
segundo erro, como não existe nenhuma trava mencionada no primeiro
argumento, e não envolve travas do kernel, pode ser algum problema
apenas como manipulação dos dados ou quebra de integridade interna, e,
por isso, dá uma esperança que pode ser um ORA-600 com resolução rápida.&lt;/p&gt;

&lt;p&gt;Ambos
os erros podem estar associados a um BUG da versão ou apenas uma má
interpretação do banco de dados, isso, apenas olhando o erro e o trace
não iremos conseguir garantir nada. É apenas um exemplo e modo de como
podemos se comportar com um ORA-600 no banco de dados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lembrete&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sempre,
mas &lt;strong&gt;sempre mesmo,&lt;/strong&gt; que tiver um ORA-600 em sua base de dados, acione de
imediato o suporte da Oracle para analisar profundamente os motivos do
aparecimento do problema e realizar uma investigação sobre seu
ambiente, como mencionado, os fatores podem ser diversos e também pode
ser ou não um real BUG da sua versão.&lt;/p&gt;

&lt;p&gt;Estou
apenas dizendo uma experiência que tenho no dia-a-dia e não me
responsabilizo pelos seus atos. Espero que tenham gostado desse assunto
e que possa entender melhor o motivo do nosso velho amigo ORA-600. &lt;/p&gt;

&lt;p&gt;Abraços,&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.rodrigoalmeida.net/material/RA/assinatura.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
            <author>dbarodrigo@gmail.com (Rodrigo Almeida)</author>
            <pubDate>Mon, 01 Feb 2010 11:15:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/15434</guid>
        </item>
        <item>
            <title>Ferramentas RDA e SCM, qual a diferença?</title>
            <link>http://imasters.uol.com.br/artigo/15433/oracle/ferramentas_rda_e_scm_qual_a_diferenca/</link>
            <description>&lt;p&gt;Olá!&lt;/p&gt;


&lt;p&gt;Para quem trabalha em empresas que possuem diversas bases de dados e têm contrato de suporte com a Oracle, como &lt;a href=&quot;http://metalink.oracle.com/&quot; class=&quot;ext&quot;&gt;Metalink&lt;/a&gt;, &lt;a href=&quot;http://www.oracle.com/consulting/index.html&quot; class=&quot;ext&quot;&gt;Oracle Consulting&lt;/a&gt; ou parceiras da empresa, já conhece ou deve ter ouvido falar sobre as ferramentas de suporte às equipes de DBA, o RDA (Remote Diagnostic Agent) e o SCM (Software Configuration Management).&lt;/p&gt;


&lt;p&gt;Pois
bem, muitos confundem e acham que essas ferramentas são a mesma coisa,
ou que o SCM é uma versão do RDA melhorado, que realmente parece ter a
mesma funcionalidade, mas existe um diferença entre eles.&lt;/p&gt;


&lt;p&gt;O RDA
é uma ferramenta de suporte da Oracle desenvolvido em Perl, que tem
como principal finalidade captar diversas informações do ambiente do
cliente para ajudar na solução de problemas quando se tem um TAR aberto
no Metalink. Essas informações variam desde o sistema operacional,
configurações de rede, java até informações do banco de dados e seus
respectivos produtos, como ASM, Enterprise Manager, EBS, iAS e etc.&lt;/p&gt;


&lt;p&gt;Sua
função é auxiliar no momento da abertura do TAR ou durante o processo
de investigação de seu problema junto à Oracle. Ao instalar e
configurar o RDA, e posteriormente a sua execução, são coletados
informações essenciais para os analistas, pois o RDA no final da
execução gera um arquivo compactado contendo diversos relatórios em
extensão HTML com todas as informações citadas acima.&lt;/p&gt;


&lt;p&gt;O SCM
já trabalha de forma diferente, sua finalidade também é captar todas as
informações sobre seu ambiente para ajudar na resolução de seus
problemas, quase as mesmas que do RDA, porém, seu grande diferencial é
que ele trabalha com os chamados coletores, ou OCM (Oracle
Configuration Manager), que podem ser executados em períodos de tempo
de acordo com a sua necessidade e ociosidade do sistema, ou seja, após
sua instalação e configuração correta, ele envia todas as informações
coletadas para um repositório on-line na Oracle, que pode ser acessado
pelo novo site do Metalink, o My Oracle Support, com essas
informações retidas na Oracle, ele automaticamente analisa e fornece
dicas e alertas sobre seu banco de dados, quais patchs estão faltando
no banco, dicas para melhorar segurança, informações de ajuste para
alguns parâmetros e etc. Deste modo, fornece uma habilidade de
pró-atividade aos DBAs, mantendo sempre atualizado.&lt;/p&gt;


&lt;p&gt;Ambas
as ferramentas são multi-plataformas, ou seja, podem ser utilizadas
tanto em ambientes Windows, Linux e Unix. Para cada caso existem
scripts específicos para cada sistema operacional.&lt;/p&gt;


&lt;p&gt;O RDA
sempre foi uma ferramenta muito boa não apenas para lhe auxiliar nas
tarefas junto ao suporte da Oracle, mas também para consultores de
banco de dados que trabalham em diversas empresas e que precisam
conhecer o ambiente que irá enfrentar, já que seus relatórios podem ser
vistos de forma offline e completo, ajuda em muito para conhecer o
sistema.&lt;/p&gt;


&lt;p&gt;Eu
apenas estou dando uma pequena prévia sobre essas ferramentas, que
considero como um recurso básico em qualquer equipe de administradores
de banco de dados. Quem tem acesso ao Metalink, recomendo que veja como
funciona essas ferramentas através de demonstrações da própria Oracle e
conheça mais tecnicamente o que cada uma pode lhe oferecer. Existem também
Web Seminars em português gratuitos no site para lhe auxiliar na
aprendizagem.&lt;/p&gt;


&lt;p&gt;Dúvidas e sugestões, visitem o meu &lt;a href=&quot;http://www.rodrigoalmeida.net/blog&quot; class=&quot;ext&quot;&gt;blog&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Abraços,&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://www.rodrigoalmeida.net/material/RA/assinatura.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
            <author>dbarodrigo@gmail.com (Rodrigo Almeida)</author>
            <pubDate>Mon, 25 Jan 2010 10:00:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/15433</guid>
        </item>
        <item>
            <title>Crescendo profissionalmente no mundo Oracle</title>
            <link>http://imasters.uol.com.br/artigo/15431/oracle/crescendo_profissionalmente_no_mundo_oracle/</link>
            <description>&lt;p&gt;Olá!&lt;/p&gt;


&lt;p&gt;Gostaria
de discutir um assunto que vem me chamando muito a atenção nesses
últimos tempos, a força que as comunidades Oracle podem oferecer aos
profissionais iniciantes e até mesmo aos mais experientes. E quando
estamos falando de comunidades, estamos diretamente nos referindo aos
grupos de usuários, sites e fóruns na internet. E o mais importante,
eles podem lhe ajudar no seu crescimento profissional e técnico na área
de tecnologia Oracle.&lt;/p&gt;


&lt;p&gt;As
comunidades Oracle, ultimamente, com o apoio da própria Oracle, vêm
crescendo e amadurecendo com a experiência de seus próprios
usuários. Esse crescimento podemos notar pelos eventos, conteúdos
técnicos, blogs e o enriquecimento dos seus respectivos fóruns. Eu
mesmo sou um fã de carteirinha de diversos sites Oracle brasileiros
pelos serviços e eventos que oferecem.&lt;/p&gt;


&lt;p&gt;Mas como a comunidade pode ajudar no meu crescimento profissional?&lt;/p&gt;


&lt;p&gt;A
resposta é simples: nada melhor que você compartilhar a sua experiência
técnica e profissional com outros profissionais que realizam a mesma
função que você. Pela simples troca de experiência em problemas de
outras pessoas a partir de fóruns ou lista de discussões, você consegue
estudar mais sobre o assunto, o outro profissional conhece novas
técnicas, outros usuários que estão participando do assunto conhecem
mais sobre o problema e quando você vivenciar o problema discutido na
empresa ou cliente que trabalha, já irá saber quais os passos e tarefas
necessárias para chegar a sua solução.&lt;/p&gt;


&lt;p&gt;E o
que dizer sobre recomendações de livros, eventos, white papers e até
mesmo ambiente de trabalho? Nada melhor do que você discutir isso com
profissionais que estão no mercado, que fazem o que você faz todos os
dias. Simplesmente não dá para chegar em casa e tentar conversar com a
sua esposa(o) sobre um erro ORA-600 que aconteceu contigo nesta manhã.
No meu caso, minha esposa é administradora - se comento sobre erros
ORA-600, ela pensa que é placa de carro, código de guerra ou qualquer
coisa de outro mundo. E, desse jeito, não temos muito assunto!&lt;/p&gt;


&lt;p&gt;Por
isso que as comunidades estão se tornando mais fortes no Brasil
conforme o crescimento da tecnologia Oracle acontece. Fóruns e sites são as
nossas casas virtuais, sempre recorremos à elas quando precisamos ou
queremos saber algo sobre um determinado assunto. Aliás, dentro de
fóruns conhecemos usuários e ganhamos amigos, aumentando nossa network.
E, talvez, conheceremos os amigos virtuais em eventos criados pela
própria Comunidade.&lt;/p&gt;


&lt;p&gt;Outro ponto importante é que todo iniciante tem três dúvidas básicas, tais como:&lt;/p&gt;


&lt;ol&gt;&lt;li&gt;Como iniciar na carreira;&lt;/li&gt;

&lt;li&gt;Quais os melhores livros para comprar;&lt;/li&gt;

&lt;li&gt;Qual o melhor centro de treinamento;&lt;/li&gt;

&lt;li&gt;E o básico de fóruns, ME AJUDE NO TRABALHO DE FACULDADE. (Opcional)&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Algumas
coisas podem ser respondidas pelo Google, mas, com certeza, nos diversos
fóruns de Oracle que temos aqui no Brasil, sabendo usar o SEARCH/PROCURAR
do fórum, já temos tópicos com títulos bem parecidos com os
que estão acima, com dicas e sugestões de diversos profissionais, com
diversos pontos de vista e recomendações do que deve ou não ser feito.
Isso é centralização, disseminação, orientação e agilidade que uma
comunidade pode lhe oferecer.&lt;/p&gt;


&lt;p&gt;Para
os mais experientes, que já sabem o poder da comunidade, além da troca
de experiência, conteúdo técnico e network, algo que chama atenção são as
VAGAS DE EMPREGO. Sim, o mercado de DBA é muito restrito e nada mais
normal que, nesse pequeno círculo de profissionais, vagas que se abrem
em outras empresas, se compartilhadas por eles mesmos. Um exemplo disso
é a chamada RECOMENDAÇÃO. Muitas vezes você não conhece o
profissional fisicamente, porém, acompanha seus trabalhos, posts em
blogs ou fóruns e sabe que a tal pessoa domina sobre a tecnologia.
Então, em vez de você deixar que o departamento de RH escolha um
profissional para a vaga, o que pode ser um problema, você passa a
indicação ao gerente e/ou diretor de TI, conforme os requisitos da
vaga. E, deste modo, pode ter certeza de que a contratação será muito mais
valiosa e agregadora à empresa, pois geralmente RH não sabe
mensurar um profissional para o tipo de problema ou requisito que a
empresa está necessitando.&lt;/p&gt;


&lt;p&gt;Para
concluir, é válido saber que comunidades Oracle, principalmente as
brasileiras, estão cheias de pessoas que colaboram e dedicam o seu
tempo livre para ajudar e compartilhar sua experiência com os mais
novos, com a criação e a organização de eventos, artigos técnicos,
blogs, fóruns, lista de discussões por e-mail, chats e etc, elevando o
nível de conhecimento, enriquecendo a internet e compartilhando a
informação. Seguindo o velho ditado:&lt;/p&gt;


&lt;blockquote&gt;
&lt;p&gt;O importante é sempre compartilhar para multiplicar.&lt;/p&gt;

&lt;/blockquote&gt;


&lt;p&gt;Para
conhecerem mais sobre as nossas comunidades Oracle, preparei uma página sobre comunidades, grupos de usuários, fóruns e sites em
geral que podem lhe ajudar nessa caminhada.&lt;/p&gt;


&lt;p&gt;Saiba mais sobre as &lt;a href=&quot;http://www.rodrigoalmeida.net/blog/index.php/comunidades/&quot; class=&quot;ext&quot;&gt;Comunidades Oracle&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Abraços,&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://www.rodrigoalmeida.net/material/RA/assinatura.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</description>
            <author>dbarodrigo@gmail.com (Rodrigo Almeida)</author>
            <pubDate>Mon, 11 Jan 2010 09:30:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/15431</guid>
        </item>
        <item>
            <title>Funções pipelined em Oracle</title>
            <link>http://imasters.uol.com.br/artigo/13745/oracle/funcoes_pipelined_em_oracle/</link>
            <description>				&lt;p&gt;Por definição, uma função de pipelined é aquela que retorna uma coleção de dados, foi implementada pela Oracle a partir da versão 9i. Imagine ter que desenvolver uma query, com várias regras embutidas. Teríamos que criar, codificar várias linhas de código, talvez tenhamos que utilizar subquerys, minus, intersect, unions, decodes, cases, dentre outros recursos para que possamos obter o resultado esperado. Agora imagine a manutenção disso. Dentre outras utilidades, uma função de pipelined permite a simplificação do código, tornando mais rápido o desenvolvimento e ágil sua manutenção.&lt;/p&gt;

&lt;p&gt;Muitas vezes, durante o desenvolvimento, torna-se necessário criar uma seqüência de números ou datas, que não estão em tabelas, ou então desejamos obter resultados de cálculos, fórmulas ou até expressões condicionais. Para estes casos podemos utilizar funções de pipelined. Além de facilitar o desenvolvimento, é muito mais rápida e de menor custo que uma query comum para retornar os dados.&lt;/p&gt;

&lt;p&gt;É possível facilitar o desenvolvimento com uma função de pipelined. Veremos como.&lt;/p&gt;

&lt;p&gt;Nosso cenário será um relatório de movimento de estoque de uma loja virtual. Um usuário deseja visualizar quantos itens de determinado produto foram movimentados a cada minuto. A estrutura da tabela de movimentos de estoque grava a data do movimento e a quantidade movimentada de um item. O resultado esperado deve estar no seguinte layout:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;De&lt;br /&gt;&lt;/th&gt;&lt;th&gt;Até&lt;br /&gt;&lt;/th&gt;&lt;th&gt;Quant. Movimentada&lt;br /&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 07:40:01&lt;/td&gt;&lt;td&gt;5/7/2009 07:41:00&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 07:41:01&lt;/td&gt;&lt;td&gt;5/7/2009 07:42:00&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 07:42:01&lt;/td&gt;&lt;td&gt;5/7/2009 07:43:00&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 07:43:01&lt;/td&gt;&lt;td&gt; 5/7/2009 07:44:00&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Então vamos lá:&lt;/p&gt;

&lt;p&gt;1 - Crie a estrutura da tabela onde serão inseridos os movimentos ocorridos no estoque.&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;create table TB_MOVIMENTO&lt;br /&gt;(&lt;br /&gt;  ID_MOVIMENTO    NUMBER primary key,&lt;br /&gt;  DT_MOVIMENTO    DATE,&lt;br /&gt;  QTD_MOVIMENTADA NUMBER(4),&lt;br /&gt;  COD_ITEM        VARCHAR2(6)&lt;br /&gt;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;2 - Iremos incluir algumas movimentações de estoque, algo em torno de 10 mil registros, que serão gerados aleatoriamente. Para isso utilizarei a package dbms_random, proveniente da própria instalação do banco de dados.&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;declare&lt;br /&gt;v_dt  dbms_sql.date_Table;    --Cria vetor do tipo data&lt;br /&gt;v_qtd dbms_sql.Number_Table;  --Cria vetor do tipo numérico&lt;br /&gt;begin&lt;br /&gt;&lt;br /&gt;      --Popular as datas geradas aleatoriamente&lt;br /&gt;      dbms_random.seed(to_date('05/07/2009 23:59:59','dd/mm/rrrr HH24:MI:SS'));&lt;br /&gt;&lt;br /&gt;      --Gera os registro de data de movimento em um dia.&lt;br /&gt;      for dd in 1..10000 loop   &lt;br /&gt;&lt;br /&gt; v_dt(dd) := ((to_date('05/07/2009 23:59:59','dd/mm/rrrr hh24:mi:ss')+dbms_random.value)-1);                 &lt;br /&gt;&lt;br /&gt;      end loop;   &lt;br /&gt;&lt;br /&gt;      --Termina o processo&lt;br /&gt;      dbms_random.terminate;&lt;br /&gt;&lt;br /&gt;      --Popular as datas geradas aleatoriamente&lt;br /&gt;      dbms_random.seed(99999);&lt;br /&gt;&lt;br /&gt;      --Gera os registros de quantidade movimentada&lt;br /&gt;      for dd in 1..10000 loop      &lt;br /&gt;          v_qtd(dd) := dbms_random.value(1,100);                 &lt;br /&gt;      end loop;       &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;      for dd in 1..v_dt.count loop&lt;br /&gt;&lt;br /&gt;         --Insere as movimentações&lt;br /&gt;         insert into tb_movimento&lt;br /&gt;           (id_movimento, dt_movimento, qtd_movimentada, cod_item)&lt;br /&gt;         values&lt;br /&gt;           (dd, v_dt(dd), v_qtd(dd), 'CDROM');&lt;br /&gt;&lt;br /&gt;      end loop;  &lt;br /&gt;&lt;br /&gt;   commit;&lt;br /&gt;end;              &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;3 - Devemos criar a package que irá conter a função de pipelined, vamos chamá-la de pck_pipelined. Como uma função de pipelined retorna sempre uma coleção de dados, precisamos criar a estrutura de retorno, que pode ser um Record Type ou um Array. Utilizarei um Record Type. Vamos chamá-las de typ_periodo. Depois de criado, vamos criar uma tabela deste nosso novo Record.&lt;/p&gt;

&lt;p&gt;Na declaração da assinatura da função de pipelined, devemos emitir o comando pipelined logo após a determinação do tipo de retorno, este comando é responsável por identificar a função como pipelined. Para retorno dos dados, vamos declarar a variável v_record do tipo do  typ_periodo, declarado no spec da package.&lt;/p&gt;

&lt;p&gt;Também e possível validar as informações da mesma forma que em uma procedure. Neste exemplo o parâmetro p_dt_ini não poderá ser maior que p_dt_fim e o parâmetro p_segundo não poderá ser menor que 60, caso seja, será emitido um erro na tela para o usuário. Dentro do comando while, emitimos o comando pipe row, este é utilizado para retornar a variável com o conteúdo que formará o registro.&lt;/p&gt;

&lt;p&gt;Como toda função, ela precisa ter um return, que este é emitido no final da função.&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;--Spec da package&lt;br /&gt;create or replace package pck_pipelined&lt;br /&gt;is&lt;br /&gt;&lt;br /&gt;type typ_periodo is record (de date,&lt;br /&gt;                            ate date,&lt;br /&gt;                            qtd_movimento number);&lt;br /&gt;&lt;br /&gt;type typ_tb_periodo is table of typ_periodo;      &lt;br /&gt;&lt;br /&gt;function fnc_periodo(p_dt_ini  in date,&lt;br /&gt;                     p_dt_fim  in date,&lt;br /&gt;                     p_segundo in number,&lt;br /&gt;                     p_item    in varchar2)&lt;br /&gt;return typ_tb_periodo pipelined;                     &lt;br /&gt;&lt;br /&gt;end pck_pipelined;&lt;br /&gt;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;--Body da package&lt;br /&gt;create or replace package body pck_pipelined&lt;br /&gt;is&lt;br /&gt;function fnc_periodo(p_dt_ini in date,&lt;br /&gt;                     p_dt_fim in date,&lt;br /&gt;                     p_segundo in number,&lt;br /&gt;                     p_item    in varchar2)&lt;br /&gt;return typ_tb_periodo pipelined&lt;br /&gt;is&lt;br /&gt;--Variável do tipo typ_periodo, declarado no spec da package anteriormente&lt;br /&gt;v_record          typ_periodo;&lt;br /&gt;v_dt_base_ini     date;&lt;br /&gt;v_dt_base_fim 	   date;&lt;br /&gt;v_qtd_movimento   number;&lt;br /&gt;&lt;br /&gt;begin&lt;br /&gt;&lt;br /&gt;--Se a data inicial for maior que a data final, interrompe o processamento&lt;br /&gt;if(p_dt_ini &amp;gt; p_dt_fim)then&lt;br /&gt; raise_application_error(-20001,'A data inicial não pode ser maior que a data final!');&lt;br /&gt;end if;&lt;br /&gt;&lt;br /&gt;--Se o período for menor que 60 segundos interrompe o processamento&lt;br /&gt;if(p_segundo &amp;lt; 60)then&lt;br /&gt; raise_application_error(-20002,'Os segundos não podem ser menores que 60');&lt;br /&gt;end if;&lt;br /&gt;&lt;br /&gt;v_dt_base_ini  := to_date(p_dt_ini,'dd/mm/rrrr hh24:mi:ss') + (1/24/60/60);&lt;br /&gt;v_dt_base_fim  := to_date(p_dt_ini,'dd/mm/rrrr hh24:mi:ss') + ((1/24/60/60) * p_segundo);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  while trunc(v_dt_base_fim) &amp;lt; trunc(p_dt_fim+1) loop&lt;br /&gt;&lt;br /&gt;              select nvl(sum(qtd_movimentada),0)&lt;br /&gt;                into v_qtd_movimento&lt;br /&gt;                from tb_movimento&lt;br /&gt;               where dt_movimento between v_dt_base_ini and v_dt_base_fim&lt;br /&gt;                 and cod_item = p_item;&lt;br /&gt;&lt;br /&gt;               --Alimenta a variável do tipo record&lt;br /&gt;               v_record.qtd_movimento := v_qtd_movimento;&lt;br /&gt;               v_record.de  := v_dt_base_ini;&lt;br /&gt;               v_record.ate := v_dt_base_fim;&lt;br /&gt;&lt;br /&gt;               --Retorna a variável&lt;br /&gt;        pipe row (v_record);&lt;br /&gt;&lt;br /&gt;               v_dt_base_ini  := v_dt_base_fim + (1/24/60/60);&lt;br /&gt;               v_dt_base_fim  := v_dt_base_fim + ((1/24/60/60) * p_segundo);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;   end loop;    &lt;br /&gt;&lt;br /&gt;   v_dt_base_fim  := v_dt_base_ini + ((1/24/60/60) * (p_segundo-2));&lt;br /&gt;&lt;br /&gt;              select nvl(sum(qtd_movimentada),0)&lt;br /&gt;                into v_qtd_movimento&lt;br /&gt;                from tb_movimento&lt;br /&gt;               where dt_movimento between v_dt_base_ini and v_dt_base_fim&lt;br /&gt;                 and cod_item = p_item;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;       --Alimenta a variável do tipo record&lt;br /&gt;               v_record.qtd_movimento := v_qtd_movimento;&lt;br /&gt;               v_record.de  := v_dt_base_ini;&lt;br /&gt;               v_record.ate := v_dt_base_fim;&lt;br /&gt;&lt;br /&gt;        --Retorna a variável&lt;br /&gt;               pipe row (v_record);&lt;br /&gt;&lt;br /&gt;  --Finaliza a função emitindo o comando de retorno, comum em toda função&lt;br /&gt;  return;&lt;br /&gt;&lt;br /&gt;end fnc_periodo;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;end pck_pipelined;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;4 - Vamos executar esta função.&lt;/p&gt;&lt;p&gt;Uma função de pipelined não pode ser executada como uma função comum. Para executá-la devemos fazer um select em sua estrutura, e transformar a função em uma tabela virtual utilizando o comando table:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; select *&lt;br /&gt;    from (table(pck_pipelined.fnc_periodo(to_date('05/07/2009'),&lt;br /&gt;                                          to_date('05/07/2009'),&lt;br /&gt;                                          60,&lt;br /&gt;                                          'CDROM')))&lt;br /&gt;   ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt; Logo o resultado será:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;De - Até&lt;br /&gt;&lt;/th&gt;&lt;th&gt;Quant. Movimento&lt;br /&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:00:01 - 5/7/2009 00:01:00&lt;/td&gt;&lt;td&gt;304&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:01:01 - 5/7/2009 00:02:00&lt;/td&gt;&lt;td&gt;282&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:02:01 - 5/7/2009 00:03:00&lt;/td&gt;&lt;td&gt;198&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:03:01 - 5/7/2009 00:04:00&lt;/td&gt;&lt;td&gt;44&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:04:01 - 5/7/2009 00:05:00&lt;/td&gt;&lt;td&gt;312&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:05:01 - 5/7/2009 00:06:00&lt;/td&gt;&lt;td&gt;563&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:06:01 - 5/7/2009 00:07:00&lt;/td&gt;&lt;td&gt;170&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:07:01 - 5/7/2009 00:08:00&lt;/td&gt;&lt;td&gt;363&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:08:01 - 5/7/2009 00:09:00&lt;/td&gt;&lt;td&gt;463&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:09:01 - 5/7/2009 00:10:00&lt;/td&gt;&lt;td&gt;347&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:10:01 - 5/7/2009 00:11:00&lt;/td&gt;&lt;td&gt;215&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:11:01 - 5/7/2009 00:12:00&lt;/td&gt;&lt;td&gt;304&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5/7/2009 00:12:01 - 5/7/2009 00:13:00&lt;/td&gt;&lt;td&gt;30&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Conforme o layout esperado.&lt;/p&gt;

&lt;p&gt;Também podemos relacionar a função de pipelined com outras tabelas em um select.&lt;/p&gt;

&lt;p&gt;No oracle 9i, não é suportada a seleção de todas as tuplas utilizando o identificador select *, devendo ser declaradas as colunas manualmente, da seguinte forma:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; select de, ate, qtd_movimento&lt;br /&gt;  2   from (table(pck_pipelined.fnc_periodo(to_date('05/07/2009','dd/mm/rrrr'),&lt;br /&gt;  3                                         to_date('05/07/2009','dd/mm/rrrr'),&lt;br /&gt;  4                                         60,&lt;br /&gt;  5                                         'CDROM')))&lt;br /&gt;  6  ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;5 - Vamos simular o erro previsto em nossa função.&lt;br /&gt; Passaremos a data final maior que a data inicial para induzir o erro:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt; select de, ate, qtd_movimento&lt;br /&gt;  2   from (table(pck_pipelined.fnc_periodo(to_date('05/07/2009','dd/mm/rrrr'),&lt;br /&gt;  3                                         to_date('01/07/2009','dd/mm/rrrr'),&lt;br /&gt;  4                                         60,&lt;br /&gt;  5                                         'CDROM')))&lt;br /&gt;  6  ;&lt;br /&gt;&lt;br /&gt;select de, ate, qtd_movimento&lt;br /&gt; from (table(pck_pipelined.fnc_periodo(to_date('05/07/2009','dd/mm/rrrr'),&lt;br /&gt;                                       to_date('01/07/2009','dd/mm/rrrr'),&lt;br /&gt;                                       60,&lt;br /&gt;                                       'CDROM')))&lt;br /&gt;&lt;br /&gt;ORA-20001: A data inicial não pode ser maior que a data final!&lt;br /&gt;ORA-06512: em &quot;PROJETO.PCK_PIPELINED&quot;, line 17&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;6 - Também podemos ordernar a listagem:&lt;/p&gt;

&lt;div class=&quot;codigo&quot;&gt;&lt;pre&gt;&lt;code&gt;SQL&amp;gt;     select de, ate, qtd_movimento&lt;br /&gt;  2       from (table(pck_pipelined.fnc_periodo(to_date('05/07/2009','dd/mm/rrrr'),&lt;br /&gt;  3                                             to_date('05/07/2009','dd/mm/rrrr'),&lt;br /&gt;  4                                             60,&lt;br /&gt;  5                                             'CDROM')))&lt;br /&gt;  6    order by qtd_movimento desc&lt;br /&gt;  7 ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Como em toda função que é utilizada em selects, a função de pipelined também não permite utilização de comandos DML. Com a utilização das funções de pipelined podemos reduzir muito o tempo de desenvolvimento.&lt;/p&gt;

&lt;p&gt;No próximo artigo abordarei sobre a velocidade de processamento na utilização de uma função de pipelined. Até lá!&lt;/p&gt;				</description>
            <author>leonardo.litz@gmail.com (Leonardo Litz)</author>
            <pubDate>Fri, 31 Jul 2009 10:00:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/13745</guid>
        </item>
        <item>
            <title>Desfragmentar faz bem</title>
            <link>http://imasters.uol.com.br/artigo/13573/sql_server/desfragmentar_faz_bem/</link>
            <description>&lt;p&gt;Olá, pessoal. No artigo desta semana abordarei um assunto muito importante para quem trabalha com bancos de dados considerados grandes: a reindexação. Apresentarei quais são as características de bancos de dados que levam à reindexação, como detectá-la, o planejamento da sua execução e a medição dos resultados.&lt;/p&gt;


&lt;p&gt;Em geral, a análise da fragmentação de índices é uma das etapas mais importantes. Não me esqueço de verificar isso durante a análise inicial de um banco de dados, quando trabalho em alguma consultoria relacionada a problemas de desempenho. Em outras palavras, isso quer dizer que, infelizmente, encontro com mais freqüência do que gostaria diversos problemas relacionados à falta de desfragmentação dos índices das tabelas do banco de dados.&lt;/p&gt;


&lt;p&gt;Muitos bancos de dados possuem um crescimento considerável ao longo do tempo devido a vários fatores, como o tipo de sistema utilizado, o volume de dados, as operações da empresa, integrações gerais, falta de manutenção e outros. Conforme o banco de dados vai sendo utilizado, a tendência é que ele fique cada vez mais cheio se não houver uma preocupação em &quot;esvaziá-lo&quot;, ou seja, uma manutenção periódica. &lt;/p&gt;


&lt;p&gt;Um dos efeitos colaterais da utilização operacional dos bancos de dados para sistemas de ERP, CRM, Ponto de Venda e outros é a modificação da característica de ordenação dos índices. Sim, conforme os dados vão sendo inseridos, alterados ou excluídos das tabelas, há também uma modificação nas páginas de índices, independente do tipo de índice utilizado. A grosso modo, é possível imaginar que logo após a criação de um índice (com &lt;em&gt;fill factor&lt;/em&gt;=100%) todas as suas páginas estão corretamente ordenadas e conectadas, como mostra o exemplo da Figura 1.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://conteudo.imasters.uol.com.br/13573/Figura1_IndiceConstruido.png&quot; alt=&quot;Figura 1. Páginas de índices recém criadas&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;span class=&quot;c4&quot;&gt;Figura 1. Páginas de índices recém criadas&lt;/span&gt;&lt;/p&gt;


&lt;p&gt;Na Figura 1 os retângulos em azul representam as páginas do índice, independente do tipo. As setas pretas mostram como estas páginas estão conectadas de forma ordenada e a seta vermelha indica o sentido que o SQL Server irá utilizar quando for procurar dados neste índice. É claro que esta representação de páginas de índices é uma abstração, pois internamente o SQL Server utiliza árvores binárias e outros recursos para percorrer as páginas de índices. Porém para a explicação de fragmentação este exemplo é útil.&lt;/p&gt;


&lt;p&gt;Como dito anteriormente, conforme há modificação, inserção e deleção de dados nas tabelas, o índice começa a ser fragmentando logicamente, ou seja, a páginas de dados deste índice não mais vão ser conectadas em seqüência, como mostrado na Figura 1.&lt;/p&gt;


&lt;p&gt;Aqui vamos abrir um pequeno parêntese. Existem diversas formas de fragmentação e provavelmente cada pessoa pensa algo diferente quando escuta essa palavra. Talvez o primeiro conceito que venha à mente de muitos quando escutam a palavra fragmentação é a fragmentação física do disco rígido (HD). Apesar desta fragmentação física ser importante para a localização de dados no disco rígido, este assunto não será tratado neste artigo. Entretanto, recomenda-se utilizar alguma ferramenta especializada para desfragmentar o disco rígido do servidor de acordo com a recomendação do próprio sistema operacional, desde que o banco de dados esteja devidamente parado e que esta desfragmentação seja realizada em um horário de manutenção e sob supervisão. &lt;/p&gt;


&lt;p&gt;Voltado para a desfragmentação lógica de páginas de índice no SQL Server, após a utilização operacional durante um período de tempo é comum que a estrutura de páginas de índice de uma tabela do SQL Server fique parecida com o desenho apresentado na figura 2.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://conteudo.imasters.uol.com.br/13573/Figura2_IndiceFragmentado.png&quot; alt=&quot;Figura 2. Páginas de índices após uso natural da tabela&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;span class=&quot;c4&quot;&gt;Figura 2. Páginas de índices após uso natural da tabela

&lt;/span&gt;&lt;/p&gt;


&lt;p&gt;A figura 2 mostra que algumas páginas de índice não estão mais completas, devido a &lt;em&gt;page splits&lt;/em&gt;, e outras páginas foram removidas, devido à modificação dos dados. É possível perceber também que as páginas não estão mais conectas em sequência como na figura 1. Sem entrar em detalhes, a desfragmentação deste índice pode ser útil nesta situação, pois ela fará com que as páginas sejam reconstruídas alocando os dados novamente. Além disso, a desfragmentação criará uma nova ordem de conexão entre as páginas.&lt;/p&gt;


&lt;p&gt;O cenário acima provavelmente ocorre em bancos de dados grandes, com tamanhos acima de 50 GB. Obviamente que esta é uma afirmação genérica e cada banco de dados precisa ser analisado para indicar ou não a presença de fragmentação. Contudo, nos bancos de dados grandes geralmente encontramos o seguinte cenário: um pequeno conjunto de tabelas, entre 3 e 10, é responsável pela maior parte do banco de dados enquanto as demais tabelas ocupam pouco espaço. É a famosa regra que diz que 20% do total são responsável por 80% do resto, porém aplicada ao tamanho de algumas tabelas e ao banco de dados. Resultado: o pequeno conjunto de tabelas contém as prováveis tabelas candidatas para a reindexação. &lt;/p&gt;


&lt;p&gt;Isso me lembra um pouco da época dos sistemas desenvolvidos em Clipper, ou tecnologia similar, com bancos de dados no padrão xBase. Apesar da nostalgia, lembro que naquela época a reindexação era uma necessidade operacional e que, infelizmente, era uma desculpa muito utilizada para justificar erros no sistema ou comportamentos bizarros. Felizmente as tecnologias de bancos de dados atuais evoluíram ao ponto onde a reindexação não mais pode ser utilizada como desculpa para certas situações ou inconsistências no sistema.&lt;/p&gt;


&lt;p&gt;Antes de partir para a reindexação é preciso verificar se ela é realmente necessária. Aqui recomendo analisar primeiro o grupo de tabelas com um tamanho grande de dados antes de partir para a estratégia de reindexação. Para aqueles que não sabem como obter informações sobre o tamanho da tabela, recomendo a utilização da system stored procedure &lt;em&gt;sp_spaceused&lt;/em&gt; e também uma lida na documentação da tabela de sistema chamada &lt;em&gt;sysindexes&lt;/em&gt;, pois assim é possível identificar rapidamente quais são as tabelas que ocupam muito espaço e que provavelmente possuem problemas de fragmentação lógica.&lt;/p&gt;


&lt;p&gt;Após descobrir quais são as tabelas que ocupam muito espaço em disco é preciso verificar a fragmentação dos seus índices. Recomendo utilizar o comando DBCC SHOWCONTIG para cada índice de cada tabela de modo a verificar a fragmentação lógica. Esse comando é tão importante que é comum encontrar nas provas oficiais de certificação da Microsoft algumas questões que cobrem o conhecimento do seu resultado.  Sem entrar em detalhes específicos, a Figura 3 apresenta o resultado da execução do comando DBCC SHOWCONTIG reportando a análise do único índice da tabela chamada Tabela1.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://conteudo.imasters.uol.com.br/13573/Figura3_ComandoDBCC.png&quot; alt=&quot;Figura 3. Relatório apresentado pelo comando DBCC SHOWCONTIG&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;span class=&quot;c4&quot;&gt;Figura 3. Relatório apresentado pelo comando DBCC SHOWCONTIG&lt;/span&gt;&lt;/p&gt;


&lt;p&gt;O valor destacado pelo retângulo vermelho da Figura 1 indica o quão fragmentado este índice está. Quando mais próximo de 0%, mais fragmentado ele estará, ou seja, valores menores indicam que a desfragmentação pode ser benéfica. Notem que a execução do comando DBCC SHOWCONTIG pode demorar de acordo com o tamanho da tabela e que devemos procurar utilizar este comando durante uma janela de manutenção do banco de dados, assim como a desfragmentação. Obviamente que existem diversos outros valores a serem analisados, porém, sem entrar em maiores detalhes, basta uma rápida olhada no resultado do comando DBCC SHOWCONTIG e já obtemos indícios sobre o a fragmentação do índice.&lt;/p&gt;


&lt;p&gt;Aqui cabe indicar que os benefícios de fragmentação são vários: desde a redução do espaço ocupado pela tabela até a melhora no desempenho das instruções que utilizam o índice da tabela em questão. A razão destes benefícios é simples: quando menos páginas são necessárias para manipular os dados das tabelas, a tendência é que a execução das instruções seja mais rápida.&lt;/p&gt;


&lt;p&gt;Existem várias maneiras de se desfragmentar um índice. Porém, antes de fazê-lo, é preciso tomar algumas cuidados. Em primeiro lugar deve-se sempre contar com um backup antes de realizar esta manutenção, que deve ser feita durante uma janela de manutenção devido aos impactos negativos no desempenho do banco de dados causados pelo processo de desfragmentação. Em segundo lugar é preciso monitorar e adequar o tamanho do Transacion Log, pois a desfragmentação de índices que ocupam muito espaço requer uma grande movimentação de dados que, sem sombra de dúvida, utiliza muito o Transacion Log. Em terceiro lugar, mas não menos importante, é preciso desfragmentar um índice por vez e medir o tempo e o espaço antes e depois da desfragmentação para comprovar se houve algum ganho ou não. &lt;/p&gt;


&lt;p&gt;Seguidas estas recomendações podemos prosseguir no processo de desfragmentação. Como geralmente alguns índices são associados à chaves primárias ou estrangeiras, recomendo a utilização do comando DBCC INDEXDEFRAG, pois assim pode-se desfragmentar o índice sem afetar os objetos associados a ele. Porém esta é uma recomendação genérica que deve ser avaliada de acordo com as características de cada ambiente.&lt;/p&gt;


&lt;p&gt;Por fim vale a pena identificar os ganhos ou perdas obtidos com a desfragmentação. Como é de praxe, recomenda-se montar um gráfico ou algum tipo de visualização de dados que auxilie a comprovação e evidencie os resultados. Por exemplo: o gráfico da Figura 4 mostra o ganho que obtive no tamanho de uma base de dados real após a desfragmentação de alguns índices.&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://conteudo.imasters.uol.com.br/13573/Figura4_GraficoDesfragmentacao.png&quot; alt=&quot;Figura 4. Gráfico mostrando os espaço ocupado pela Base 1 antes e depois da desfragmentação.&quot; /&gt;&lt;/p&gt;


&lt;p&gt;&lt;span class=&quot;c4&quot;&gt;Figura 4. Gráfico mostrando o espaço ocupado pela Base 1 antes e depois da desfragmentação.&lt;/span&gt;&lt;/p&gt;


&lt;p&gt;No gráfico da figura 4 pode-se notar que o banco de dados ocupava aproximadamente 33,1 GB apenas com dados e índices antes da desfragmentação. Após a análise das tabelas e da desfragmentação dos índices de 4 tabelas o tamanho do banco de dados foi reduzido para aproximadamente 29,3 GB, o que dá um ganho de aproximadamente 3,7 GB ou aproximadamente 11,2% de redução em relação ao tamanho inicial. Este resultado de tamanho em disco pôde ser medido imediatamente após a desfragmentação, porém outros efeitos benéficos foram constatados devido à redução da quantidade de páginas de índices.&lt;/p&gt;


&lt;p&gt;Em resumo, vale a pena analisar o banco de dados em busca das tabelas que ocupam mais espaço e procurar montar uma estratégia para organizar uma reindexação nos índices, preferencialmente de forma automática e periódica. Quem sabe esta pode ser a pedra no sapato que tanto acaba influenciando no problema de desempenho que ninguém sabe exatamente onde é.&lt;/p&gt;


&lt;p&gt;Um grande abraço e até a próxima, pessoal. &lt;/p&gt;

</description>
            <author>pichiliani@gmail.com (Mauro Pichiliani)</author>
            <pubDate>Mon, 20 Jul 2009 09:00:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/13573</guid>
        </item>
        <item>
            <title>Que tipo de DBA é você?</title>
            <link>http://imasters.uol.com.br/artigo/13518/oracle/que_tipo_de_dba_e_voce/</link>
            <description>&lt;p&gt;A carreira do profissional de banco de dados (DBA) é cercada de especializações, pelo motivo de trabalhar com diversas áreas do TI, como desenvolvimento, projetos, infra-estrutura e etc. É natural que o DBA, com o passar dos anos, tenha preferências ou &quot;seja forçado&quot; a trabalhar com áreas específicas, criando assim um perfil do administrador de banco de dados. Veja os diversos tipos de DBAs abaixo:&lt;/p&gt;


&lt;h4&gt;&lt;strong&gt;DBA Desenvolvedor&lt;/strong&gt;&lt;/h4&gt;


&lt;p&gt;É o profissional que desde administrar o banco de dados também desenvolve a aplicação, tem no perfil as seguintes características:&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;Profundos conhecimentos na linguagem de programação local;&lt;/li&gt;

&lt;li&gt;Conhecimentos em instalação e administração do banco de dados;&lt;/li&gt;

&lt;li&gt;Sempre preocupado com a qualidade e manutenção das querys;&lt;/li&gt;

&lt;li&gt;Procura sempre o mais performático, mesmo que a atividade não seja uma boa prática;&lt;/li&gt;

&lt;li&gt;Fortes conhecimentos em modelagem de dados, sabe aplicar a 3FN (brincadeira);&lt;/li&gt;

&lt;li&gt;Trabalha sobre prazos e acostumado a &quot;martelar&quot; o banco de dados ou aplicação para que seja entregue na data prevista.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Geralmente, o DBA desenvolvedor é lider de desenvolvimento ou atua como um guro na equipe, mandando orientações aos novos integrantes, organizando as atividades e analisando todos os requisitos de desenvolvimento.&lt;/p&gt;


&lt;h4&gt;&lt;strong&gt;DBA Infra-Estrutura&lt;/strong&gt;&lt;/h4&gt;


&lt;p&gt;É o profissional que conhece toda a infra-estrutura necessária para a implementação do banco de dados, atua desde a concepção do hardware até a analise da infra-estrutura local do banco de dados, tem as seguintes características:&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;Profundos conhecimentos da arquitetura e administração Oracle;&lt;/li&gt;

&lt;li&gt;Profundos conhecimentos em infra-estrutura, desde a configuração do hardware, cabeamento, switch, sistema operacional e backup &amp;amp; recover;&lt;/li&gt;

&lt;li&gt;Especialidade em performance ao nível de sistema operacional e instância Oracle;&lt;/li&gt;

&lt;li&gt;Extremamente cuidadoso no momento de aplicação de patches no banco de dados e sistema operacional;&lt;/li&gt;

&lt;li&gt;Trabalha mais voltado a projetos e implementação de novos recursos de banco de dados ou aplicação;&lt;/li&gt;

&lt;li&gt;Responsável em adotar as boas práticas para administração do banco de dados, mesmo que isso crie conflitos internamente na equipe.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;O DBA Infra-Estrutura geralmente não dá tanta importância para as aplicações da empresa, costuma se preocupar apenas com o banco de dados e afeta diretamente a vida o SYSADMIN, pois tudo que o SYSADMIN fizer que tenha banco de dados no meio, ele irá questionar.&lt;/p&gt;


&lt;h4&gt;&lt;strong&gt;DBA Projetos&lt;/strong&gt;&lt;/h4&gt;


&lt;p&gt;É o perfil do profissional que já foi um DBA Desenvolvedor e Infra-Estrutura, sabe como funciona cada área é aplica as boas práticas na construção da aplicação e na infra-estrutura para o banco de dados, suas principais características são:&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;Bons conhecimentos em desenvolvimento de aplicações;&lt;/li&gt;

&lt;li&gt;Bons conhecimentos sobre o produto e arquitetura Oracle;&lt;/li&gt;

&lt;li&gt;Gerencia os prazos das atividades, aquisição de produtos extras, manutenção na aplicação, patches de banco de dados e requisitos básicos da infra-estrutura;&lt;/li&gt;

&lt;li&gt;Costuma usar o Microsoft Project para se organizar e documenta todas as suas atividades;&lt;/li&gt;

&lt;li&gt;Acostumado a opinar/sugerir/questionar o comportamento&lt;/li&gt;

&lt;li&gt;Acostumado a delegar as atividades básicas de administração do banco de dados e cuidar apenas dos projetos que envolvem o banco de dados e a burocracia da empresa.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;O DBA Projetos é conhecido com o &quot;cara&quot; do projeto da empresa, pois é ele que em diversas reuniões com dezenas de áreas costuma a questionar e interrogar os participantes para coletar as informações no momento de criar o projeto do banco de dados.&lt;/p&gt;


&lt;p&gt;Com sua experiência, ele consegue detectar muitos problemas e possui pró-atividade em suas atividades.&lt;/p&gt;


&lt;p&gt;Agora, para descontrair um pouco, vamos falar sobre as outras vertentes da carreira de um DBA, aquelas vertentes que são comentadas pela &lt;em&gt;&quot;rádio Peão&quot;&lt;/em&gt; da empresa, como:&lt;/p&gt;


&lt;h4&gt;&lt;strong&gt;DBA Cafeteira&lt;/strong&gt;&lt;/h4&gt;


&lt;p&gt;É o profissional que passa mais tempo tomando café e fumando que trabalhando efetivamente. Porém, resolve os problemas da empresa rapidamente.&lt;/p&gt;


&lt;h4&gt;&lt;strong&gt;DBA Google&lt;/strong&gt;&lt;/h4&gt;


&lt;p&gt;Esse é o profissional criado dentro do SIBEL ou qualquer outra ferramenta de gerenciamento de mudanças,  conhecido pelas filas de CHAMADOS! Passa a maior parte de sua vida atendendo chamados para produção ou desenvolvimento, tendo que aprender todos os tipos de coisas possíveis que existem no mundo Oracle, por isso que falam que um DBA Google sem internet não trabalha!&lt;/p&gt;


&lt;p&gt;Mas é muito bom para quem quer aprender banco de dados, aprende e tem noção de tudo!&lt;/p&gt;


&lt;h4&gt;&lt;strong&gt;DBA Bombeiro&lt;/strong&gt;&lt;/h4&gt;


&lt;p&gt;Essa vertente é a pós-graduação do DBA Google, pois em algum momento da vida o DBA Google fica revoltado com a vida que tem e quer mudar de empresa, e a empresa em que ele será empregado é um consultoria com N clientes e ele deverá atender todos.&lt;/p&gt;


&lt;p&gt;Deste modo, acaba surgindo o DBA Bombeiro, pois ele vai para os clientes apenas para apagar incêndios a todo momento, não consegue prosseguir em uma especialização. E para ajudar, é o perfil de DBA que costuma a receber um celular ou Page para ficar 24x7 para a empresa.&lt;/p&gt;


&lt;p&gt;Também muito conhecido pelas suas olheiras, que vêm com o tempo!&lt;/p&gt;


&lt;h4&gt;&lt;strong&gt;DBA Ghost&lt;/strong&gt;&lt;/h4&gt;


&lt;p&gt;Esse é o perfil de um profissional que escutou de alguém que DBA ganha bem, que sendo DBA ele irá prosperar em sua vida financeira e terá tudo que o mundo pode vender para ele, assim sendo, alguém muito conhecido consegue arrumar uma vaga na área de banco de dados e quando ele realmente consegue entrar, possui as características abaixo:&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;Não sabe administrar o banco de dados;&lt;/li&gt;

&lt;li&gt;Quando há problemas, ele desaparece;&lt;/li&gt;

&lt;li&gt;Não atende o celular após as 18 horas nunca;&lt;/li&gt;

&lt;li&gt;Mata dezenas de parentes no ano para justificar suas faltas;&lt;/li&gt;

&lt;li&gt;Não gosta de estudar, ler livros, buscar conhecimentos e muito mesmo debater assuntos referentes a Oracle;&lt;/li&gt;

&lt;li&gt;E o melhor, só aparece para receber o salário.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Acho que é isso, pessoal, deu para entender um pouco como funciona a carreira de um profissional de banco de dados Oracle, muitos área de especializações ou até mesmo uma generalização de tudo, com muita moderação, não diga que sabe trabalhar com RAC, sendo que nunca viu como funciona RAC em sua frente.&lt;/p&gt;


&lt;p&gt;Certificação é importante e recomendo a todos, porém o Certificado Oracle, seja ele um OCA ou OCP, não vai dar garantias que seja o melhor profissional de todos os tempos, pois certificação não é garantia de qualidade no serviço.&lt;/p&gt;


&lt;p&gt;Abraços.&lt;/p&gt;

</description>
            <author>dbarodrigo@gmail.com (Rodrigo Almeida)</author>
            <pubDate>Tue, 14 Jul 2009 10:00:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/13518</guid>
        </item>
        <item>
            <title>Check-List para auditoria SOX em Oracle</title>
            <link>http://imasters.uol.com.br/artigo/13327/bancodedados/check-list_para_auditoria_sox_em_oracle/</link>
            <description>&lt;p&gt;Olá! &lt;/p&gt;


&lt;p&gt;Recentemente estive sobre os olhares da auditoria Sarbanes-Oxley (SOX) para os bancos de dados Oracle da empresa que trabalho e gostaria de compartilhar alguns check-lists necessários para os DBAs passarem sem muitos problemas dessa auditoria.&lt;/p&gt;


&lt;h4&gt;Sobre a Lei Sarbanes-Oxley (SOX)&lt;/h4&gt;


&lt;p&gt;A auditoria SOX, foi criada em 2002 pelo senador Paul Sarbanes e deputado Michael Oxley, nos EUA, tendo como objetivo controlar e investigar todos os investimentos estrangeiros de empresas que possuem capital aberto no mercado, afim de evitar grandes fraudes e governança inapropriada.&lt;/p&gt;


&lt;p&gt;Como muitas empresas que possuem operações financeiras no exterior, a SOX promove a criação de processos de auditoria e segurança em todos os departamentos da empresa, a fim de torná-la uma empresa confiável, transparente e principalmente segura.&lt;/p&gt;


&lt;p&gt;Deste modo, a atenção ao departamento de Tecnologia da Informação é uma parte muito importante durante uma auditoria SOX, pois os sistemas da empresa devem ser seguros e seguir diversos processos internos elaborados pelas suas gestões para prevenir fraudes.&lt;/p&gt;


&lt;p&gt;O banco de dados acaba sendo um alvo certo no processo de auditoria, porque simplesmente, armazena todos os dados vitais de uma empresa, e essa &quot;caixa&quot; de dados precisa ser segura e de acesso controlado, tornando uma dor de cabeça aos DBAs e projetos da empresa, porque muitas restrições são impostas.&lt;/p&gt;


&lt;p&gt;Vocês poderão ver essas restrições impostas no check-list abaixo, onde são pontos que os auditores pedem evidências sobre o processo e/ou atividade realizada. Todo o check-list foi realizado para ambientes de bancos de dados Oracle.&lt;/p&gt;


&lt;p&gt;Primeiramente, vamos iniciar o nosso check-list partindo da infra-estrutura, ou seja, o que é necessário para o ambiente de banco de dados estar de acordo com o SOX.&lt;/p&gt;


&lt;h4&gt;Infra-Estrutura&lt;/h4&gt;


&lt;ul&gt;&lt;li&gt;Backup &amp;amp; Recover em dia;&lt;/li&gt;

&lt;li&gt;Documentação da Estratégia de Backup &amp;amp; Recover para cada banco de dados;&lt;/li&gt;

&lt;li&gt;Evidências de testes de recover vindas de Fita e/ou disco, o verdadeiro LOG da operação;&lt;/li&gt;

&lt;li&gt;Padrão de instalação seguindo o OFA (Optimal Flexible Architecture);&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Para bancos de dados em ambientes Windows:&lt;/p&gt;

&lt;p&gt;Lista de usuários Locais do servidor;&lt;/p&gt;

&lt;p&gt;Permissões dos usuários e pastas Oracle;&lt;/p&gt;

&lt;p&gt;DUMPSEC dos servidores;&lt;/p&gt;

&lt;p&gt;Relacionamento de confiança entre os servidores;&lt;/p&gt;

&lt;p&gt;Lista de serviços do windows, para saber qual é necessário ou não;&lt;/p&gt;

&lt;p&gt;Lista de protocolos utilizados pelo servidor;&lt;/p&gt;

&lt;p&gt;Permissão dos arquivos listener.ora, sqlnet.ora e Executáveis;&lt;/p&gt;

&lt;p&gt;Permissão do Oratab;&lt;/p&gt;

&lt;p&gt;Arquivo de Parâmetro, quais e qual o motivo dos parâmetros;&lt;/p&gt;

&lt;p&gt;Informação sobre os processos do Windows Scheduler;&lt;/p&gt;

&lt;p&gt;Informações sobre os processos Batch, não é permitido fixar a senha de usuários em hardcode;&lt;/p&gt;

&lt;p&gt;Informações sobre as últimas atualizações do Windows, principalmente de Vulnerabilidade.&lt;/p&gt;

&lt;p&gt;Para bancos de dados em ambientes Linux/Unix:&lt;/p&gt;

&lt;p&gt;Utilizar o umask 022 no profile Oracle;&lt;/p&gt;

&lt;p&gt;Fornecer os detalhes do profile default dos usuários e csh.login do sistema operacional;&lt;/p&gt;

&lt;p&gt;Lista de serviços que estão executando, e desativar os desnecessários.&lt;/p&gt;

&lt;p&gt;Lista dos usuários do DBA Group;&lt;/p&gt;

&lt;p&gt;Permissão dos arquivos, diretórios e FileSystem do Oracle User;&lt;/p&gt;

&lt;p&gt;Permissão do OraTab;&lt;/p&gt;

&lt;p&gt;Permissão de shell scripts, não é permitido fixar a senha de usuários em hardcode;&lt;/p&gt;

&lt;p&gt;Permissão nos arquivos Listener.ora, sqlnet.ora e Executáveis/Libs;&lt;/p&gt;

&lt;p&gt;Arquivo de Parâmetro, quais e qual o motivo dos parâmetros;&lt;/p&gt;

&lt;p&gt;Informações sobre os processos da Crontab e suas permissões.&lt;/p&gt;

&lt;p&gt;Informações de permissão sobre os arquivos de dados, traces e log;&lt;/p&gt;

&lt;p&gt;Agora, vamos para um check-list mais refinado, internamente no banco de dados, o que o DBA deverá prestar atenção na auditoria, veja abaixo:&lt;/p&gt;


&lt;h4&gt;Banco de dados&lt;/h4&gt;


&lt;ul&gt;&lt;li&gt;Lista de usuários Genéricos, ou seja, Lista dos owners da aplicação;&lt;/li&gt;

&lt;li&gt;Lista de usuários Convencionais, os usuários finais;&lt;/li&gt;

&lt;li&gt;Lista de Profiles e seus parâmetros;&lt;/li&gt;

&lt;li&gt;A função VERIFY_PASS_FUNCTION deve ser programada para de acordo com a política de senha da empresa;&lt;/li&gt;

&lt;li&gt;Permissões de visualização no dicionário de dados Oracle, principalmente as views dba_source e dba_objects;&lt;/li&gt;

&lt;li&gt;Lista de permissão dos Usuários por objeto, role e grants de sistema;&lt;/li&gt;

&lt;li&gt;Lista de permissão dos usuáriso com WITH OPTION para concessão de permissão;&lt;/li&gt;

&lt;li&gt;Documentação do processo de Backup sobre os componentes lógicos, como tabelas, procedures, packages, functions e triggers;&lt;/li&gt;

&lt;li&gt;Documentação do processo de agendamento de Jobs ou a utiização do DBMS_SCHEDULER, Quem usa, Como usa e quem utiliza;&lt;/li&gt;

&lt;li&gt;O DBA não pode utilizar as contas SYS e SYSTEM, deve possuir uma conta própria e nomeada para cada profissional;&lt;/li&gt;

&lt;li&gt;Senha no Listener;&lt;/li&gt;

&lt;li&gt;Não utilizar autenticação via SO para logar-se como SYS AS SYSDBA;&lt;/li&gt;

&lt;li&gt;Utilizar arquivo de senha no banco de dados;&lt;/li&gt;

&lt;li&gt;Utilizar o parâmetro DBLINK_ENCRYPT_LOGIN = TRUE no banco de dados quando se trabalha com versões anteriores ao 9.2.0.1;&lt;/li&gt;

&lt;li&gt;Recomendação de habilitar o AUDIT_TRAIL = DB ou SO, mas é apenas recomendação, depende de analise de ambiente;&lt;/li&gt;

&lt;li&gt;Habilitar o parâmetro AUDIT_SYS_OPERATIONS = TRUE para auditoria no usuário SYS;&lt;/li&gt;

&lt;li&gt;Ocultar as autenticações no banco de dados pelo sistema operacional, usando o parâmetro OS_AUTHENT_PREFIX = &quot;;&lt;/li&gt;

&lt;li&gt;Ter habilitado o parâmetro REMOTE_LOGIN_PASSWORDFILE = EXCLUSIVE para administração remota.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Dependendo da empresa que irá auditar, alguns itens podem ser incluídos e outros nem solicitados, porém, nunca se sabe o que eles vão pedir, por isso, fica a recomendação e as devidas atenções de segurança.&lt;/p&gt;


&lt;p&gt;Outro detalhe importante sobre uma auditoria SOX, que os auditores pedem todos os documentos de processo e/ou atividade do banco de dados, portanto, mais e mais documentos são necessário para os nossos ambientes, como:&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;Documentação de Instalação do banco de dados;&lt;/li&gt;

&lt;li&gt;Documentação do controle de incidentes de banco de dados;&lt;/li&gt;

&lt;li&gt;Documentação do controle de alteração do banco de dados feitas atráves de aplicação, ou seja, quando é necessário incluir, deletar ou modificar algum objeto da base;&lt;/li&gt;

&lt;li&gt;Documentação dos serviços que estão sendo monitorados no banco de dados;&lt;/li&gt;

&lt;li&gt;Documentação de procedimentos de manutenção no banco de dados e etc;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Para a equipe de DBAs pode ser um imenso problema isso, porque documentar todo esses processos leva muito tempo e dificilmente um específico profissional sabe tudo sobre um determinado ambiente. Por um lado, a documentação é extremamente importante para equipes com muitos DBAs, ou empresa que possuem alta rotatividade desses profissionais, pois o ambiente fica muito mais controlado, seguro e fácil de se administrar. Eu sou totalmente favorável a qualquer tipo de documentação, tanto banco e aplicação.&lt;/p&gt;


&lt;p&gt;Uma recomendação importante quando for passar por auditoria SOX, são elas:&lt;/p&gt;


&lt;ul&gt;&lt;li&gt;O DBA deve ter um backup, ou seja, outro profissional que faça as mesmas tarefas quando ele ficar doente ou sair da empresa;&lt;/li&gt;

&lt;li&gt;Tenha ambientes separados para a aplicação, exemplo: Ambiente de DESENVOLVIMENTO, HOMOLOGAÇÂO e PRODUÇÂO;&lt;/li&gt;

&lt;li&gt;Tenha uma gestão de incidentes ou projeto que controle todas as transações sobre os ambientes mencionados acima;&lt;/li&gt;

&lt;li&gt;Todo o código PL/SQL que passe a terceiros ou outras filiais deve usar o aplicativo WRAP para criptografia dos dados e posteriormente comparar os checksum;&lt;/li&gt;

&lt;li&gt;Tenha ótimas estratégias de Backup &amp;amp; Recover;&lt;/li&gt;

&lt;li&gt;E um acesso restrito para querys em ambiente de produção.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;BOM! Acho que é isso pessoal, esses são alguns (&quot;grandes&quot;) check-lists para supotar uma auditoria da SOX, ou até melhor, para conhecer também um pouco mais sobre como proteger o seu banco de dados, não precisa passar por uma auditoria para poder implementar alguns sugestões que estão acima ou até mesmo, documentar os seus processos. São check-lists que é válido como um todo! &lt;/p&gt;


&lt;p&gt;Para mais informações, o &lt;a href=&quot;http://rodrigoalmeida.profissionaloracle.com.br&quot;&gt;meu Blog&lt;/a&gt; está a disposição.&lt;/p&gt;


&lt;p&gt;Abraços,&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.rodrigoalmeida.net/material/RA/assinatura.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;</description>
            <author>dbarodrigo@gmail.com (Rodrigo Almeida)</author>
            <pubDate>Wed, 01 Jul 2009 10:30:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/13327</guid>
        </item>
        <item>
            <title>Desperdiçando espaço em disco</title>
            <link>http://imasters.uol.com.br/artigo/13251/sql_server/desperdicando_espaco_em_disco/</link>
            <description>&lt;p&gt;Olá, pessoal. Hoje abordarei um assunto muito importante para quem trabalha com banco de dados de grandes tamanhos: o desperdício de espaço em disco devido ao uso incorreto de tipos de dados.&lt;/p&gt;

&lt;p&gt;Como consultor de banco de dados, uma das principais atividades com que me deparo durante o trabalho é analisar o modelo de dados dos sistemas que já estão em produção. Este trabalho requer um conhecimento básico do que o sistema faz e auxilia na identificação das diversas razões e motivos de problemas, principalmente os relacionados ao desempenho do banco de dados e consumo excessivo de recursos.&lt;/p&gt;

&lt;p&gt;Nas últimas consultorias que prestei, não pude deixar de notar a presença de uma prática não recomendada que, infelizmente, encontro com mais freqüência do que gostaria em diversos bancos de dados. Esta prática, que explicarei em seguida, está diretamente relacionada com a modelagem do banco de dados e com a cultura geral da falta de planejamento e modelagem adequada. Como conseqüência, diversos problemas aparecem, inclusive o desperdício de espaço em disco e problemas de desempenho. &lt;/p&gt;

&lt;p&gt;Explicarei uma situação de desperdício evidente a partir da modelagem do banco de dados. Em situações normais de temperatura e pressão, após a elaboração de requisitos e a especificação do que o sistema deve fazer, a equipe de desenvolvimento monta um diagrama entidade-relacionamento com as tabelas, colunas, tipos de dados, relacionamentos, etc. O problema começa aqui: em muitas situações não se dá a devida atenção aos tipos de dados de certas colunas. Mais especificamente, acaba-se usando tipos de dados superdimensionados para determinadas colunas, o que ocupa mais espaço em disco do que o necessário. Mesmo com a taxa de custo/megabyte diminuindo a cada dia, isso não quer dizer que devemos esbanjar e evitar tomar certos cuidados durante a modelagem dos tipos de dados.&lt;/p&gt;

&lt;p&gt;Um dos motivos para este super dimensionamento está relacionado com a falta de previsibilidade do crescimento e volume de dados que serão armazenados. Nem sempre é fácil identificar qual é o melhor tipo de dados para determinada coluna e, por causa disso, o modelo acaba pecando por excesso. Contudo, este pecado vai custar caro um dia devido ao crescimento.&lt;/p&gt;

&lt;p&gt;Vou comentar um exemplo prático. Em uma das consultorias que prestei, me deparei com um banco de dados cujo tamanho ocupava cerca de 50 GB, o que é um tamanho considerável de acordo com o hardware, a finalidade da aplicação e do banco de dados neste contexto. Analisando melhor, me deparei com uma tabela que tinha aproximadamente 38 milhões de linhas e que ocupava cerca de 30 GB apenas considerando os dados armazenados. Com certeza o tamanho e volume desta tabela estavam associados aos problemas de desempenho do banco de dados, motivo pelo qual fui contratado para dar a consultoria.&lt;/p&gt;

&lt;p&gt;Analisando com calma, identifiquei que esta tabela continha mais de 40 colunas. Sem entrar em detalhes, pude verificar que das 40 colunas, 22 eram do tipo dados inteiro (INT). Até aqui sem problemas. Porém, ao verificar o intervalo mínimo e máximo para cada coluna (com o uso de instrução SELECT MAX(), MIN() FROM TABELA), determinei que, das 22 colunas, 19 armazenavam apenas valores numéricos compreendidos entre  0 e 50.000. Outro detalhe interessante é que não havia sequer um valor negativo para estas 19 colunas no meio das 38 milhões de linhas. Este é um cenário típico onde o tipo de dados INT é utilizado como chave primária junto com uma propriedade de auto-numeração.&lt;/p&gt;

&lt;p&gt;Se lembrarmos que o SQL Server possui o  tipo de dados INT que ocupa 4 bytes, o  tipo de dados SMALLINT ocupa 2 bytes e o tipo de dados TINYINT que ocupa 1 byte podemos ver claramente que o tipos de dados das 19 colunas foram super dimensionados.&lt;/p&gt;

&lt;p&gt;Conversando com analistas, desenvolvedores e usuários ele confirmaram que estas colunas não armazenam valores grandes. Por exemplo: colunas com o número de agência bancária, o número da praça, o código do usuário que digitou o documento, a filial da empresa, etc. Com a confirmação de que todas estas colunas poderiam ter utilizado um tipo de dados que ocupa menos espaço, isto é, o SMALLINT ou o TINYINT no lugar do INT, parti para calcular o quando se ganharia de espaço na mudança de tipos. &lt;/p&gt;

&lt;p&gt;Aqui vou considerar um cálculo simples de custo de linha. Para informações e mais detalhes sobre o custo por linha, recomendo a leitura dos seguintes artigos publicados anteriormente aqui no iMasters: &lt;a href=&quot;http://imasters.uol.com.br/artigo/2527/sql_server/verificando_a_alocacao_de_dados_-_parte_01/&quot;&gt;Verificando a alocação de dados - Parte 1&lt;/a&gt; e &lt;a href=&quot;http://imasters.uol.com.br/artigo/2554/sql_server/verificando_a_alocacao_de_dados_-_parte_02/&quot;&gt;Verificando a alocação de dados&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vamos aos cálculos: &lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Das 19 colunas com o tipo de dados INT (4 bytes), verifiquei que 8 delas poderiam ser trocadas pelo tipo TINYINT (1 BYTE) e as 11 poderiam ser trocadas pelo tipo SMALLINT (4 bytes). Notem que o intervalo de valores do TINYINT é de 0 a 255, o intervalo de valores do SMALLINT é de -32.768 a 32.767 e o intervalo de valores do INT é de -2.147.483.648 a 2.147.483.647.&lt;/li&gt;

&lt;li&gt;Temos 19 colunas do tipo INT por linha. Como o tipo INT ocupa 4 bytes, a tabela ocupava 19x4 = 76 bytes por linha apenas com estas 19 colunas.&lt;/li&gt;

&lt;li&gt;Multiplicando 76 bytes pela quantidade de linhas da tabela, 38 milhões, temos: 76*38.000.000 = 28.880.000.00 bytes ou aproximadamente 2,7 GB. &lt;/li&gt;

&lt;li&gt;Se utilizarmos o tipo de dados TINYINT em 8 colunas teremos: 8x1 = 8 bytes. Devemos somar também 11 colunas do tipo SMALLINT. Ou seja, teremos (8x1) + (11*2) = 8 + 22 = 30 bytes. Este é o custo da linha para as 19  colunas que serão modificadas.&lt;/li&gt;

&lt;li&gt;Multiplicando 30 pela quantidade de linhas teremos 30*38.000.000 = 1.140.000.000 bytes ou aproximadamente 1 GB.&lt;/li&gt;

&lt;/ol&gt;&lt;p&gt;Se fizéssemos a troca de tipos, estaríamos economizando 1,7 GB, pois 2,7  - 1,0 = 1,7 GB. Notem que esta economia é de 63% do espaço ocupado pelas colunas numéricas e de 5,6% do tamanho total da tabela e, por conseqüência, do espaço em disco. Isto apenas para o tamanho ocupado pelos dados, pois teríamos um ganho adicional de espaço se considerarmos que muitas destas 19 colunas fazem partes de índices. Para o leitor ter idéia do que isso representa, faremos uma analogia. &lt;/p&gt;

&lt;p&gt;Imagine se 5,6 % do espaço do seu monitor estivesse com um retângulo preto sem uso. Este espaço estaria reservado para você, porém ele nunca é utilizado porque o fabricante imaginou que um dia alguém descobriria um jeito de utilizar este espaço, coisa que nunca aconteceu na realidade. Se alguns designers já reclamam de um ou outro &lt;em&gt;dead pixel&lt;/em&gt; em um monitor com resolução de 1280x800 imaginem a falta que 51.000 pixels não faria....&lt;/p&gt;

&lt;p&gt;A redução de espaço proporciona outros efeitos colaterais benéficos. Além da redução dos índices, o banco de dados ocuparia menos memória para armazenar as páginas de dados e índices desta tabela. Os joins ficariam mais rápidos de serem executados devido ao tamanho reduzido das chaves primárias, o backup e a replicação seriam executados mais rápido, o processador gastaria menos ciclos de CPU para executar a instrução, etc. Contudo, mensurar estes tipos de ganhos é mais complexo do que simplesmente indicar o ganho de espaço em disco e, em muitas situações, a troca de tipos de dados pode se tornar muito complexa, especialmente com tipos que não armazenam números.&lt;/p&gt;

&lt;p&gt;Um fator decisivo para a minha escolha da mudança de tipos nesta consultoria foi   facilidade de implementação: em termos práticos não houve muitas dificuldades técnicas para trocar um tipo de dados INT para SMALLINT ou TINYINT. Em primeiro lugar, a conversão dos programas, stored procedures e outros objetos programáveis é  automática, pois um valor SMALLINT ou TINYINT pôde ser armazenado em um INT sem problemas. Além disso, foi possível utilizar o comando ALTER TABLE para trocar o tipo de dados sem problemas, com exceção das chaves primárias. Em segundo lugar, valores numéricos, em geral, são indexados e manipulados mais rápido que outros tipos de dados, o que tornou esta manutenção mais rápida do que trocar um char(30) por um varchar(30), por exemplo. Em terceiro lugar, esta manutenção apresentou resultados imediatos, que puderam ser medidos através de diversas maneiras no SQL Server. &lt;/p&gt;

&lt;p&gt;Porém isso não quer dizer que a tarefa vai ser sempre simples: há sempre a obrigação de testar o sistema após a troca dos tipos de dados e contar com um backup pronto para ser restaurado em caso de problemas. Além disso, as implicações desta troca de tipos podem afetar funcionalidades já agendadas para desenvolvimento que contavam com um tipo de dado e, na hora da implementação, se depararam com outro tipo de dados.&lt;/p&gt;

&lt;p&gt;Agora eu termino este artigo perguntando: você, leitor, já sabe o quanto do seu banco de dados está sendo &quot;desperdiçado&quot; devido ao uso incorreto do tipo de dados de dados nas suas tabelas? &lt;/p&gt;

&lt;p&gt;Um grande abraço,&lt;/p&gt;

</description>
            <author>pichiliani@gmail.com (Mauro Pichiliani)</author>
            <pubDate>Thu, 25 Jun 2009 09:00:00 +0100</pubDate>
            <guid>http://imasters.uol.com.br/artigo/13251</guid>
        </item>
    </channel>
</rss>
