tag:blogger.com,1999:blog-82087309474179752462024-03-13T17:18:30.251-03:00Oraculo do SulUm blog sobre programação, banco de dados e generalidades.Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-8208730947417975246.post-8845544876907125192016-12-06T08:59:00.003-02:002016-12-06T09:00:48.548-02:00Novo curso Performance Tuning com Oracle 12c<div style="text-align: justify;">
Nos últimos 3 meses estive trabalhando na elaboração de um curso sobre Performance Tuning em Oracle incorporando os novos recursos disponíveis na versão 12c. A idéia era criar um curso que ensinasse desde a base necessária para o entendimento da arquitetura Oracle até as técnicas mais avançadas para obter o máximo de performance e escalabilidade do ambiente.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Neste curso eu consolidei tanto informações do material oficial de <i>tuning</i> da Oracle (baseado no manual Oracle Database Performance Tuning Guide) como também informações de meus artigos anteriores e uma extensa pesquisa documental nos blogs, artigos e notas dos principais "gurus" do mundo Oracle, como Tom Kyte, Tanel Poder, Maria Colgan, Adrian Billington e outros.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A idéia é explorar a ótica do performance tuning tanto do ponto de vista de SQL, através do entendimento do otimizador baseado em custo (CBO), das coleções de estatísticas e dos principais operadores de acesso, como também explorar o mundo PL/SQL com seus padrões de codificação, estratégias de processamento em massa e principais otimizações.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Este curso já foi realizado em duas turmas e agora estou abrindo a divulgação para que empresas interessadas possam contratá-lo.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Eu disponibilizei a primeira versão deste curso no Slideshare para quem quiser ter uma idéia do material e assuntos abordados. Notem que a versão atual do curso foi revista e ampliada, contendo temas que não foram abordados nesta primeira edição.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Veja o material da primeira edição abaixo:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<iframe allowfullscreen="" frameborder="0" height="485" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/key/a1dfMzE1qj53oj" style="border-width: 1px; border: 1px solid #ccc; margin-bottom: 5px; max-width: 100%;" width="595"> </iframe> </div>
<div style="margin-bottom: 5px;">
<div style="text-align: justify;">
<strong> <a href="https://www.slideshare.net/DanielaPetruzalek/performance-tuning-com-oracle-database-12c" target="_blank" title="Performance Tuning com Oracle Database 12c">Performance Tuning com Oracle Database 12c</a> </strong> de <strong><a href="https://www.slideshare.net/DanielaPetruzalek" target="_blank">Daniela Petruzalek</a></strong> </div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Mais informações e dados de contato podem ser encontradas no site <a href="http://zlk.net.br/">zlk.net.br</a>.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-86374800532914619362016-07-22T21:22:00.001-03:002016-07-23T23:43:52.365-03:00Notas Sobre a Instalação do EBS 12.2.5 no ODA X5-2 (bare metal)<h4>
Introdução</h4>
<div>
<br /></div>
O objetivo deste artigo é documentar os desafios e soluções para problemas encontrados durante a instalação do <b>Oracle e-Business Suite (EBS) 12.2.5</b> no <b>Oracle Database Appliance (ODA)</b>.<br />
<br />
Este artigo é um <i><u>Work in Progress (WIP)</u></i> e pode ser atualizado a qualquer momento a medida que novos passos vão sendo descobertos e documentados.<br />
<br />
<h4>
<b>Infraestrutura</b></h4>
<div>
<b><br /></b></div>
A infraestrutura de instação do ambiente escopo deste artigo é composta pelos seguintes componentes:<br />
<ol>
<li>App Tier: Uma máquina x86-64 com Oracle Linux 6.5 </li>
<li>Database Tier: ODA X5-2 (<i>bare metal</i>) com Oracle Linux 5.11. Instalação <i>single node</i>. </li>
</ol>
<h4>
<b>Software Necessário </b></h4>
<div>
<b><br /></b></div>
Para a execução dos passos da instalação é necessário ter um cliente SSH instalado e um servidor de janelas X11. Eu estou utilizando o putty com o Xming Server.<br />
<br />
Alternativamente, é possível utilizar o vncserver no servidor e um cliente VNC como o TightVNC no cliente.<br />
<br />
<h4>
Leitura Recomendada </h4>
<div>
<br /></div>
<ul>
<li>Oracle E-Business Suite Installation Guide: Using Rapid Install (Part No. E22950) </li>
<li>Oracle E-Business Suite Release Notes, Release 12.2 (Doc ID 1320300.1)</li>
<li>Implementing Oracle E-Business Suite 12.1 Databases on Oracle Database Appliance (Doc ID 1566935.1)</li>
<li>Oracle E-Business Suite Installation and Upgrade Notes Release 12 (12.2) for Linux x86-64 (Doc ID 1330701.1)</li>
<li>MD5 Checksums for R12.2 Rapid Install Media (Doc ID 1505510.1)</li>
<li>Oracle E-Business Suite Release 12.2: Suite-Wide Rollup and AD/TXK Delta Information (Doc ID 1583092.1)</li>
<li>Applying the Latest AD and TXK Release Update Packs to Oracle E-Business Suite Release 12.2 (Doc ID 1617461.1)</li>
<li>Oracle E-Business Suite 12.2 Patching Technology Components Guide (Doc ID 1355068.1)</li>
</ul>
<div>
<br /></div>
<h4>
Visão Geral das Macro Tarefas</h4>
<div>
<ol>
<li>Download dos Binários</li>
<li>Validação de Dependências do Sistema Operacional</li>
<li>Instalação dos Pacotes de Dependências</li>
<li>Configuração do Sistema Operacional</li>
<li>App Node: Criação de Usuários</li>
<li>ODA: Expansão de volumes</li>
<li>Cópia de Binários para Máquina Local</li>
<li>Criação da Área de Stage</li>
<li>Checksum da Área de Stage</li>
<li>Ajustes ASM (permissões e oratab)</li>
<li>Correção do script adrundb.sh (compatible)</li>
<li>Execução do rapidwiz no ODA</li>
<li>Cópia do arquivo de configuração para o App Node</li>
<li>Execução do rapidwiz no App Node</li>
<li>Aplicar o Consolidated Seed Table Upgrade Patch</li>
<li>Criar snapshot</li>
<li>Aplicar AD e TXK RUP</li>
<li>Aplicar Oracle e-Business 12.2 Suite RUP5</li>
</ol>
</div>
<div>
<h4>
Tarefa 1: Download do Binários</h4>
<div>
<br /></div>
Esta tarefa é simples de executar, porém dependendo da qualidade da conexão que você tem disponível ela pode ser bastante demorada, pois estamos falando de um download da ordem de 50 GB.<br />
<br />
Para iniciar o download vá para o site http://edelivery.oracle.com e entre com o seu usuário SSO da Oracle. O download em si não tem muitos segredos, mas um detalhe é importante: faça a busca pelo produto que você está instalando, não pela suite do EBS. Por exemplo, se você quer instalar o WMS, procure por "Oracle Warehouse Management".<br />
<br />
É possível buscar diretamente por Oracle e-Business Suite, porém o pacote de download que ele vai apresentar não estará completo, por isso é importante pesquisar pelo produto. Não se preocupe em fazer o download de vários produtos pois, seguindo o exemplo acima, mesmo fazendo o download do WMS todos os demais produtos da suite EBS estarão inclusos.<br />
<br />
<b>Dica:</b> tome cuidado na hora de confirmar os pacotes, pois o download padrão seleciona <b>todos</b> os language packs. Selecione apenas os necessários (tanto para a base 12.2.0 como para o RUP 12.2.5) e economize vários GB de download.<br />
<br />
<h4>
Tarefa 2: Validação de Dependências do Sistema Operacional</h4>
<div>
<br /></div>
Verificar se as versões de SO e kernel são certificadas para o EBS de acordo com a nota 1330701.1.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">$ uname -r</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">3.8.13-16.2.1.el6uek.x86_64</span><br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<span style="font-family: "courier new" , "courier" , monospace;">$ lsb_release -d</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Description: Oracle Linux Server release 6.8</span><br />
<div>
<br /></div>
<h4>
Tarefa 3: Instalação dos Pacotes</h4>
<br />
O servidor de aplicação pode se aproveitar do pacote <b>oracle-ebs-server-r12-preinstall</b>, mas o este pacote não pode ser utilizado no ODA. Resta então fazer a checagem de todos os pacotes listados na nota 1330701.1.<br />
<br />
De regra geral, se o pacote estiver instalado e tiver versão superior ao solicitado, mantém-se o pacote instalado. Caso o pacote tenha versão abaixo ou não esteja instalado, instalar o pacote da nota. Note que alguns pacotes são "pareados" em 32 bit e x86-64. Eu optei por manter os dois sempre na mesma versão.<br />
<br />
<h4>
Tarefa 4: Configuração do Sistema Operacional</h4>
<br />
Verificar os parâmetros de kernel e rede, entre outros, de acordo com a nota 1330701.1. No caso do ODA este passo <u>precisa ser feito manualmente</u>, conforme o processo descrito na nota.<br />
<br />
No caso do servidor de aplicação, que é simplesmente uma máquina Linux, este passo <u>pode ser simplificado com o próximo</u> através da instalação do pacote <b>oracle-ebs-server-r12-preinstall</b> a partir da do repositório public-yum da Oracle.<br />
<h4>
<br />Tarefa 5: App: Criação dos Usuários</h4>
<br />
Por padrão o EBS possui 2 usuários: <i>ora<sid></sid></i> é o <i>owner </i>da <i>database tier</i> e <i>appl<sid></sid></i> é o <i>owner </i>da <i>application tier</i>.<br />
<br />
Para simplificar a instalação, eu optei por manter um único <i>owner </i>no ODA, o usuário padrão <i>oracle</i>. Isto tem a consequencia que o grupo de instalação deverá ser <i>oinstall</i>, e não <i>dba </i>como consta no manual, ou a instalação irá falhar logo nos primeiros passos.<br />
<br />
Na camada de aplicação, devemos criar o usuário appl correspondente. Exemplo:<br />
<br />
<span style="background-color: white; font-family: "monaco" , "consolas" , "bitstream vera sans mono" , "courier new" , "courier" , monospace; font-size: 16px; line-height: 17.6px; white-space: pre;"># useradd applvis -g oinstall</span><br />
<span style="background-color: white; font-family: "monaco" , "consolas" , "bitstream vera sans mono" , "courier new" , "courier" , monospace; line-height: 17.6px; white-space: pre;"># passwd applvis</span><br />
<span style="background-color: white; line-height: 17.6px; white-space: pre;"><span style="font-family: "monaco" , "consolas" , "bitstream vera sans mono" , "courier new" , "courier" , monospace;">Changing password for user applvis.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.</span></span><br />
<span style="background-color: white; line-height: 17.6px; white-space: pre;"><span style="font-family: "monaco" , "consolas" , "bitstream vera sans mono" , "courier new" , "courier" , monospace;"># usermod -a -G dba applvis</span></span><br />
<span style="background-color: white; line-height: 17.6px; white-space: pre;"><span style="font-family: "monaco" , "consolas" , "bitstream vera sans mono" , "courier new" , "courier" , monospace;"><br /></span></span>
<br />
<h4>
Tarefa 6: ODA: Expansão dos Volumes</h4>
<br />
A nota 1566935.1 documenta o processo de instalação do EBS 12.1 no ODA bare metal. Embora o processo tenha mudado bastante na versão 12.2, a seção 1 que trata da expansão dos volumes ainda é relevante.<br />
<br />
Os comandos abaixo foram retirados desta nota:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">lvextend -L +25G /dev/mapper/VolGroupSys-LogVolOpt<br />resize2fs /dev/mapper/VolGroupSys-LogVolOpt<br /><br />lvextend -L +25G /dev/mapper/VolGroupSys-LogVolU01<br />resize2fs /dev/mapper/VolGroupSys-LogVolU01</span></div>
<br />
Como sugestão, o filesystem em opt pode ser utilizado para armazenar os arquivos zip e o filesystem em u01 pode conter a área de stage e os binários instalados. Caso você esteja com pouco espaço em u01, a área de stage pode residir em opt sem maiores problemas.<br />
<h4>
<br />Links Úteis</h4>
<br />
http://onlineappsdba.com/index.php/2007/06/10/start-up-shutdown-scripts-in-oracle-apps-r12/<br />
https://www.pythian.com/blog/step-by-step-installation-of-an-ebs-12-2-vision-instance/
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-45281113128825130332015-02-06T10:11:00.004-02:002016-07-25T08:56:54.800-03:00Fundador da SAP falando sobre o HANA: "Se isto não funcionar estamos mortos"Será inteligente para um negócio multibilionário colocar todos os ovos na mesma cesta? Uma cesta que historicamente não tem dado bons resultados?<br />
<br />
Destaques:<br />
<br />
<ul>
<li>A SAP está tendo dificuldades para entrar no mercado de cloud, basicamente adquirindo novas empresas porque desenvolver dentro de casa não tem dado muito certo</li>
<li>HANA foi a forma como eles encontraram de tirar revenue da Oracle, que no mercado de cloud tem "dado trabalho"</li>
<li>Em 4 anos no mercado, o HANA tem 2000 clientes</li>
<li>Acabou de ser lançada a nova geração do HANA - SAP S/4HANA</li>
</ul>
<br />
<br />
<a href="http://www.businessinsider.com/sap-founder-hasso-plattner-if-this-doesnt-work-were-dead-2015-2">http://www.businessinsider.com/sap-founder-hasso-plattner-if-this-doesnt-work-were-dead-2015-2</a>Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-40735793231046961162015-02-05T18:18:00.003-02:002016-07-23T23:49:30.114-03:00SAP on Oracle Development Update - 5 de fevereiro de 2015<span class="commentary" id="control_gen_43" style="background-color: white; border: 0px; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px; margin: 0px; padding: 0px; vertical-align: baseline;">Roadmap da SAP em base Oracle, atualizado hoje (5 de fevereiro de 2015). </span><span style="background-color: white; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px;">Destaques: </span><br />
<br />
<ul>
<li><span style="background-color: white; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px;">Suporte restrito ao 10g expira em Julho. </span></li>
<li><span class="commentary" style="background-color: white; border: 0px; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px; margin: 0px; padding: 0px; vertical-align: baseline;">Rollout do Oracle 12.1.0.2</span><span class="commentary" style="background-color: white; border: 0px; color: #333333; font-size: 13px; line-height: 17px; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="font-family: "arial" , "helvetica" , sans-serif;"> </span></span><span class="commentary" id="control_gen_44" style="background-color: white; border: 0px; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px; margin: 0px; padding: 0px; vertical-align: baseline;">em 31 de Março. </span></li>
<li><span style="background-color: white; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px;">Suporte ao Exadata X5 </span></li>
<li><span style="background-color: white; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px;">Suporte ao Exalogic virtualizado (antes era só bare metal) </span></li>
<li><span style="background-color: white; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px;">Aliás, suporte ao OVM em qualquer x86-64 </span><b style="color: #333333; font-family: Arial, sans-serif; font-size: 13px; line-height: 17px;">exceto</b><span style="background-color: white; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px;"> o ODA (não entendi porque...) </span></li>
</ul>
<br />
<span style="background-color: white; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px;">E o mais importante: eles FINALMENTE "descobriram" que o processamento de dados deve ser feito no BANCO DE DADOS e não na camada de aplicação. Eles estão gradualmente modificando o ABAP para este "novo" paradigma (slide 42).</span><br />
<span class="commentary" style="background-color: white; border: 0px; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px; margin: 0px; padding: 0px; vertical-align: baseline;"><br /></span>
<span class="commentary" style="background-color: white; border: 0px; color: #333333; font-family: "arial" , sans-serif; font-size: 13px; line-height: 17px; margin: 0px; padding: 0px; vertical-align: baseline;"><b>Fonte:</b></span><br />
<span class="commentary" style="background-color: white; border: 0px; font-size: 13px; line-height: 17px; margin: 0px; padding: 0px; vertical-align: baseline;"><span style="color: #333333; font-family: "arial" , sans-serif;"><a href="https://scn.sap.com/docs/DOC-15887">https://scn.sap.com/docs/DOC-15887</a></span></span>Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-56477328894107604852015-01-02T10:00:00.000-02:002016-07-23T23:52:13.807-03:00Tudo (ou quase tudo) que você queria saber sobre licenciamento Oracle e não tinha para quem perguntar<div class="left" style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A escolha da melhor tecnologia para atender as suas necessidades em meio a um mercado tão veloz e competitivo é um grande desafio. Se tratando de software então, não basta escolher o melhor produto, mas também escolher a melhor forma de comprá-lo a fim de maximizar o investimento.</div>
<div class="left" style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
No meu dia-a-dia eu vejo muita dificuldade de gestores de TI em entender os conceitos de licenciamento dos mais diversos fornecedores. Como não existe um padrão de mercado é importante estar atento aos nuances de cada fornecedor para não cair em irregularidades.</div>
<div class="left" style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A fim de facilitar a vida de clientes e parceiros, vou consolidar neste artigo algumas informações bem relevantes na hora de tomar a decisão para o melhor investimento.</div>
<h3 class="left" style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
<span style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">O guia prático de licenciamento da Oracle</span></h3>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Sabendo que os clientes têm dificuldades em entender as regras de licenciamento, a Oracle elaborou um manual de licenciamento, chamado <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Software Investment Guide (SIG),</strong> que contém as explanações básicas sobre as métricas de licenciamento para os diferentes tipos de produtos e cenários. Regras bastante polêmicas de licenciamento como failover, stand by, backup, quantidade de usuários e etc. estão explicadas de forma detalhada e com vários exemplos de aplicações destas regras em cenários semelhantes ao mundo real.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
No link abaixo, além do SIG você também vai encontrar uma planilha de controle de inventário de licenças que já vem preparada com as métricas e produtos da Oracle. Seu uso não é obrigatório, mas ajuda bastante quando não há nenhum outro tipo de controle.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Software Investment Guide: <a href="http://www.oracle.com/us/corporate/pricing/software-investment-guide/index.html" rel="nofollow" style="border: 0px; box-sizing: border-box; color: #7b539d; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;" target="_blank">http://www.oracle.com/us/corporate/pricing/software-investment-guide/index.html</a></div>
<h3 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Principais pontos sobre licenciamento Oracle</h3>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A Oracle hoje possui uma gama muito vasta de produtos e serviços, que vai muito além da visão tradicional de que a Oracle é uma empresa de banco de dados. Hoje a Oracle possui em seu portfólio produtos que vão desde a camada de aplicação, passando por middleware, banco de dados, virtualização, sistema operacional, servidores e até storage.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Por isso, quando vamos checar a forma de licenciar um produto, precisamos estar atentos que cada linha de produto possui uma forma específica de licenciamento. Como os pontos mais polêmicos são com relação ao licenciamento de banco de dados, é neste tópico que eu vou focar, mas o SIG está aí para falar também sobre os demais produtos.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
O primeiro ponto na escolha do software de banco de dados a ser licenciado é a escolha da funcionalidade desejada. Dependendo das necessidades da empresa em termos de negócio uma ou outra tecnologia pode ser mais adequada. O banco de dados Oracle é comercializado de acordo com a disponibilidade destes recursos para atender necessidades especifícias.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A versão mais básica do banco de dados Oracle é a versão Express (também conhecida como XE). O <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Oracle XE</strong> é gratuíto, porém é o que possui menos recursos e têm maiores limitações em termos de hardware. Independente da máquina onde estiver rodando, ele fica limitado a utilizar apenas um núcleo (core) de processador e 1 GB de memória RAM.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
O <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Oracle Standard Edition One (SE1)</strong> é a versão comercial entry-level do banco de dados, ele é limitado a rodar num hardware com no máximo 2 (dois) processadores físicos (sockets) e não tem opção de fazer cluster (funcionalidade onde duas ou mais máquinas trabalham em paralelo sobre o mesmo banco de dados).</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
O <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Oracle Standard Edition (SE),</strong> por sua vez, possui o limite de hardware de até 4 processadores físicos (sockets) e tem a possibilidade de fazer cluster através do Oracle RAC (Real Application Clusters). Note que ao optar por utilizar o RAC, continua valendo o limite de 4 processadores para o cluster inteiro (exemplo: duas máquinas com dois processadores).</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Finalmente, o banco <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Oracle Enterprise Edition (EE)</strong> é o produto top de linha desta categoria, contendo inúmeras características que o torna ideal para negócios extremamente críticos e dinâmicos. Somente com o Oracle Enterprise Edition você pode garantir alta disponibilidade e continuidade de negócios com zero perda de dados e downtime zero ou próximo de zero. Logo, ele é adequado para empresas que não podem parar (operam 24x7) e também não podem correr risco de perder os seus dados. Isto é, claro, entre outras características como melhor performance, segurança e escalabilidade.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Em termos de licenciamento, o Oracle Enterprise Edition possui uma métrica diferenciada. O processador do EE é calculado de acordo com o número de núcleos (cores) que a máquina possui, aplicado um fator de conversão que é tabelado. Fica mais fácil de entender na prática:</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Vamos pegar como exemplo um servidor padrão de mercado hoje, com dois processadores x86 octa-core (8 cores cada, 16 cores no total). O fator de conversão para x86 é 0,5. Logo, o número de processadores a serem licenciados de banco EE é 16 (total de cores) x 0,5 (fator x86) = 8 processadores. (Note que a mesma máquina em SE1 ou SE necessitaria de 2 (duas) licenças de processador)</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Para conhecer todos os fatores de conversão, basta consultar a tabela <a href="http://www.oracle.com/us/corporate/contracts/processor-core-factor-table-070634.pdf" rel="nofollow" style="border: 0px; box-sizing: border-box; color: #7b539d; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;" target="_blank">Oracle Processor Core Factor Table</a>. Hoje, os mais relevantes são: 0,5 para x86 e SPARC e 1,0 para processadores RISC não-Oracle.</div>
<h3 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Licenciamento por Usuários Nomeados (Named User Plus)</h3>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Além do licenciamento por processador, algumas linhas de produtos podem ser licenciadas por usuários nomeados, os chamados Named User Plus. Para a linha de produtos de banco de dados, isto também é possível, desde que se considere as seguintes regras:</div>
<ol style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 30px 40px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;">Usuários humanos e não-humanos precisam ser contáveis (ex.: 30 sensores + 400 operadores)</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;">Existem quantidades mínimas de usuários que precisam ser respeitadas, que variam por produto. Para os produtos banco de dados SE1 e SE, o mínimo de usuários nomeados é 5 por processador. Para o banco de dados EE, o mínimo é 25 usuários por processador.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;">Para calcular os mínimos, primeiro calcula-se o número de licenças de processador necessárias para o hardware específico e depois aplicam-se os multiplicadores de cada produto.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;">Se o número de usuários contados for maior que o mínimo, licencia-se por usuários contados. Se não, licencia-se pelo mínimo calculado.</li>
</ol>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Considerando a máquina de referência do exemplo acima, 2 processadores físicos com 8 cores cada um, os mínimos respectivos são:</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
SE e SE1: 2 processadores x 5 usuários = 10 usuários nomeados</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
EE: 2 processadores x 8 cores x 0,5 (fator x86) x 25 usuários = 200 usuários nomeados</div>
<h3 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Tópicos Especiais de Licenciamento</h3>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Os cenários de licenciamento descritos acima vão cobrir a maioria dos casos que encontramos no dia-a-dia. No entanto, a medida que precisamos fazer usos mais avançados do software a complexidade da solução aumenta e as regras precisam ser extendidas para contemplar esta nova complexidade. Dois tópicos muito quentes são o licenciamento de disaster recovery e o licenciamento de ambientes virtualizados.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Com relação ao disaster recovery (DR), entendemos por isso um ambiente onde exista o banco de dados Oracle instalado pronto para assumir a carga do ambiente de produção caso ocorra um evento que indisponibilize o mesmo. Ou seja, é um conjunto de hardware e software adicional que através de alguma forma de replicação mantém uma cópia do banco de dados para eventos de desastres ou outros tipos de paradas, sejam estas planejadas ou não planejadas. Todo servidor onde houver o software da Oracle instalado precisa ser licenciado logo, sim, é preciso licenciar o site DR.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Uma pergunta muito comum é: posso licenciar o site de produção por processador e o DR por usuário? A resposta é <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="underline" style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: underline; vertical-align: baseline;">não</span></strong>. Independente do tipo de replicação utilizado, se a finalidade é DR, os servidores precisam obrigatoriamente seguir a mesma métrica. Agora se estivessemos falando de ambientes distintos, como por exemplo, produção e homologação ou QA, aí sim, neste caso pode ser licenciado produção por processador e homologação por usuários. Para esclarecer de uma vez por todas as regras de licenciamento de sites de disaster recovery, backup, etc, incluindo esta e outras regras, o documento oficial é o <a href="http://www.oracle.com/us/corporate/pricing/data-recovery-licensing-070587.pdf" rel="nofollow" style="border: 0px; box-sizing: border-box; color: #7b539d; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;" target="_blank">Licensing Data Recovery Environments</a>.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Sobre o tema de virtualização, gostaria de destacar que é preciso tomar muito cuidado com este tópico, em especial para não ficar irregular. Todo processador que roda o código Oracle precisa ser licenciado. Isso fica bem fácil de entender vendo um servidor bare metal, onde todo o processamento fica disponível para o banco de dados e com isso toda a máquina precisa ser licenciada. Agora, em ambientes virtualizados, nem sempre temos o controle sobre quais processadores vão executar quais tarefas, podendo elas estar distribuidas em múltiplos servidores em momentos distintos - a exemplo da tecnologia de live migration. Nestes casos, farms de VMs, onde o banco pode estar executando hora em uma máquina, hora em outra, é necessário licenciar TODA a farm de VMs. Sim, toda. Mesmo que você esteja usando só 2 processadores de cada vez.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Existem exceções a esta regra? Sim. Quando a tecnologia de virtualização tem a capacidade de fazer o chamado hard partitioning ou "CPU pin", ou seja, fixar a execução da VM em um determinado core ou grupo de cores, como se efetivamente estivéssemos "fatiando" uma máquina. Note que não são todas as tecnologias de virtualização que suportam isso, e mesmo que as que suportam, precisam ser homologadas pela Oracle para que o licenciamento seja válido. Esta regra pode ser vista na íntegra no documento <a href="http://www.oracle.com/us/corporate/pricing/partitioning-070609.pdf" rel="nofollow" style="border: 0px; box-sizing: border-box; color: #7b539d; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;" target="_blank">Partitioning</a> (não confundir com a option de banco Partitioning, este partitioning se refere a divisão de uma máquina física em máquinas virtuais menores).</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A documentação completa sobre os tópicos especiais (além dos dois previamente citados) pode ser encontrada no site da Oracle, na seção <a href="http://www.oracle.com/us/corporate/pricing/specialty-topics/index.html" rel="nofollow" style="border: 0px; box-sizing: border-box; color: #7b539d; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;" target="_blank">Specialty Topics</a>.</div>
<h3 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Palavras Finais</h3>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Ok, talvez meu título tenha sido (um pouco) enganatório. Mas o objetivo era chamar a atenção para estes tópicos de licenciamento que são bastante polêmicos e muito comuns de encontrarmos no dia-a-dia. Vale lembrar também que regras de licenciamento são muito dinâmicas e podem variar ao longo dos anos, então por este motivo fiz questão de apontar sempre as referências oficiais, assim mesmo que este texto algum dia fique desatualizado, aí estão os links para a consulta do material direto na fonte.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-26064705650714787082014-12-30T10:05:00.000-02:002016-07-23T23:56:58.036-03:00Princípios Básicos de Segurança da Informação<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Eu lembro que na minha infância costumava se falar muito aquele ditado popular "tempo é dinheiro". Talvez porque naquela época as coisas eram bem mais difíceis... os meios de transportes não eram tão evoluídos (viajar de avião, por exemplo, era uma fortuna), os meios de comunicação idem (telefones fixos custavam o preço de um carro novo e celulares eram aparatos de filmes de ficção científica), então se gastava muito tempo para realizar algumas tarefas que hoje são triviais. A tecnologia encurtou as distâncias e tornou viáveis uma infinidade de novas possibilidades. Hoje mandamos uma mensagem de um lado para o outro do mundo em segundos, quando antes levava meses.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Não obstante, hoje, tempo ainda é dinheiro. Mas talvez mais importante que isso, na era digital, <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">informação é dinheiro</strong>. Vivemos num mundo de empresas cada vez mais dependentes de tecnologia, e sobretudo, de seus dados. Devido a toda essa evolução tecnológica encurtando as distâncias, a informação consegue fluir muito rápido e, quando se trata de uma informação crítica para o negócio, é preciso fazer de tudo para que ela não encontre um caminho rápido até as mãos da concorrência.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Na prática, no entanto, vejo muitas empresas não tomarem as devidas precauções com a segurança. O problema, na maioria dos casos, é que uma falha de segurança tem geralmente proporções intangíveis, ou seja, não é possível delimitar um impacto financeiro e nem mesmo dar a certeza de que um dia vai acontecer. Quando se trata de segurança, sempre estamos falando no conceito de risco. Fazer um investimento para mitigar um risco (em contrapartida a uma certeza), não costuma ser muito simples de justificar, exceto quando as companhias já vivenciaram um problema antes.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Outro motivo que tende a minimizar os investimentos em segurança é a própria falta de conhecimento dos profissionais sobre as ferramentas disponíveis no mercado e sobre as regulamentações e normas existentes no setor. O restante deste artigo vou me dedicar a estes dois aspectos.</div>
<h4 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Regulamentação</h4>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
As normas que regem o domínio da segurança da informação estão consolidadas na série <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ISO 27000</strong>. Em linhas gerais, a série 27000 especifica a uma estrutura para gerenciamento de segurança da informação para qualquer organização, seja esta pública ou privada, de pequeno ou grande porte.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A ISO/IEC 27000 propriamente dita constitui uma visão geral da família 27000, além de definir um glossário dentro do escopo da Tecnologia da Informação e da gestão da segurança da informação, para melhor entendimento das demais normas que constituem o conjunto.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ISO/IEC 27002:2007</strong> é a norma de Segurança da Informação, que por motivos históricos muitas vezes é referenciada por <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">ISO/IEC</strong> <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">17799:2005</strong>, a sua numeração anterior. Ela foi publicada originalmente em 2000, sendo então uma cópia fiel do padrão britânico (<strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">BS 7799-1:1999</strong>), e passou por uma revisão em 2005 para se adaptar ao mercado internacional.</div>
<h4 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Objetivos de Segurança</h4>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A segurança da informação estabelece alguns princípios básicos que precisam ser “forçados” para garantir a proteção dos dados. Estes princípios, também conhecidos como atributos, objetivos ou propriedades (entre outros), regem o foco das políticas de segurança e as funcionalidades que as ferramentas de tecnologia dispõe para controla-los.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
O coração da segurança da informação costuma ser definido pela <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">tríade clássica</strong>: confidencialidade, integridade e disponibilidade. A medida que o estudo desta área foi evoluindo, diversos autores e comitês propuseram princípios adicionais. A ISO/IEC 27002:2007 define, além da tríade clássica, os princípios da autenticidade e da irretratabilidade (ou não repúdio). Resumidamente, os 5 princípios regem sobre os seguintes aspectos:</div>
<ul style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 30px 40px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;"><strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Confidencialidade:</strong> o acesso a informação deve ser permitido apenas as entidades autorizadas.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;"><strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Integridade:</strong> a informação deve ser preservada da forma como o seu proprietário a definiu e/ou modificou, durante todo o seu ciclo de vida, sendo protegida contra modificações não autorizadas ou não detectadas.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;"><strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Disponibilidade:</strong> a informação deve estar acessível aos usuários autorizados ao seu acesso sempre que necessário.</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;"><strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Autenticidade:</strong> garantia de que a informação é genuína e que os sujeitos autorizados que a modificaram, ao longo do seu ciclo de vida, são realmente quem dizem ser (e não um terceiro impersonando um sujeito autorizado).</li>
<li style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px 0px 5px; padding: 0px; vertical-align: baseline;"><strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Irretratabilidade (não-repúdio):</strong> é a impossibilidade de negar a autoria de uma transação realizada anteriormente sobre um determinado conjunto de dados</li>
</ul>
<h4 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Políticas de Segurança</h4>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Para cumprir com os objetivos de segurança é necessário ter uma política de segurança bem definida. Conforme a <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">RFC 2196 – Site Security Handbook</strong> – uma política de segurança é uma declaração formal das regras as quais as pessoas que possuem acesso a informações e tecnologia de uma organização devem respeitar. O principal propósito de uma política de segurança é informar aos usuários, equipe e gerentes de suas obrigações para proteger os bens da companhia, sejam estes bens informações ou tecnologia.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
A política deve especificar os mecanismos pelos quais estes requisitos são cumpridos. Para que a política seja eficiente, todos os procedimentos precisam ser documentados e estarem prontamente disponíveis a todos os atores, cada qual com o seu papel muito bem definido. Além disso, ferramentas precisam ser implementadas para garantir as regras e sansões precisam ser definidas onde as ferramentas não conseguem proteger o bem automaticamente.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Note que, neste processo, grande ênfase é dada ao papel das pessoas. Em contrapartida, as ferramentas têm um papel importante, porém não tem valor se não forem operadas e implementadas corretamente. Nada vale um sistema de segurança em uma empresa onde, por exemplo, para não esquecer a senha o funcionário deixa um post-it com suas senhas coladas no monitor. Sim, isso acontece.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Mas de qualquer forma, as ferramentas de tecnologia desempenham um papel fundamental no controle da informação e na garantia de que as propriedades básicas sejam asseguradas. Sem a tecnologia apropriada, hoje, é impossível manter o controle do volume de informações que transitam entre os mais diversos sistemas que compõem a infraestrutura das empresas.</div>
<h4 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Tipos de Controles na Tecnologia de Informação</h4>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Nos voltando agora para a tecnologia da informação, podemos classificar os mecanismos que temos para atuar sobre a segurança da informação em dois níveis básicos de controle: o <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">controle preventivo</strong>, ou seja, os mecanismos que temos para prevenir que uma ação mal intencionada seja efetuada e, o <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">controle reativo</strong>, aquele que nos permite agir mediante uma falha de segurança.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Quando entramos a fundo nas regulamentações de mercado no que tange a tecnologia, é comum encontrarmos a divisão do controle da TI em dois domínios: o <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">domínio das aplicações</strong> e o <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">domínio geral</strong>, que seria correspondente ao domínio da infraestrutura.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
O domínio das aplicações é regido pelo acesso dos usuários aos aplicativos corporativos. Geralmente as próprias aplicações possuem algum tipo de controle para que apenas usuários autorizados tenham acesso às informações, porém algumas ferramentas específicas de TI tendem a melhorar este controle fornecendo algumas facilidades, como por exemplo, o Single Sign-On (SSO) ou outras modalidades de gerenciamento de acesso e controle de chaves.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Logo, no domínio das aplicações consideramos um risco o acesso de pessoas não autorizadas pela própria camada de aplicação, seja pela incorporação de uma identidade (ex.: roubo de senha, personificação ou fraude) ou por uma falha no controle de acesso (ex.: um funcionário demitido com credenciais ainda válidas).</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
No domínio geral, ou infraestrutura, os pontos de risco são mais amplos. Pensando em segurança da informação, o objeto mais crítico é o banco de dados, onde todas as informações das aplicações estão armazenadas. Como pontos chave para falhas de segurança temos desde a comunicação entre os servidores de banco de dados e de aplicação (camada de rede), o acesso direto aos dados (via sistema operacional), o acesso irrestrito de usuários privilegiados e, finalmente, a exposição indevida de dados críticos a desenvolvedores de sistema.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Permitam-me elaborar um pouco sobre cada um deles, e as maneiras de proteger-se contra cada um destes riscos:</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
<strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">1) Comunicação entre aplicação e banco de dados:</strong> toda e qualquer comunicação entre computadores está sujeita ao que chamamos de “sniffing” ou “packet capture”, entre outros termos, que nada mais é a interceptação das informações transmitidas de ponto a ponto por um software terceiro. Uma forma de se proteger deste tipo de ataque é através da criptografia, pois assim mascaramos os dados transmitidos de uma ponta a outra e sem a chave o terceiro não consegue decodificar a mensagem.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
<strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">2) Acesso direto aos dados:</strong> semelhante ao item anterior, se os dados são armazenados “planos” (sem criptografia), não importa quantas camadas de segurança e autenticação você coloque, uma pessoa com acesso a uma cópia do banco de dados pode acessar todas as informações contidas nele com um grau moderado a leve de dificuldade. Imagine o cenário onde, por exemplo, que o “motoboy” que vai levar as fitas de backup para o cofre perde uma destas fitas ou é roubado. Ou um sysadmin mal-intencionado faz uma cópia dos datafiles do banco. A criptografia também é a solução para estes problemas.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
<strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">3)</strong> <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Acesso irrestrito de usuários privilegiados:</strong> administradores de banco de dados (DBAs) geralmente são profissionais com o mais alto nível de acesso em uma infraestrutura de banco de dados. Isto se deve a própria característica do trabalho, pois, eles devem ter o poder tanto de criar como, literalmente, destruir o banco. Mas deveriam eles ter acesso às informações contidas no banco? Não necessariamente. Por exemplo, um DBA não deveria ter acesso a uma tabela de salários em um sistema de RH. Na prática, muitos têm. A forma de controlar isso depende muito de banco para banco.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
<strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">4)</strong> <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Exposição de dados críticos a desenvolvedores de sistemas:</strong> também de nada adianta tomar todas as precauções com a segurança - criptografia, controle de acesso e limitação de usuários privilegiados - se deixamos os dados de produção completamente expostos no ambiente de desenvolvimento. É muito comum criarmos massas de dado para desenvolvimento e testes a partir dos dados de produção, mas nestes ambientes secundários os mecanismos de segurança são mais relaxados ou inexistentes. Em decorrência disso, qualquer desenvolvedor com acesso direto ao banco pode ter acesso a dados que jamais deveria ter conhecimento. Aí mais uma vez para ilustrar uso o exemplo do sistema de RH, onde o salário de todos os funcionários está exposto. Mas não só isso, poderiam ser informações estratégicas de negócio da própria empresa ou de uma empresa cliente. Um risco este que pode ser mitigado através da estratégia de mascaramento de dados, descaracterizando os dados sensíveis de maneira irreversível, mas mantendo suas características relacionais para que testes permaneçam válidos.</div>
<h4 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
A tecnologia Oracle voltada para a segurança</h4>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Como especialista em Oracle eu não poderia deixar de indicar as tecnologias que a Oracle tem para endereçar cada uma destas necessidades.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Para trabalhar com controle no domínio das aplicações, a Oracle dispõe da suíte de<strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Identity Management (IDM)</strong>. Esta é uma suíte completa que inclui produtos para controle de acesso, gestão de identidade, single sign-on, governança, serviços de diretório, mobile e etc.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Já para trabalhar no domínio geral, a Oracle conta com algumas opções de banco para atuar tanto no controle preventivo como reativo. De modo geral estes produtos são comercializados como <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">options</em> do banco <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Oracle Database Enterprise Edition (DBEE)</strong> ou como <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">packs</em> para o <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Enterprise Manager</strong>. Alguns destes produtos, no entanto, podem ser utilizados em conjunto com outros bancos de dados que não são Oracle.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Para trabalhar com criptografia de banco de dados (data files e backup), a ferramenta é chamada de <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Transparent Data Encryption (TDE)</strong>, sendo comercializada como <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">option</em> do Oracle Database Enterprise Edition com o nome de <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Advanced Security</strong>. Para criptografia de rede, entre banco de dados e aplicação, até junho de 2013 este recurso também fazia parte da <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">option</em> Advanced Security, porém desde então agora ela faz parte da funcionalidade padrão do banco de dados Oracle Database Enterprise Edition.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
O controle de usuários privilegiados, considerando o banco de dados Oracle Enterprise Edition, pode ser feito através da <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">option</em> <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Database Vault</strong>. O objetivo desta <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">option</em> é assegurar que os usuários privilegiados (DBAs e SYSDBAs) continuem com os seus “super poderes” administrativos, porém não tenham acesso a dados sensíveis.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Finalmente, para trabalhar com o mascaramento dos dados de produção na hora de replicar o ambiente para desenvolvimento, a ferramenta da Oracle é um <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">pack</em> do Enterprise Manager 12c chamado de <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Data Masking and Subsetting</strong>. Este <em style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">pack</em> é capaz não só de descaracterizar os dados como também exportar apenas um subconjunto dos dados de produção mantendo sua integridade referencial, mas reduzindo os requisitos de espaço na base de dados de desenvolvimento. Um fato interessante é que esta ferramenta é multi-banco, ou seja, não funciona apenas em bancos de dados Oracle.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Todas as ferramentas acima trabalham no conceito de controle preventivo. Para fechar o raciocínio dos tipos de controle e suas soluções faltou comentar sobre o controle reativo. A ferramenta que dispomos para tratar este tipo de controle é chamada de <strong style="border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;">Audit Vault</strong>, um repositório de informações de auditoria isolado dos ambientes que monitora e totalmente desenvolvido com as melhores práticas de segurança para que não haja alteração dos dados auditados. O princípio é que, no advento de uma falha de segurança, hajam informações disponíveis para rastrear a origem da falha e punir com as devidas sanções os responsáveis. O Audit Vault, assim como o Data Masking, é uma ferramenta que pode ser usada também em bancos não-Oracle, incluindo SQL Server, DB2 e outros.</div>
<h4 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: Helvetica, Arial, sans-serif; font-size: 20px; font-stretch: inherit; font-weight: normal; line-height: 26px; margin: 0px 0px 30px; padding: 0px; vertical-align: baseline;">
Palavras Finais</h4>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Espero com este artigo ter conseguido mostrar um pouco do mundo da segurança da informação e as possíveis vulnerabilidades as quais as empresas estão sujeitas no dia a dia. Como minha especialidade é Oracle, tomei a liberdade também de mostrar algumas das ferramentas dentro do nosso portfólio podem ser utilizadas para atacar os pontos de risco citados no artigo. De maneira alguma o meu objetivo foi ser exaustivo na descrição destas ferramentas, mas sim dar uma visão geral do que está disponível no mercado.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
Caso haja mais interesse em conhecer o portfólio de segurança da Oracle, fiquem a vontade para entrar em contato. Estarei a disposição para esclarecer quaisquer dúvidas que por ventura possam aparecer.</div>
<div style="background-color: white; border: 0px; box-sizing: border-box; color: #4d4f51; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-stretch: inherit; line-height: 24px; margin-bottom: 30px; padding: 0px; vertical-align: baseline;">
E para finalizar, vale lembrar aquilo que eu comentei anteriormente sobre política de segurança e ferramentas. De nada adianta investir em ferramentas top de linha se não houver uma mudança de cultura corporativa, afinal segurança é um conceito extremamente dependente das pessoas. Para que uma política de segurança funcione corretamente, não basta ter as ferramentas corretas, mas também é preciso treinar as pessoas e deixar muito claro através de políticas, papéis e sanções o que cabe a cada um fazer.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-21932951291737292752014-11-27T08:49:00.003-02:002016-07-24T00:00:22.777-03:00Tutorial: Enterprise Manager 12c Cloud Control com o Oracle VM VirtualBox<img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPIWzWWWNHUPctH2qAmVzOejg79YnCy1qMBK57G44LjLBzT0WeKXVeg6YfJvm8dPQ1W6eXg5bobo5g1FiUViXTtkbBiIXBxVFVXSXUz3MW-E3wid18oWR4gZeU4Wa2RaD3SZv1NuLFrrE7/s1600/image069.png" style="display: none;" />
<br />
<div style="text-align: justify;">
O objetivo deste tutorial é criar um ambiente de demo ou testes do <b>Enterprise Manager 12c Cloud Control</b>. Ele surgiu como uma necessidade direta do meu trabalho como pré-vendas em demonstrar soluções para os clientes, porém este mesmo material pode ser muito útil para o público geral, em especial aquelas pessoas que gostariam de ter um ambiente <i>sandbox </i>para aprender mais sobre a ferramenta<b> Enterprise Manager 12c</b> e não têm uma máquina física disponível. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Além disso, é sabido que a instalação manual do EM12c é um pouco trabalhosa, e muitas vezes o que queremos é apenas usar o ambiente, e não aprender a instalá-lo. Logo, para conseguir um ambiente funcional o mais rápido possível, optei por utilizar extensivamente os templates de VMs disponíveis no site da Oracle.</div>
<div>
<h2 style="text-align: justify;">
</h2>
<h3 style="text-align: justify;">
Pré-Requisitos</h3>
<div style="text-align: justify;">
<br />
Antes de começar, é importante se assegurar que as seguintes condições sejam cumpridas:</div>
<ul>
<li style="text-align: justify;">O suporte a virtualização está habilitado no BIOS. (Extensões VT-x ou similar)</li>
<li style="text-align: justify;">A última versão do <b>Oracle VM VirtualBox </b>está instalada. Se vocês caírem no erro abaixo, atualizar a versão do VirtualBox:</li>
</ul>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEtQXS9SU8EMXUim5M2Kqrryev0bMEIzZhKutFbk45ShNN5dkQYaLTgOPNZWBQDavf8r1S-hoRpIA91i_kODBkMHxRDB2crfgKqbIIm1DZSItJbhXHzNQOQ5C4ckDjgndbgaC3c-qY6BH8/s1600/image001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEtQXS9SU8EMXUim5M2Kqrryev0bMEIzZhKutFbk45ShNN5dkQYaLTgOPNZWBQDavf8r1S-hoRpIA91i_kODBkMHxRDB2crfgKqbIIm1DZSItJbhXHzNQOQ5C4ckDjgndbgaC3c-qY6BH8/s1600/image001.png" /></a></div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
<span style="text-align: start;">Baixar em </span><a href="https://www.virtualbox.org/wiki/Downloads" style="text-align: start;">https://www.virtualbox.org/wiki/Downloads</a><span style="text-align: start;">. É importante também baixar o <b>Extension Pack </b>compatível.</span></div>
<div style="text-align: justify;">
<br /></div>
<span style="text-align: justify;">Para atualizar o </span><b style="text-align: justify;">Extension Pack</b><span style="text-align: justify;"> do VirtualBox, vá em </span><b style="text-align: justify;">Arquivo -> Preferências -> Extensões</b><span style="text-align: justify;"> e clique em Acrescentar pacote:</span><br />
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyyNko7HiRVKisrQT7GPZIW6HZIQLLDN3sLaiJelzsjmyzBnZK7YnLz-iDePv6pllyTMlep2shoWpJDKpN0BiimFz87QVuVTkTVu4ya8GsiUImN_PhYgFv_gotElFptzGM5ULJSCEUnZCl/s1600/image004.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="380" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyyNko7HiRVKisrQT7GPZIW6HZIQLLDN3sLaiJelzsjmyzBnZK7YnLz-iDePv6pllyTMlep2shoWpJDKpN0BiimFz87QVuVTkTVu4ya8GsiUImN_PhYgFv_gotElFptzGM5ULJSCEUnZCl/s1600/image004.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Selecione o arquivo baixado da <i>home </i>do VirtualBox e atualize o pacote:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKHZsN5wXXbl07WlZxASE-EvOcE1n7QYLmTxLvIt2nic1eWFBAHuQLGKSlJrQk-Pjd7yJg898xpeaP1wRODdl2jR2qOyADn-MI9jszNhK4f5b4rBhh40SY4LYJY_bNtIbApOS1zXCAD9vl/s1600/image006.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKHZsN5wXXbl07WlZxASE-EvOcE1n7QYLmTxLvIt2nic1eWFBAHuQLGKSlJrQk-Pjd7yJg898xpeaP1wRODdl2jR2qOyADn-MI9jszNhK4f5b4rBhh40SY4LYJY_bNtIbApOS1zXCAD9vl/s1600/image006.png" /></a></div>
<ul>
<li style="text-align: justify;">Baixar os templates das VMs no site da Oracle <b>/ </b><i>e-delivery</i>.</li>
</ul>
<div style="text-align: justify;">
<b>a. Oracle Linux: </b>baixar a <b>Oracle Linux 6 Admin VM</b>. No <a href="http://www.oracle.com/">www.oracle.com</a>, ir em <b>Downloads -> Prebuilt developer VMs</b>: </div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
<span style="text-align: center;"> </span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXeBYUjJ2gQBymJrsH58N_Qn2a82w-_jSJh3XBE07gf9mInsydDiR6RbxGAZHLJ_0CSOwOQM4fq3ncM2Sf9yTNt4M85Q3qQQ9X6yoLqbNXJSh_dbz_f9wZBXlGga4AikTG6VRIGF6b5ng-/s1600/image010.png" imageanchor="1" style="clear: right; display: inline !important; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img border="0" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXeBYUjJ2gQBymJrsH58N_Qn2a82w-_jSJh3XBE07gf9mInsydDiR6RbxGAZHLJ_0CSOwOQM4fq3ncM2Sf9yTNt4M85Q3qQQ9X6yoLqbNXJSh_dbz_f9wZBXlGga4AikTG6VRIGF6b5ng-/s1600/image010.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
Na lista de VMs, localizar a <b>Oracle Linux 6 Admin VM</b>:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmXbRE12dNs1TAFsI58CEJskaaksahqV0qqQYzJK-UG7r0Tpjr5IExxc5xvpTDJ2UBbY29_1fGf5yL6WlYhHT8jqzVCl0dsK1J_hnLEvnimEsSnZWH_d6xuwvSE_qsxjr6QBzwVg2VyH08/s1600/image012.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmXbRE12dNs1TAFsI58CEJskaaksahqV0qqQYzJK-UG7r0Tpjr5IExxc5xvpTDJ2UBbY29_1fGf5yL6WlYhHT8jqzVCl0dsK1J_hnLEvnimEsSnZWH_d6xuwvSE_qsxjr6QBzwVg2VyH08/s1600/image012.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>b. Oracle Enterprise Manager 12c Cloud Control: </b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Baixar pelo <i>e-delivery </i>(<a href="https://edelivery.oracle.com/linux">https://edelivery.oracle.com/linux</a>). No <b>Media Pack Search</b> escolher <b>Oracle VM Templates</b> e <b>x86 64 bit</b>:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDCLfWfNDFvKl3a_pPqUQ2h6ADn7c0266lLJ7EC7F09h67tcUx1Devrx-rkfEtGDWxQLZGFgWWduT-4Rya1cRXfIUjhJeMpzznxEYSZzqEOm4sGGN8FVEhRzQFjVMpWMh0XS1fVC61N6gy/s1600/image014.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDCLfWfNDFvKl3a_pPqUQ2h6ADn7c0266lLJ7EC7F09h67tcUx1Devrx-rkfEtGDWxQLZGFgWWduT-4Rya1cRXfIUjhJeMpzznxEYSZzqEOm4sGGN8FVEhRzQFjVMpWMh0XS1fVC61N6gy/s1600/image014.png" width="640" /></a></div>
<div style="text-align: justify;">
Baixar o template abaixo:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOktGVTcMPXIdqTRkMcIi3QXX-Rky7yElOg0fcVwh0O0TU2yiICr5ZNPajvp7AidR7H1ahFEu-gcrZZWnagfUqCO2s0zAVzB99LzxGa0Z-Ai8EXnIP4ElQcICoPrWi5U8NhxRrD2OIOcYv/s1600/image016.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOktGVTcMPXIdqTRkMcIi3QXX-Rky7yElOg0fcVwh0O0TU2yiICr5ZNPajvp7AidR7H1ahFEu-gcrZZWnagfUqCO2s0zAVzB99LzxGa0Z-Ai8EXnIP4ElQcICoPrWi5U8NhxRrD2OIOcYv/s1600/image016.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Cuidado para não baixar o o Oracle VM Template, e sim o Oracle VM VirtualBox. O arquivo correto tem 4 partes e 15 GB no total. A versão mais atual é a 12.1.0.4.0.</div>
<br />
<div style="text-align: justify;">
Antes de importar o appliance é necessário descompactar os arquivos e recombiná-los em um só *.OVA. Para fazer isso basta seguir as instruções do readme:</div>
<span style="font-family: "courier new" , "courier" , monospace;"></span><br />
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">a) Extract all of the zip files using unzip. This will create files with the .ova extension. </span></div>
<span style="font-family: "courier new" , "courier" , monospace;">
</span>
<br />
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">b) Run the following command to combine the .ova files into one .ova file: </span></div>
<span style="font-family: "courier new" , "courier" , monospace;">
</span>
<br />
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">On Linux: cat VBox*.ova > EM12cR4.ova</span></div>
<span style="font-family: "courier new" , "courier" , monospace;">
</span>
<br />
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">On Windows: type VBox*.ova > EM12cR4.ova</span></div>
<div style="text-align: justify;">
<span style="color: red;">Sugestão: como é um processo intensivo de I/O, recomendo fazer esta movimentação entre HDs diferentes.</span><br />
<span style="color: red;"><br /></span></div>
<h3 style="text-align: justify;">
</h3>
<h3 style="text-align: justify;">
Descritivo do Ambiente</h3>
<div>
<div style="text-align: justify;">
<br />
Eu estou usando como máquina de teste o notebook Dell Latitude E7240. É um modelo com disco interno SSD e 8 GB de RAM. Eu já fiz um ambiente similar utilizando um note mais antigo, Lenovo Thinkpad T420, também com 8 GB, porém com disco normal. O meu note está com Windows 8, mas no setup anterior fiz com o Windows 7.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Em termos de periféricos, como eu já montei algumas demos bem grandes (exemplo: <b>EBS Vision Single Node</b>, requisitos de 300 GB de disco!), eu comprei dois HDs externos – um HD SSD de 240 GB e outro normal de 1 TB que eu uso como “storage”, ambos em USB 3.0.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A idéia é rodar as VMs a partir do SSD, seja interno ou externo (vou montar no externo neste setup), e manter uma biblioteca de templates no disco normal. Em casos extremos como o do EBS Vision não tem outra escolha senão rodar a VM a partir do disco externo.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: red;"><b>Observação:</b> se vocês forem utilizar o recurso de snapshots extensivamente, sugiro deixar num disco externo bem grande, pois vocês vão ver o disco sumir rapidinho.</span> <span style="color: red;">Também dá para bolar uma estratégia mista, mantendo a imagem original no disco lento e as imagens diferenciais no disco rápido. Depois vou elaborar melhor este ponto, primeiro vamos cuidar dos setups básicos, ok?</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Basicamente, para ter menos concorrência em disco, uma alternativa é alternar sempre o drive de destino. Ex.: baixar os arquivos do template na unidade externa ‘A’, descompactar no disco interno ‘B’ (ou outra unidade externa ‘C’) e recombinar os arquivos para a unidade externa ‘A’ de novo. Eu mantenho um diretório com todos os templates de VM prontos para importar no disco de 1 TB.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A VM do EM12c depois de importada tem em torno de 40 GB. A VM do Oracle Linux tem 5,5 GB. Após o fim de todos os setups é esperado que elas ocupem bem mais espaço, então recomendo reservar cerca de 60 GB para todo o ambiente.<br />
<br /></div>
</div>
<div style="text-align: justify;">
<div style="text-align: start;">
<h3 style="text-align: justify;">
</h3>
<h3 style="text-align: justify;">
Passo 1: Import dos Templates</h3>
</div>
</div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="text-align: start;"><br /></span></div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="text-align: start;">Antes de importar qualquer template é importante indicar para o VirtualBox qual é o diretório de destino das máquinas virtuais. Na tela principal, clicar em <b>Arquivo -> Preferências -> Geral</b> e modificar a pasta padrão das máquinas para o diretório desejado (ficar atento para exigências de espaço livre em disco):</span></div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="text-align: start;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI970ES6QROqBvOsRpq29LeC7BGuBLjOGxsvBKjzPg9VQyU1TAbq6Yvxbmf7PhsRR8ZHmRhgUprmR8lpOoccGEpgY9kfHF5DldTS1aOsJZqunc_2eudAnSEGVGSVuIw7qSMsg1s384KODR/s1600/image018.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI970ES6QROqBvOsRpq29LeC7BGuBLjOGxsvBKjzPg9VQyU1TAbq6Yvxbmf7PhsRR8ZHmRhgUprmR8lpOoccGEpgY9kfHF5DldTS1aOsJZqunc_2eudAnSEGVGSVuIw7qSMsg1s384KODR/s1600/image018.png" /></a></div>
<br />
<div style="text-align: justify;">
Na tela principal do VirtualBox, clicar em <b>Arquivo -> Importar Appliance</b>:</div>
<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinBNVgqQVntB5VHX_C9ManNKW-W1TM6vnxUvjRtTWUAIwG6uyuUntEUI9sYCXlsu9UxGebAhUHtU3GnXj1h7-sIDDaNfSs-iP9otibB1tA6yfduGSwg-JaGbSXy69K9IZlm5WHfyZIchJ2/s1600/image020.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="479" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinBNVgqQVntB5VHX_C9ManNKW-W1TM6vnxUvjRtTWUAIwG6uyuUntEUI9sYCXlsu9UxGebAhUHtU3GnXj1h7-sIDDaNfSs-iP9otibB1tA6yfduGSwg-JaGbSXy69K9IZlm5WHfyZIchJ2/s1600/image020.png" width="640" /></a></div>
<br />
<div style="text-align: justify;">
Selecionar o arquivo <b>EM12cR4.ova</b> e apertar Próximo:</div>
<span style="text-align: justify;"> </span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU8UsH06vzMZ47t4mZbCfoEk_g8F34Ug-B1bVxHDNSFxZkp8ThfBUUw5qjJ-xIShAcEdJtcq_xoluuLGKw5kVH-j7DfJXsEGcFi5ZRElXpnOBTY_pLzdZPiwyUlpcW6h5v6Bq0u8kcR26q/s1600/image022.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU8UsH06vzMZ47t4mZbCfoEk_g8F34Ug-B1bVxHDNSFxZkp8ThfBUUw5qjJ-xIShAcEdJtcq_xoluuLGKw5kVH-j7DfJXsEGcFi5ZRElXpnOBTY_pLzdZPiwyUlpcW6h5v6Bq0u8kcR26q/s1600/image022.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
Na tela seguinte, eu recomendo renomear a máquina virtual para <b>emcc.example.com</b>, reduzir o número de CPUs para 1 e desativar o áudio, para economizar um pouco de recursos. Feito isto basta disparar o import:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3CUE_cOcxvSOGXwAIesJAmj95Pjkn2p_6-mAJXctApsViqAYBDf5mh_Q00IpAAM3k4gyglxz2yFdT0yHJ9t2wikufGyipCBMAv1o8pmZ5OrIYFizj20wgo62oejCFXLKQMeCQli7V8CNu/s1600/image024.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="482" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3CUE_cOcxvSOGXwAIesJAmj95Pjkn2p_6-mAJXctApsViqAYBDf5mh_Q00IpAAM3k4gyglxz2yFdT0yHJ9t2wikufGyipCBMAv1o8pmZ5OrIYFizj20wgo62oejCFXLKQMeCQli7V8CNu/s1600/image024.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
Este processo, considerando o setup que eu comentei, leva em torno de 10 minutos. Se vocês forem importar no mesmo disco, esperem que vai demorar... :)</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Na sequência, fazer o mesmo para o Oracle Linux, renomeando a máquina para oel.example.com e desativando o áudio. O import desta máquina leva em torno de 3 minutos. No final vocês devem ter as duas máquinas na página principal do VirtualBox.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Agora, para eu me organizar melhor, eu costumo fazer duas práticas que vocês podem adotar também ou não. A primeira, é organizar as VMs em grupo, assim eu sei que elas fazem parte do mesmo ambiente. Clique com o botão direito do mouse em uma das VMs e escolha Grupo:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia3zddOBxBFepmjr3MMZd8ACQJpxEBlsAsYRMesBOWi-yesycma0V8o_geoeqzjQRLudp5oLRM3nqYwBcyKg0Ur5rEgJR0pyrU1cENuz1__S1Ke-pMSwihEvFFSDjtW5y83dz9CPcBPJrO/s1600/image026.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="479" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia3zddOBxBFepmjr3MMZd8ACQJpxEBlsAsYRMesBOWi-yesycma0V8o_geoeqzjQRLudp5oLRM3nqYwBcyKg0Ur5rEgJR0pyrU1cENuz1__S1Ke-pMSwihEvFFSDjtW5y83dz9CPcBPJrO/s1600/image026.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<span style="text-align: justify;">Em seguida, arraste a segunda VM para dentro do grupo. Eu vou chamar este grupo de </span><b style="text-align: justify;">EM12c 12.1.0.4</b><span style="text-align: justify;">:</span><br />
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUNO6s49czw8KQ9wNksnqqqQBJa6GSk2Bq95Krz1I335aL0Mft-bIW7MHVkXld9dkJFZQlcq3oFV9mVvdm-PAyKLLup5OCmu6Y_i6YXm3L_orZrgPvQqQa7ZzUdmqkPmbZMBTRf7WCQXY4/s1600/image028.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="479" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUNO6s49czw8KQ9wNksnqqqQBJa6GSk2Bq95Krz1I335aL0Mft-bIW7MHVkXld9dkJFZQlcq3oFV9mVvdm-PAyKLLup5OCmu6Y_i6YXm3L_orZrgPvQqQa7ZzUdmqkPmbZMBTRf7WCQXY4/s1600/image028.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A segunda prática é criar um snapshot a cada passo significativo do setup do ambiente. Como acabamos de importar os templates e esse é um processo que pode ser demorado (importar o EM12cR4.ova na minha máquina antiga levava quase uma hora). </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Manter snapshots é uma forma de garantir “restore points” caso vocês precisem voltar o ambiente para o estado anterior, seja para desfazer um erro de configuração ou ainda como um passo natural para ambientes de demo. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Vou criar um para cada VM a fim de guardar este estado inicial. Primeiro clique em <b>Snapshots</b>, e depois em <b>Criar Snapshot</b>:</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrNmQ-Kgb-CCF7lIUnC_wilPw5ywJMrM_TDUdCEH8LqND-9Tljze4RUHtgs9wg_37TPxxeM1EAbdKR0ATjq6HrLQwUePwenFOfZXe1k7g-AbuPBfaCU7tI9kgVoaIgKdKwT2NuVDytGEbf/s1600/image034.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="479" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrNmQ-Kgb-CCF7lIUnC_wilPw5ywJMrM_TDUdCEH8LqND-9Tljze4RUHtgs9wg_37TPxxeM1EAbdKR0ATjq6HrLQwUePwenFOfZXe1k7g-AbuPBfaCU7tI9kgVoaIgKdKwT2NuVDytGEbf/s1600/image034.png" width="640" /></a></div>
<div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdjQSsgXYHA2_g4QCZLIzgOXWCy3xJ4Kgi1fAERYhC7JTj4VbxBxqCqWLNInEqXJlIamHTtkJ-oWGtzYBQ9Zdq72FzdR4WEbjoLSWSfphL0SzALWe4HdKi8jtgkKWDMi8yy_V9LwdVOp5c/s1600/image036.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdjQSsgXYHA2_g4QCZLIzgOXWCy3xJ4Kgi1fAERYhC7JTj4VbxBxqCqWLNInEqXJlIamHTtkJ-oWGtzYBQ9Zdq72FzdR4WEbjoLSWSfphL0SzALWe4HdKi8jtgkKWDMi8yy_V9LwdVOp5c/s1600/image036.png" width="314" /></a></div>
<h3 style="text-align: justify;">
</h3>
<h3 style="text-align: justify;">
</h3>
<h3 style="text-align: justify;">
Passo 2: Configuração do EM12c</h3>
<span style="text-align: justify;"><br /></span>
<span style="text-align: justify;">Estamos prontos para inciar a VM pela primeira vez. Inicie a VM </span><b style="text-align: justify;">emcc.example.com</b><span style="text-align: justify;">. O usuário e senha é </span><b style="text-align: justify;">oracle/welcome1</b><span style="text-align: justify;">. Como primeira tarefa, vamos atualizar os Adicionais para Convidado. No menu do VirtualBox, clicar em </span><b style="text-align: justify;">Dispositivos -> Inserir imagem de CD dos Adicionais para Convidados...</b><br />
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggg9XCHUZQCPUxxA3a3nTELPgq05lImYMBAM-QDQ8Pfnw2vSTG4NKy47lq-NZNdJJPyAPboiSTTYNWrMcdgS64_sfVj_XWInEUAIjamIayWyy1IVauyAi1mLT_F1YcSk6Jp9S4KUftLddy/s1600/image038.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="359" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggg9XCHUZQCPUxxA3a3nTELPgq05lImYMBAM-QDQ8Pfnw2vSTG4NKy47lq-NZNdJJPyAPboiSTTYNWrMcdgS64_sfVj_XWInEUAIjamIayWyy1IVauyAi1mLT_F1YcSk6Jp9S4KUftLddy/s1600/image038.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Na caixa de mensagem que abrir na tela, dar um duplo clique no <b>autorun.sh</b> e escolher <b>Run in Terminal</b>. Ele vai pedir o password do <b>root </b>que também é <b>welcome1</b>. Espere concluir o processo e você pode “ejetar” o CD.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Vamos dar um shutdown na VM e preparar o ambiente de rede. O primeiro passo é configurar a rede de hospedeiro. No menu do VirtualBox, clique em <b>Arquivo -> Preferências -> Rede -> Redes Exclusivas de Hospedeiro</b>. Deve haver pelo menos um adaptador criado:<br />
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCQ3cLdWI028_tVUjv08o2ZhydvtcF6sCZ6Zaw1XSI25IaBuniC9hFX_eikwDxt_NXLJenUtLtceiCvTqpTCiYXei7QxBfbnkLk2uZXwaLfwpBvpb3WmAI-vAf05veDh9h89SBhVI5borz/s1600/image040.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCQ3cLdWI028_tVUjv08o2ZhydvtcF6sCZ6Zaw1XSI25IaBuniC9hFX_eikwDxt_NXLJenUtLtceiCvTqpTCiYXei7QxBfbnkLk2uZXwaLfwpBvpb3WmAI-vAf05veDh9h89SBhVI5borz/s1600/image040.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Se não houver, criar um com o ícone + no canto direito da tela. Clique na chave de fenda e depois em <b>Servidor DHCP</b> para ver as configurações da rede:<br />
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZAAek1J3J9BIdosaV8Ktt_IXKRjgL9pIVqP1DELUc1rKLlQ9RSXy2uj1H799mP9AVxXHjHSqbrKAEIqOna-UXO7SwwmZdPfrBccjzUsuP4rvPpI_Gp3SNmcrdS5pHAuHiQLHB5bagFEz3/s1600/image042.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZAAek1J3J9BIdosaV8Ktt_IXKRjgL9pIVqP1DELUc1rKLlQ9RSXy2uj1H799mP9AVxXHjHSqbrKAEIqOna-UXO7SwwmZdPfrBccjzUsuP4rvPpI_Gp3SNmcrdS5pHAuHiQLHB5bagFEz3/s1600/image042.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Por padrão o VirtualBox utiliza a faixa de IPs de 192.168.56.x. IPs iguais ou maiores que 101 estão reservados para o servidor DHCP interno. Como nós vamos utilizar este ambiente para testes de data guard, RAC, etc, recomendo utilizar IPs fixos na faixa de 10 a 100.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para meu setup inicial, vou considerar as seguintes máquinas:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">192.168.56.10 emcc.example.com emcc</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">192.168.56.20 oel.example.com oel</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Adicione estes endereços nos arquivos hosts de todos os servidores, incluindo o computador host do VirtualBox e as VMs. No Windows 8, o arquivo hosts está no caminho <b>X:\Windows\System32\drivers\etc\hosts</b>, onde <b>X </b>é a unidade de instalação do SO. No <b>Linux</b>, o arquivo hosts está no caminho <b>/etc/hosts</b>. (Um atalho rápido para linha de comando no Windows 8 é pressionar a tecla <b>Windows+x</b> e depois pressionar ‘<b>a</b>’. É preciso ter acesso de administrador para editar o arquivo hosts)</div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
</div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE15XCYnlFyyvT2mXt1hBAlPhGGT-Bnz5ou4LRtsfNiQCpcejMUOtoBlg_wx0MnRSjvRPOsfnN1ks07TdZniU3HsgFjkQz2PT3C_vELzsQWSukn6qwxCoeNJ6uduV55Ldx6lCVZQrxVCHR/s1600/image044.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE15XCYnlFyyvT2mXt1hBAlPhGGT-Bnz5ou4LRtsfNiQCpcejMUOtoBlg_wx0MnRSjvRPOsfnN1ks07TdZniU3HsgFjkQz2PT3C_vELzsQWSukn6qwxCoeNJ6uduV55Ldx6lCVZQrxVCHR/s1600/image044.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMWck3k2t46z1BQlA9bL3jhxdkx93JkyPzC1z0kbHyRhpKghsn_z6t4amsNRuy-vRKoJfQUn8KI-hpFWPv11He0S67w7pZe8zXVNG6t730ux2Odq19DQGks35qHfbDuOJrEfB7uSwuPJhW/s1600/image046.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="509" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMWck3k2t46z1BQlA9bL3jhxdkx93JkyPzC1z0kbHyRhpKghsn_z6t4amsNRuy-vRKoJfQUn8KI-hpFWPv11He0S67w7pZe8zXVNG6t730ux2Odq19DQGks35qHfbDuOJrEfB7uSwuPJhW/s1600/image046.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Feito isso vamos mudar as configurações das placas de rede dos dois servidores para fixar estes IPs. No VirtualBox, clicar com o botão direito no nome da máquina (<b>emcc.example.com</b>) e depois em <b>Configurações -> Rede</b> e trocar o adaptador para <b>Placa de Rede Exclusiva de Hospedeiro (host-only)</b>.<br />
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhECkRSdU8nNKFclgMUmawcff8KtvOfnj99WG1wCB5Ik64d9edfw2xz8l7-wLU2j04mtprkNPGpjAo_lCVl5-8-q1WRx4Z1L-q9QfDYs9KoC4cQZMleuU7uyQtw6ciB9Yn2RyIcIm1gLNtg/s1600/image048.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhECkRSdU8nNKFclgMUmawcff8KtvOfnj99WG1wCB5Ik64d9edfw2xz8l7-wLU2j04mtprkNPGpjAo_lCVl5-8-q1WRx4Z1L-q9QfDYs9KoC4cQZMleuU7uyQtw6ciB9Yn2RyIcIm1gLNtg/s1600/image048.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Fazer o mesmo para a máquina <b>oel.example.com</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Um último passo de setup que pode economizar bastante tempo no futuro é definir uma pasta compartilhada para as VMs e o host. Ainda na tela de Configurações, escolher o último item, <b>Pastas Compartilhadas</b>. Eu costumo acrescentar uma pasta s<i>hared </i>no meu disco “Storage”.</div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgivL2Ia3xl8XF6ih0oFZT2B-lXepVxKPadnxR162nQrnp3ToHZWOkYFR71Su13SW2L6cn5iO-TrFxi2kXZdUq12gPcwGWCf5GD2LzPSwTWELXqgDJY8itwz7vDayQFt85auveWxHvR1oao/s1600/image050.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgivL2Ia3xl8XF6ih0oFZT2B-lXepVxKPadnxR162nQrnp3ToHZWOkYFR71Su13SW2L6cn5iO-TrFxi2kXZdUq12gPcwGWCf5GD2LzPSwTWELXqgDJY8itwz7vDayQFt85auveWxHvR1oao/s1600/image050.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A pasta compartilhada vai estar disponível no diretório <b>/media/sf_nome</b>. Como a minha pasta se chama <i>shared</i>, ela aparece como <b>/media/sf_shared</b>. Note que para o usuário oracle poder ler e gravar nesta pasta ele precisa das permissões corretas. Para fazer isso é necessário acessar o terminal da VM e adicionar o usuário oracle ao grupo <b>vboxsf</b>:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRIAuhzdOQGzqpBsEVJGIjsLvLU8Dx6TshglD5K_9EVDYtSssPzo4kXleLhfaacfdDUCJHWJM2fER1c8hBnFLG9PaLLjPdbHC5pYfWm9eOgmaAIKqHkc0eW_0WgmUUE9kgJezDBGNDlO2O/s1600/image051.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="445" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRIAuhzdOQGzqpBsEVJGIjsLvLU8Dx6TshglD5K_9EVDYtSssPzo4kXleLhfaacfdDUCJHWJM2fER1c8hBnFLG9PaLLjPdbHC5pYfWm9eOgmaAIKqHkc0eW_0WgmUUE9kgJezDBGNDlO2O/s1600/image051.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Depois dessa mudança é necessário fazer Log Out / Log On para que o X Windows reconheça as novas permissões.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
(<span style="color: red;"><b>Observação:</b> outra coisa que pode ajudar bastante neste momento é habilitar o clipboard bi-direcional no VirtualBox.</span> <span style="color: red;">Isso pode ser feito no menu <b>Dispositivos -> Área de Transferência Compartilhada -> Bi-direcional</b>)</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Agora vamos subir a máquina emcc.example.com. Inicie a VM e entre com o usuário <b>oracle/welcome1</b>. Precisamos mudar o IP do adaptador de rede e configurar o arquivo hosts assim como fizemos no Windows. Vá em <b>System -> Administration -> Network</b>, entre com a senha de <b>root </b>- <b>welcome1</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
É possível configurar tudo a partir desta única tela, basta seguir os modelos abaixo. Selecionar <b>eth0 </b>e clicar em <b>edit</b>:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxWRws0F6C73uVAOf4H9WcrZPnBFChPrj46EBlaQniBttQ4JH6AXZcnN5sV502Ge0iT3d0y_BNU7-WuPNBX3bXC2KKPUztocTvtrgHx3TT8e9PsclrTBLYiNydIh-KbLVrbXGWf032Bdbq/s1600/image053.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxWRws0F6C73uVAOf4H9WcrZPnBFChPrj46EBlaQniBttQ4JH6AXZcnN5sV502Ge0iT3d0y_BNU7-WuPNBX3bXC2KKPUztocTvtrgHx3TT8e9PsclrTBLYiNydIh-KbLVrbXGWf032Bdbq/s1600/image053.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Configurar o IP estático:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyh1A2c21pBmFu29KSZ9jMM-hv9hONlNXzbreC4u3jZXWfYYDRU84hfylbvjvVHkpet7NKZ4-WkuN5n4XvGtfLughx2mMu8E1SwZBxaE1Zbr6Qjkq65wsQ1ZRke2_D28ylWPkHAlreXilA/s1600/image055.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyh1A2c21pBmFu29KSZ9jMM-hv9hONlNXzbreC4u3jZXWfYYDRU84hfylbvjvVHkpet7NKZ4-WkuN5n4XvGtfLughx2mMu8E1SwZBxaE1Zbr6Qjkq65wsQ1ZRke2_D28ylWPkHAlreXilA/s1600/image055.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Na aba hosts, adicionar os endereços do <b>emcc.example.com</b> e <b>oel.example.com</b>:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfa1wr1pE2fRtEZVEPo8fIDfT6GgUUNXo4MbbAGSC-GyISZiTCJEuukkBybXlGWQocyqDY9HOliPzmwJrYyRCjk30HTukNJHjwI6n61Wz3RDHW3_QwdSXNwugmjs2PXi1PQ14wuge0nqVW/s1600/image057.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfa1wr1pE2fRtEZVEPo8fIDfT6GgUUNXo4MbbAGSC-GyISZiTCJEuukkBybXlGWQocyqDY9HOliPzmwJrYyRCjk30HTukNJHjwI6n61Wz3RDHW3_QwdSXNwugmjs2PXi1PQ14wuge0nqVW/s1600/image057.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy5Y1zh5NnGW0KWc7Qy2TD2tB_4ZeffOmELBJ071S8gsPhaUI0Ptt6xmkdig-lYK-y0zBfzu3Y_C5pEJMCTSn65p89ApfjoLHRosweTVMK08qTRymDXre1Igl3KO9wLA4KoKweYc7yRgkX/s1600/image059.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy5Y1zh5NnGW0KWc7Qy2TD2tB_4ZeffOmELBJ071S8gsPhaUI0Ptt6xmkdig-lYK-y0zBfzu3Y_C5pEJMCTSn65p89ApfjoLHRosweTVMK08qTRymDXre1Igl3KO9wLA4KoKweYc7yRgkX/s1600/image059.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy3IaZ5e1Ch1joUXeR1zhMEouVzJD3CFAjnzQWOLHKRoU9eDXQwZWuPSB2XeMRolwwIKX7sC1QrHqbNv0ubTH1E6yltg8khZbr46gxWXS6F28V4Z6LWJqFyAz0qcCSQ9ppwUp1HTPJB_FW/s1600/image061.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy3IaZ5e1Ch1joUXeR1zhMEouVzJD3CFAjnzQWOLHKRoU9eDXQwZWuPSB2XeMRolwwIKX7sC1QrHqbNv0ubTH1E6yltg8khZbr46gxWXS6F28V4Z6LWJqFyAz0qcCSQ9ppwUp1HTPJB_FW/s1600/image061.png" /></a></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Está na hora de iniciar o EM12c, finalmente, mas os scripts estão bugados... Então antes de subir o EM precisamos corrigi-los no terminal. Abra uma janela do terminal pelo menu <b>Applications -> Accessories -> Terminal</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Então renomeamos os scripts antigos e criamos dois scripts novos para start/stop do oms:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ mv start_oms.sh start_oms.sh.old</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ mv stop_oms.sh stop_oms.sh.old</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ echo /u01/OracleHomes/Middleware/oms/bin/emctl start oms > start_oms.sh</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ echo /u01/OracleHomes/Middleware/oms/bin/emctl stop oms > stop_oms.sh</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ chmod +x start_oms.sh</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ chmod +x stop_oms.sh</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Agora é um bom momento para criar um snapshot da VM. Utilizando a tecla host (Ctrl Direito) + T você pode chamar a tela de criação de snapshots diretamente da VM.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyVKVw9WwmXyREbaGQC9waTVeOzr72S6uhxnGYw_8bjcxn3kDZI2SqlkRf__2BCHtbGT1X8JECiiRxhS_MFucc8P7wl5-26JkPft-8OBBaLlP2djj2gq6ZLNcnryJ0vcEITjTWYH0ZrTfk/s1600/image063.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyVKVw9WwmXyREbaGQC9waTVeOzr72S6uhxnGYw_8bjcxn3kDZI2SqlkRf__2BCHtbGT1X8JECiiRxhS_MFucc8P7wl5-26JkPft-8OBBaLlP2djj2gq6ZLNcnryJ0vcEITjTWYH0ZrTfk/s1600/image063.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Feito isso basta rodar o script <b>start_all.sh</b> para iniciar o ambiente. O startup pode levar alguns minutos dependendo da máquina, sendo o mais demorado o OMS. Para checar que os detalhes da configuração do OMS, após a inicialização, basta rodar o seguinte comando:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ /u01/OracleHomes/Middleware/oms/bin/emctl status oms –details</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Oracle Enterprise Manager Cloud Control 12c Release 4 </span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Copyright (c) 1996, 2014 Oracle Corporation. All rights reserved.</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Enter Enterprise Manager Root (SYSMAN) Password : </span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Console Server Host : emcc.example.com</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">HTTP Console Port : 7788</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">HTTPS Console Port : 7799</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">HTTP Upload Port : 4889</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">HTTPS Upload Port : 4900</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">EM Instance Home : /u01/OracleHomes/gc_inst/em/EMGC_OMS1</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">OMS Log Directory Location : /u01/OracleHomes/gc_inst/em/EMGC_OMS1/sysman/log</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">OMS is not configured with SLB or virtual hostname</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Agent Upload is locked.</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">OMS Console is locked.</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Active CA ID: 1</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Console URL: https://emcc.example.com:7799/em</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Upload URL: https://emcc.example.com:4900/empbs/upload</span></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">WLS Domain Information</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Domain Name : GCDomain</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Admin Server Host : emcc.example.com</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Admin Server HTTPS Port: 7101</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Admin Server is RUNNING</span></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Oracle Management Server Information</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Managed Server Instance Name: EMGC_OMS1</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Oracle Management Server Instance Host: emcc.example.com</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">WebTier is Up</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">Oracle Management Server is Up</span></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">BI Publisher is not configured to run on this host.</span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace;">$ </span></div>
<div>
<br /></div>
<div>
<div style="text-align: justify;">
O EM12c já está no ar, porém está acessível apenas a partir da VM. O último passo para liberar o acesso do EM12c no host do VirtualBox é mudar a configuração do Firewall. Existem duas opções: desabilitar o firewall completamente ou adicionar as portas do EM12c como exceção. Ambas as configurações podem ser feitas no menu <b>System -> Administration -> Security Level and Firewall</b>. Para manter a simplicidade do demo, vou simplesmente desabilitar o Firewall como um todo.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWwQ7x61DEp2NDheKr2OkXI6cMQ0pQUNQh9MAWMwox72tEzZVq_3e9q89F6pQJ72RJdmfnVWBijhc_ec7XKjg8_b4zYiJnJemnVxgzheq4oRJr05m3jc2Z6UNhIIPIRwPRNgUR0uig1FD2/s1600/image065.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWwQ7x61DEp2NDheKr2OkXI6cMQ0pQUNQh9MAWMwox72tEzZVq_3e9q89F6pQJ72RJdmfnVWBijhc_ec7XKjg8_b4zYiJnJemnVxgzheq4oRJr05m3jc2Z6UNhIIPIRwPRNgUR0uig1FD2/s1600/image065.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Com tudo no ar, basta abrir uma janela do browser no host Windows e digitar o endereço <a href="https://emcc.example.com:7799/em">https://emcc.example.com:7799/em</a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Se a página não abrir, existe um passo adicional de configuração na rede do host. Numa linha de comando, verifique que a rede <b>VirtualBox Host-Only Network </b>está na mesma faixa de endereços que a VM utilizando o comando ipconfig:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">Ethernet adapter VirtualBox Host-Only Network:</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">Connection-specific DNS Suffix . :</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">Link-local IPv6 Address . . . . . : fe80::494f:65d3:7114:caef%13</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">Autoconfiguration IPv4 Address. . : 169.254.202.239</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">Subnet Mask . . . . . . . . . . . : 255.255.0.0</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">Default Gateway . . . . . . . . . :</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
No meu caso ela não está, então para corrigir vamos alterar as configurações da rede no Painel de Controle:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB7wOZcl-8yOO14bZYlLINzHnfvAJntEd0ExJpWI9Go1h0vX7qLZYgoiizOpBU0KpOSpSSwiJoA45w1WJ6EKIQXTPo5uXDO3KX4as2xcxISmPUmVo9zce4U0iTBlicpsib3UYz-6shyEVT/s1600/image067.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="359" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB7wOZcl-8yOO14bZYlLINzHnfvAJntEd0ExJpWI9Go1h0vX7qLZYgoiizOpBU0KpOSpSSwiJoA45w1WJ6EKIQXTPo5uXDO3KX4as2xcxISmPUmVo9zce4U0iTBlicpsib3UYz-6shyEVT/s1600/image067.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
As configurações do IPV4 estavam erradas. É só colocar tudo em automático e voltar ao teste. Para confirmar que o problema está resolvido, basta rodar um ping na linha de comando:</div>
<div style="text-align: justify;">
<br />
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">C:\Windows\system32>ping emcc<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">Pinging emcc.example.com [192.168.56.10]
with 32 bytes of data:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">Reply from 192.168.56.10: bytes=32
time<1ms TTL=64<!--1ms--><!--1ms--><!--1ms--><!--1ms--><!--1ms--></span></div>
</div>
</div>
</div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">Reply from 192.168.56.10: bytes=32
time<span style="text-align: justify;"><</span>1ms </span><span style="font-family: "courier new"; line-height: 17.1200008392334px; text-align: justify;">TTL=64</span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">Reply from 192.168.56.10: bytes=32
time<span style="text-align: justify;"><</span>1ms </span><span style="font-family: "courier new"; line-height: 17.1200008392334px; text-align: justify;">TTL=64</span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">Reply from 192.168.56.10: bytes=32
time<span style="text-align: justify;"><</span>1ms </span><span style="font-family: "courier new"; line-height: 17.1200008392334px; text-align: justify;">TTL=64</span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">Ping statistics for 192.168.56.10:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">Approximate round trip times in
milli-seconds:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span lang="EN-US" style="font-family: "courier new"; line-height: 107%;">
Minimum = 0ms, Maximum = 0ms, Average = 0ms<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<br /></div>
<br />
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-family: "courier new"; line-height: 107%;">C:\Windows\system32><span style="font-size: 10pt;"><o:p></o:p></span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
De volta ao browser:</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPIWzWWWNHUPctH2qAmVzOejg79YnCy1qMBK57G44LjLBzT0WeKXVeg6YfJvm8dPQ1W6eXg5bobo5g1FiUViXTtkbBiIXBxVFVXSXUz3MW-E3wid18oWR4gZeU4Wa2RaD3SZv1NuLFrrE7/s1600/image069.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="341" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPIWzWWWNHUPctH2qAmVzOejg79YnCy1qMBK57G44LjLBzT0WeKXVeg6YfJvm8dPQ1W6eXg5bobo5g1FiUViXTtkbBiIXBxVFVXSXUz3MW-E3wid18oWR4gZeU4Wa2RaD3SZv1NuLFrrE7/s1600/image069.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Voilá! Sucesso! :)</div>
<div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Lembrando que a senha do sysman é welcome1.</div>
<h3 style="text-align: justify;">
<span style="color: red;"><br /></span></h3>
<h3 style="text-align: justify;">
<span style="color: red;">Opcional:</span> Executar a VM sem interface gráfica.</h3>
</div>
<div>
<div style="text-align: justify;">
<br />
Para economizar um pouco de recursos, eu gosto de desabilitar a interface gráfica das VMs e consolidar todo o gerenciamento via browser no host do VirtualBox. Para fazer isso, primeiro é necessário baixar os serviços do EM12c. No terminal, execute o script <b>stop_all.sh</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Em seguida, como root edite o arquivo /etc/inittab e troque o default runlevel de 5 para 3:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># Default runlevel. The runlevels used by RHS are:</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># 0 - halt (Do NOT set initdefault to this)</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># 1 - Single user mode</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># 2 - Multiuser, without NFS (The same as 3, if you do not have networking)</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># 3 - Full multiuser mode</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># 4 - unused</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># 5 - X11</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"># 6 - reboot (Do NOT set initdefault to this)</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">#</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">id:3:initdefault:</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Reinicie a máquina, entre com o usuário <b>oracle/welcome1</b> e execute o script <b>start_all.sh</b> novamente. Estamos prontos!<br />
<br /></div>
</div>
<h3 style="text-align: justify;">
</h3>
<h3 style="text-align: justify;">
Passo 3: Configuração da máquina Linux</h3>
<div style="text-align: justify;">
<div>
<br />
O objetivo do tutorial era criar um ambiente EM12c para demos. Uma das primeiras coisas que os clientes gostam de ver é como se faz uma instalação de agentes remotamente. É para isso que eu vou utilizar esta máquina com o Oracle Linux.</div>
<div>
<br /></div>
<div>
Primeiro, vamos configurar a conectividade. Inicie a VM <b>oel.example.com</b>. O usuário e senha é <b>oracle/oracle</b>.</div>
<div>
<br /></div>
<div>
Como é uma versão diferente do Linux, os menus estão em lugares diferentes, mas os objetivos são os mesmos:</div>
<div>
<br /></div>
<div>
1. Instalar Adicionais para Convidados</div>
<div>
<br /></div>
<div>
2. Desabilitar (ou configurar) o Firewall: em <b>System -> Administration -> Firewall</b></div>
<div>
<br /></div>
<div>
3. Configurar o IP estático: <b>System -> Preferences -> Network Connections</b>. Em <b>eth0 -> Edit</b>.</div>
<div>
<br /></div>
<div>
4. Adicionar entradas de endereço no arquivo <b>/etc/hosts</b>.</div>
<div>
<br /></div>
<div>
5. Configurar <b>Pastas Compartilhadas</b>, incluindo permissões do usuário oracle e owner da pasta.</div>
<div>
<br /></div>
<div>
Um passo adicional que não foi necessário fazer na VM anterior é mudar o nome da máquina. É preciso editar o arquivo <b>/etc/sysconfig/network</b> e mudar a linha HOSTNAME para HOSTNAME=oel.example.com.</div>
<div>
<br /></div>
<div>
Além disso, precisamos adicionar o usuário oracle na lista de <b>sudoers</b>. Como <b>root</b>, utilize o comando <b>visudo </b>e adicione a seguinte linha no final do arquivo:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">oracle ALL=(ALL) ALL</span></div>
<div>
<br /></div>
<div>
Ainda no visudo, vamos aproveitar para mudar as propriedades <b>requiretty </b>para <b>!requiretty</b> e <b>!visiblepw</b> para <b>visiblepw</b>:</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtuWsSagFFdDgTUBwW5kq9zPFGAPq073_gntcp_KuNH-cDEq9JLcQymYDFlNlalm1DwavjBZvvkWPmf0GhEw235r81sZc9v0Dd7PUxoegGlA9SF00C6dT8UoLfR4Et3UybLIkotUKIocOH/s1600/image071.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="450" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtuWsSagFFdDgTUBwW5kq9zPFGAPq073_gntcp_KuNH-cDEq9JLcQymYDFlNlalm1DwavjBZvvkWPmf0GhEw235r81sZc9v0Dd7PUxoegGlA9SF00C6dT8UoLfR4Et3UybLIkotUKIocOH/s1600/image071.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Também vamos criar a hierarquia de diretórios para acomodar a instalação do agente. Como <b>root </b>digite:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">mkdir /u01</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">chown oracle:oracle /u01</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<h3 style="text-align: justify;">
</h3>
<h3 style="text-align: justify;">
Passo 4: Instalar o agente do EM12c no host oel.example.com</h3>
<div style="text-align: justify;">
<div>
<br />
Agora que temos todo o ambiente preparado, vamos adicionar a VM <b>oel.example.com</b> como um alvo gerenciado no EM12c.</div>
<div>
<br /></div>
<div>
No menu <b>Setup -> Add Target -> Configure Auto Discovery</b> vamos criar uma nova pesquisa para encontrar o host <b>oel.example.com</b>.</div>
<div>
<br /></div>
<div>
Clique em <b>Create </b>para adicionar uma nova regra de descoberta:</div>
<div>
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjufEXMme5nyyekqcXovVNuj8VFnvVcOlEOnSuBzFbpi0wgUb8-zwIiyfD8qK5rSeW4O-q6qoRQsIG2uJmfDPkkOVa8RqpQVVxh5tMRofgMxp65LUHa7K_cna4jzdSEfPLnGzQZZm2VD-5s/s1600/image073.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjufEXMme5nyyekqcXovVNuj8VFnvVcOlEOnSuBzFbpi0wgUb8-zwIiyfD8qK5rSeW4O-q6qoRQsIG2uJmfDPkkOVa8RqpQVVxh5tMRofgMxp65LUHa7K_cna4jzdSEfPLnGzQZZm2VD-5s/s1600/image073.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Na tela seguinte, clique em <b>Add</b>. Neste passo estamos escolhendo o agente do EM12c que vai ficar responsável por fazer esta varredura. No caso, só temos um agente disponível, o do próprio EM12c:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD8H7C0zEkerOJ4Gp8bnMYEWotfuHSIt61Hgstvf5VJl0hQIaX-k6fo1_YOWf9hNFqVbxcB5OoK8eVSVR3dVv3mSZMbeJnHPQQsoMA57WcNGZwVQgMAMNXFIky117BOvcOuQ6p-TdyZ46T/s1600/image075.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD8H7C0zEkerOJ4Gp8bnMYEWotfuHSIt61Hgstvf5VJl0hQIaX-k6fo1_YOWf9hNFqVbxcB5OoK8eVSVR3dVv3mSZMbeJnHPQQsoMA57WcNGZwVQgMAMNXFIky117BOvcOuQ6p-TdyZ46T/s1600/image075.png" width="640" /></a></div>
<div style="text-align: justify;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNl8FwZCkw2-J6rBRtpGJ4pGAkBfK5KmPcPqA9KyccGQt2YdrQvzm986UAjjD0feONcJH130fw_AZTAzKoPn-TU8LVzLwxOflXoThv9KJIq6uD_mAbJXk-wddaj0ceGGKe7S6z6TYT5okk/s1600/image077.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNl8FwZCkw2-J6rBRtpGJ4pGAkBfK5KmPcPqA9KyccGQt2YdrQvzm986UAjjD0feONcJH130fw_AZTAzKoPn-TU8LVzLwxOflXoThv9KJIq6uD_mAbJXk-wddaj0ceGGKe7S6z6TYT5okk/s1600/image077.png" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Selecione o agente <b>emcc.example.com:3872</b> para prosseguir para a próxima tela. Agora temos que preencher o formato de busca do <i>host</i>. Você pode preencher vários valores separados por espaços e utilizar faixas de endereço ou nomes de <i>hosts</i>. Eu optei por fazer a busca diretamente pelo nome do <i>host </i>para economizar tempo.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghcUKa1gqA09GdCGpr9yqqfG0JjuRqAqCkeztvDLSW7DieqwAKAPPdrzFqY-Nny0W1AZK8sl92fMN0-sZHToFbZD0RNuLhZmHRucMSB9Hu65HgxVDIcfYJCuB3FoCI8xnqGbdsOMJmSm8c/s1600/image079.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghcUKa1gqA09GdCGpr9yqqfG0JjuRqAqCkeztvDLSW7DieqwAKAPPdrzFqY-Nny0W1AZK8sl92fMN0-sZHToFbZD0RNuLhZmHRucMSB9Hu65HgxVDIcfYJCuB3FoCI8xnqGbdsOMJmSm8c/s1600/image079.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
É necessário definir também as credenciais de <b>root </b>(ou <i>poweruser</i>) do <i>host </i>onde está o agente que vai fazer a varredura. Lembrando, a senha do <b>root </b>é <b>welcome1</b>. Vou salvar esta credencial como credencial nomeada para uso futuro:</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJMYn-K-4WITCf5odOYIgjN9dbRaa12GAxkXtIZMBouFerDyfRIv12oz9GVFfulbapQYt0miuEz-Vq_j_UFu4ObJEe_dhptHf1tbYUPDuURiSDvkC-0obdlYo7RDniSiRUJ_CScAraQ_PE/s1600/image081.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJMYn-K-4WITCf5odOYIgjN9dbRaa12GAxkXtIZMBouFerDyfRIv12oz9GVFfulbapQYt0miuEz-Vq_j_UFu4ObJEe_dhptHf1tbYUPDuURiSDvkC-0obdlYo7RDniSiRUJ_CScAraQ_PE/s1600/image081.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Ao clicar em <b>Save and Submit Scan</b> você vai voltar para a tela anterior:<br />
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm5fcAqjG5FmRFu2mUZ1xMb_nOFBVoxfLHrmB1X9TYcjPtrSiPTeqgo7C1l990oWrEwpa4SAoz_uugvYLHo3jpmgfJ4PTp1OMGUntQm35eRoiSunxqiXVa7hOGWtKgrOctUOzqfwVaRkxe/s1600/image083.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhm5fcAqjG5FmRFu2mUZ1xMb_nOFBVoxfLHrmB1X9TYcjPtrSiPTeqgo7C1l990oWrEwpa4SAoz_uugvYLHo3jpmgfJ4PTp1OMGUntQm35eRoiSunxqiXVa7hOGWtKgrOctUOzqfwVaRkxe/s1600/image083.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Depois de poucos segundos o resultado já deve estar completo:</div>
<div style="text-align: justify;">
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNB8nrkplD-6iOPQva77-WsKxIB8IvkYRod3Xkh2r6iriNfSOTJQeUaX9cWQfh8Rk3GqttpPH3REcoc6pMhtOeSxV1yqdwINSnJARrAH6nBbKr64jyPR6jlsbGM9Fc1vUqBS7ys7HX3OL_/s1600/image085.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNB8nrkplD-6iOPQva77-WsKxIB8IvkYRod3Xkh2r6iriNfSOTJQeUaX9cWQfh8Rk3GqttpPH3REcoc6pMhtOeSxV1yqdwINSnJARrAH6nBbKr64jyPR6jlsbGM9Fc1vUqBS7ys7HX3OL_/s1600/image085.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Você pode ver o resultado da pesquisa clicando no número “1” na coluna <b>Discovered Targets</b>, ou pelo menu <b>Setup -> Add Target -> Auto Discovery Results</b>. Na primeira aba da tela, <b>Host and Oracle VM Manager</b>, é possível promover o <i>host </i>para gerenciado pelo botão <b>Promote</b>: </div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSz1N0aIn5qBBtB2_6_VnW5RgAGKBZD2DxEu4-kSLla6vOeMTAxwsyARFa90V2xEKKDamyoEftiF0Khgs-STpgKAqJZt_YR76ftZbvwnHyqGOpAxy1fzXikqrsQ2Pf2mCmwmojInLlBJAd/s1600/image087.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSz1N0aIn5qBBtB2_6_VnW5RgAGKBZD2DxEu4-kSLla6vOeMTAxwsyARFa90V2xEKKDamyoEftiF0Khgs-STpgKAqJZt_YR76ftZbvwnHyqGOpAxy1fzXikqrsQ2Pf2mCmwmojInLlBJAd/s1600/image087.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
O <b>Promote </b>vai abrir um w<i>izard </i>para guiar a instalação do agente do EM12c no <i>host</i>:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv5U72tcSckp5KA2sVZeqF3-HcCw4eEtuqHF9khTg_LsUItC04EqHPa5807Qj62G96aGtDMaopxUrun6pb_7uK-paRsFJWWtITi4X_n3j4HmfBE95Zu5olZda-13-AbB6kKtSGO-cEsC9e/s1600/image089.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv5U72tcSckp5KA2sVZeqF3-HcCw4eEtuqHF9khTg_LsUItC04EqHPa5807Qj62G96aGtDMaopxUrun6pb_7uK-paRsFJWWtITi4X_n3j4HmfBE95Zu5olZda-13-AbB6kKtSGO-cEsC9e/s1600/image089.png" width="640" /></a><br />
<br /></div>
<div style="text-align: justify;">
Na primeira tela não tem muito segredo, é só certificar que o SO foi descoberto corretamente. Na segunda tela especificamos o caminho da instalação do agente. Pode ser qualquer caminho que faça sentido. Vou colocar <b>/u01/agentHome</b>:</div>
<div style="text-align: justify;">
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3RozC96-WfWHeuC0xJFM9R6P85ZVcyEQAEuLhKnxdB_K1DnJEQAUFk8hO3tCGSGel3yXAZ-suE2p5HfptEuuz68xCDD97B4VjbJMWCA8AiTQJ5juKj8JpAkNdGxxC5ikj9vcwTR5Ooz1I/s1600/image091.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3RozC96-WfWHeuC0xJFM9R6P85ZVcyEQAEuLhKnxdB_K1DnJEQAUFk8hO3tCGSGel3yXAZ-suE2p5HfptEuuz68xCDD97B4VjbJMWCA8AiTQJ5juKj8JpAkNdGxxC5ikj9vcwTR5Ooz1I/s1600/image091.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Também vou criar uma credencial nomeada para o usuário oracle:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC0nG_xrAgscZAI_3aUIGmen3lfgJYOlStSjLkbuqdcr0fj_cSK-dYT3j6ZIYC7zWlm-oW7ajh6LE8KIuRXcD8vJF9ynq93S8T6Q0XJDIPUzIpP4hEnzziSVkOr5G6AmvNp1c6aH4EQoFi/s1600/image093.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC0nG_xrAgscZAI_3aUIGmen3lfgJYOlStSjLkbuqdcr0fj_cSK-dYT3j6ZIYC7zWlm-oW7ajh6LE8KIuRXcD8vJF9ynq93S8T6Q0XJDIPUzIpP4hEnzziSVkOr5G6AmvNp1c6aH4EQoFi/s1600/image093.png" width="640" /></a><br />
<br />
A última tela é apenas um <i>review</i>. Clique em <b>Deploy Agent</b>.</div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjyz9FCDdQeLfVt-StO1wEoRE-HR9fGj5MMKcjV8nDs3mYQ9bFluT8mblHGC56iysVcKjR3Yni69QGshpMYrKNNkPKB3zobI7pk0ux-EslwiMCP8FyYsqEW4metToPKDveVOdF67T3F_zK/s1600/image095.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjyz9FCDdQeLfVt-StO1wEoRE-HR9fGj5MMKcjV8nDs3mYQ9bFluT8mblHGC56iysVcKjR3Yni69QGshpMYrKNNkPKB3zobI7pk0ux-EslwiMCP8FyYsqEW4metToPKDveVOdF67T3F_zK/s1600/image095.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
O EM12c vai executar os passos de verificação e instalar o agente:<br />
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh84ki0Nv7RnB5TNyz9ZFO2C2y2KxHH6F5pXV9q4pINqJjti0c2tSCJlZignH0iZpQ4KrrnQLZrxdSvZitpSnU49PbC7C36ndVYdKNNYet_zbt8d1XTH57yfxZWhn26W5o8cBM7OhssFDsJ/s1600/image097.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="358" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh84ki0Nv7RnB5TNyz9ZFO2C2y2KxHH6F5pXV9q4pINqJjti0c2tSCJlZignH0iZpQ4KrrnQLZrxdSvZitpSnU49PbC7C36ndVYdKNNYet_zbt8d1XTH57yfxZWhn26W5o8cBM7OhssFDsJ/s1600/image097.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div style="text-align: justify;">
Pronto, o <b>oel.example.com</b> está gerenciado!<br />
<br /></div>
<div>
<h3 style="text-align: justify;">
</h3>
<h3 style="text-align: justify;">
Conclusões</h3>
<div style="text-align: justify;">
<br />
O objetivo deste roteiro era criar uma infra estrutura básica para poder rodar demos do <b>Enterprise Manager 12c Cloud Control</b>. Não se trata de um ambiente <i>production ready</i> em função de algumas simplificações que fizemos na configuração, em especial em termos de segurança, mas é perfeitamente funcional para realizar demos, testes e apresentações.</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Espero que tenham gostado do passo a passo e quaisquer dúvidas fiquem a vontade para postar nos comentários.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-18553338212805912422014-05-30T09:36:00.000-03:002016-07-25T08:53:16.192-03:00Erro silencioso na instalação do client 11.2.0.4 x64 para Windows 7Eu estou montando um ambiente de testes com algumas máquinas virtuais rodando Oracle 11.2.0.4 e me deparei com um erro estranho ao instalar o Oracle client x86-64 no Windows 7: o instalador simplesmente fecha após o termino da checagem de pré-requisitos sem mensagem alguma.<br />
<br />
Após investigar um pouco na internet acabei descobrindo que mais pessoas tiveram problemas similares e parece estar relacionado com o ambiente JRE que vem embutido no instalador. A solução para mim foi utilizar um parâmetro do executável do <i>setup </i>para escolher outro ambiente JRE:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">C:\oracle\winx64_11g_client>setup -jreLoc c:\sqldeveloper\jdk</span><br />
<br />
No caso, utilizei a JDK que vem embutida na última versão do SQL Developer (4.0.2) e aí a instalação funcionou normalmente. Cabe aqui pontuar que testei outras duas JREs que eu tenho instaladas na mesma máquina (1.6.0-71 e 1.7.0-51) e nenhuma das duas funcionou. Como eu não sou especialista em java não sei o que exatamente fez a diferença, mas fica aí o alerta e o <i>workaround</i>.Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-37635653787200674742013-11-19T13:27:00.000-02:002016-07-25T08:54:18.061-03:00Matemática de Ponteiros<div style="text-align: justify;">
Hoje vou tratar de um tema que aflinge a maioria dos programadores iniciantes em C e C++: os malvados ponteiros. O objetivo é fazer uma revisão do assunto tratando algumas propriedades que podem passar despercebidas do iniciado, mas que fazem toda a diferença na hora de compreender aquele "bug maluco" que aparece de vez enquando. Entender a fundo como funcionam os ponteiros pode ser a diferença entre passar dias ou meses debugando um código para nunca achar aquele erro, ou escrever um código menos suceptível a erros logo de cara.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Bom, para começar, o que é um ponteiro afinal? Um ponteiro nada mais é do que uma variável que contém um endereço de memória. O que muda de ponteiro para ponteiro é o significado deste endereço. </div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<div style="text-align: justify;">
O ponteiro é representado pelo símbolo asterísco (*). Também vamos utilizar bastante o operador de endereço (&), que retorna o endereço de memória de uma variável.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Vamos começar com alguns exemplos básicos para ilustrar:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">#include <iostream><iostream></iostream></span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">using namespace std;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">int main()</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">{</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int a = 0; // Declaração de uma variável tipo int</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int *p; // Declaraçào de um ponteiro para uma variável inteira</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> p = &a; // Atribui a p o endereço de a</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << " a = " << a << "\t\t *p = " << *p << endl;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> cout << "&a = " << &a << "\t p = " << p << endl;</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> cout << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A saída esperada deste programa é a seguinte (os endereços vão variar de máquina para máquina):</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> a = 0 *p = 0</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">&a = 0x28fef4 p = 0x28fef4</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
O objetivo deste exemplo é mostrar a operação normal com ponteiros. Na primeira parte, declaramos uma variável inteira "a" inicializada com o valor zero e um ponteiro "p" para um inteiro. Na seqüência, fazemos a atribuição do endereço de "a" ao ponteiro "p". Em seguida, utilizamos a saída padrão para mostrar que "p" e "a" são duas visões do mesmo dado, dadas as seguintes ressalvas:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
1) para enxergarmos o valor armazenado em "a", basta referenciar a variável pelo nome.</div>
<div style="text-align: justify;">
2) para enxergarmos o endereço de "a", precisamos utilizar o operador de endereço &.</div>
<div style="text-align: justify;">
3) para enxergarmos o valor que "p" aponta, precisamos desreferenciar o ponteiro, com o operador *.</div>
<div style="text-align: justify;">
4) para enxergarmos o endereço contido em "p", basta referenciar "p" pelo nome.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Note que, na observação 4, falamos sobre o "endereço <b>contido </b>em p", e não "o endereço <b>de </b>p". Eu fiz essa diferenciação de propósito, pois "p" também é uma variável que está armazenada no seu próprio endereço. Vamos ver o exemplo modificado:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">int main()</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">{</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int a = 0; // Declaração de uma variável tipo int</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int *p; // Declaraçào de um ponteiro para uma variável inteira</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> p = &a; // Atribui a p o endereço de a</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << " a = " << a << "\t\t *p = " << *p << endl;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> cout << "&a = " << &a << "\t p = " << p << endl;</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> cout << endl;</span></div>
<br />
<div style="text-align: justify;">
<b><span style="font-family: Courier New, Courier, monospace;"> cout << "&p = " << &p << endl;</span></b></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Observe a saída:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> a = 0 *p = 0</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">&a = 0x28fefc p = 0x28fefc</span><br />
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"><br /></span>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">&p = </span><b style="font-family: 'Courier New', Courier, monospace; text-align: justify;">0x28fef8</b><br />
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Basicamente, o valor de "p" é o endereço de "a" (0x28fefc), e o endereço de "p" (0x28fef8) é o local da memória onde está guardado este valor.</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Além disso, quando declaramos "p" não atribuímos nenhum valor a ele. Assim como qualquer outra variável declarada sem valor, ele irá conter neste momento um "lixo" qualquer. Considerando que este lixo pode ser um endereço válido, usar este ponteiro sem atribuir-lhe o valor correto pode ter conseqüências catastróficas como os lendários bugs não-determinísticos. Por este motivo, é uma boa prática ao declarar ponteiros sem valor atribuir-lhe o valor zero ou NULL (NULL = 0), pois os sistemas operacionais modernos são capazes de lançar exceções (</span><i style="font-family: inherit;">null pointer exception</i><span style="font-family: inherit;">) quando tentamos acessar o endereço zero, mas eles não necessariamente conseguem diferenciar um endereço "lixo" válido de um endereço "bom" e, acredite, é muito melhor varrer o código em busca de um </span><i style="font-family: inherit;">null pointer exception </i><span style="font-family: inherit;">do que de um erro aleatório.</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">int *p = NULL; // Sempre!</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Uma última observação antes de seguir no tema, ainda dentro da parte básica, é com relação a declaração dos ponteiros. Você observou que o operador * tem duplo significado: se utilizado na declaração da variável, ele nos diz que a variável é um ponteiro, e; se utilizado no escopo do programa, em uma variável de ponteiro, ele nos diz que queremos desreferenciar o ponteiro, ou seja, utilizar o valor para o qual ele aponta, ao invés do seu próprio valor (que é um endereço).</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Agora, pensando nisso, como fazemos para declarar vários ponteiros em uma única linha? Num primeiro momento, pensando em variáveis normais, declaramos assim:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">int a, b, c;</span></div>
<br />
<div style="text-align: justify;">
Então, por conseqüência, declarar ponteiros deve ser igual, certo?</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">int* p, q, r;</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Errado! Na verdade, o operador * faz parte do <b>nome</b> da variável, e não do tipo. Embora seja correto escrever tanto <span style="font-family: Courier New, Courier, monospace;">int* p</span> como <span style="font-family: Courier New, Courier, monospace;">int *p</span> (mudou apenas a posição do espaço), o * é considerado parte do nome e, portanto, a declaração acima irá produzir um ponteiro para um inteiro "p" e duas variáveis inteiras "q" e "r". A declaração correta é:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
int *p, *q, *r;</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Uma forma de demonstrar isto seria com o seguinte código:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">int main() {</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> char* c, d, e;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "sizeof: c = " << sizeof(c) << " d = " << sizeof(d) << " e = " << sizeof(e) << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Saída:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">sizeof: c = 4 d = 1 e = 1</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Escolhi um tipo </span><span style="font-family: Courier New, Courier, monospace;">char </span><span style="font-family: inherit;">desta vez por que com tipos inteiros não veríamos diferenças no </span><span style="font-family: Courier New, Courier, monospace;">sizeof</span><span style="font-family: inherit;">. Uma maneira de corrigir este problema, além de declarar todos os ponteiros com o devido operador *, seria utilizar um </span><span style="font-family: Courier New, Courier, monospace;">typedef</span><span style="font-family: inherit;">:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">typedef char* CharPtr;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">int main() {</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> CharPtr c, d, e;</span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "sizeof: c = " << sizeof(c) << " d = " << sizeof(d) << " e = " << sizeof(e) << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: inherit;">Saída:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">sizeof: c = 4 d = 4 e = 4</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Logo, o </span><span style="font-family: Courier New, Courier, monospace;">typedef </span><span style="font-family: inherit;">garante que todas as variáveis sejam do mesmo tipo.</span></div>
<br />
<div style="text-align: justify;">
</div>
<h2 style="text-align: justify;">
<span style="font-family: inherit;">Equivalência com <i>Arrays</i></span></h2>
<div style="text-align: justify;">
<span style="font-family: inherit;">Antes de entrar mais a fundo nas operações com ponteiros, existe uma última questão de sintaxe que vale a pena ser mencionada: a equivalência com <i>arrays</i>. Um <i>array</i> em C/C++ é declarado da seguinte forma:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">int a[N];</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Onde "a" é o nome do </span><i style="font-family: inherit;">array </i><span style="font-family: inherit;">e "N" é o seu tamanho.</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Uma das propriedades do </span><i style="font-family: inherit;">array </i><span style="font-family: inherit;">é que, se utilizarmos apenas o seu nome, sem um índice referenciado, estamos tratando do endereço do primeiro elemento do </span><i style="font-family: inherit;">array</i><span style="font-family: inherit;">. Veja:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">int main()</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">{</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int a[10] = {0,1,2,3,4,5,6,7,8,9}; // Declaração de uma variável tipo array de int com tamanho 10</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << " a[0] = " << a[0] << "\t\t &a[0] = " << &a[0] << endl;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> cout << " a = " << a << "\t &a = " << &a << endl;</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> cout << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Saída:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> a[0] = 0 &a[0] = 0x28fed8</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> a = 0x28fed8 &a = 0x28fed8</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: inherit;">Na primeira linha pedimos para imprimir o valor do primeiro elemento (a[0]) e o endereço do primeiro elemento (&a[0]). Na linha seguinte, utilizamos duas notações equivalentes: tanto "a" como "&a" trazem o endereço do primeiro elemento.</span></div>
<br />
<h2 style="text-align: justify;">
<span style="font-family: inherit;">Operações com Ponteiros</span></h2>
<div style="text-align: justify;">
<span style="font-family: inherit;">Espero que esteja tudo tranquilo até agora, pois agora vamos entrar na parte mais complexa. Lembra que o valor de um ponteiro é um endereço, certo? Então observe o seguinte:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">int main() {</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int *a = 0;</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> char *b = 0;</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> long long *c = 0;</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> float *d = 0;</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> double *e = 0;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "sizeof:\n a = " << sizeof(a) << " *a = " << sizeof(*a) << endl</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> << " b = " << sizeof(b) << " *b = " << sizeof(*b) << endl</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> << " c = " << sizeof(c) << " *c = " << sizeof(*c) << endl</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> << " d = " << sizeof(d) << " *d = " << sizeof(*d) << endl</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> << " e = " << sizeof(e) << " *e = " << sizeof(*e) << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Saída:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">sizeof:</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> a = 4 *a = 4</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> b = 4 *b = 1</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> c = 4 *c = 8</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> d = 4 *d = 4</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> e = 4 *e = 8</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Ou seja, embora os tipos de dados que estes ponteiros apontem são totalmente distintos, os tamanhos dos ponteiros são exatamente os mesmos: 4 bytes. Isto se deve ao fato de que eu estou compilando este programa em modo 32 bits (4 bytes * 8 bits = 32 bits) e, portanto, todos os endereços estão dentro deste espaço. Note que se estivéssemos compilando em 64 bits, cada ponteiro teria 8 bytes.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Além disso, tanto em 32 bits como 64 bits nós conseguimos endereçar toda a memória como um bloco contínuo, mas se voltarmos um pouco no tempo e pensarmos em programas de 16 bits, isso não é totalmente verdade. Os processadores x86 em modo 16 bits utilizam uma forma mais complexa de endereçamento, composta por segmentos e offsets que compõem um endereço efetivo de 24 bits. Não vou entrar no detalhe, mas fica aqui como uma curiosidade para quem quiser pesquisar um pouco mais.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para começar a trabalhar com operações em ponteiros, vamos trabalhar com a associação com <i>arrays</i>, pois desta forma estaremos trabalhando dentro de um espaço válido de endereçamento. Estas operações são possíveis em qualquer ponteiro, mas lembre-se sempre que a responsabilidade destas operações é totalmente do programador, o compilador não tem como checar se os limites estão sendo respeitados ou não, e bugs bizarros podem acontecer. Usando o <i>array </i>sabemos que temos o controle dos endereços de memória dentro daquela faixa.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A primeira operação é a adição:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">int main() {</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int a[10] = {0,1,2,3,4,5,6,7,8,9};</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> int *p = a;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "p = " << p << " *p = " << *p << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> p = p + 1;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "p = " << p << " *p = " << *p << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Saída:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">p = 0x28fed4 *p = 0</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">p = 0x28fed8 *p = 1</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: inherit;">Note que somar 1 ao ponteiro não somou 1 ao <b>endereço</b> do ponteiro, mas sim 4. Por quê? Porque o compilador sabe que aquele ponteiro aponta para um inteiro que ocupa 4 bytes, e ao somar 1 você está pedindo para o compilador que quer o <b>próximo</b> elemento alinhado com aquele ponteiro.</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Por exemplo, se fizessemos o mesmo com um tipo </span><b style="font-family: inherit;">char</b><span style="font-family: inherit;">:</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;">int main() {</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> char a[10] = {'0','1','2','3','4','5','6','7','8','9'};</span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> char *p = a;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "p = " << (void*) p << " *p = " << *p << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> p = p + 1;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "p = " << (void*) p << " *p = " << *p << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: inherit;">Saída:</span></div>
<br />
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">p = 0x28fef2 *p = 0</span><br />
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">p = 0x28fef3 *p = 1</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A diferença entre os endereços é apenas 1 byte, ou o tamanho do <b>char</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Que outras operações são válidas em ponteiros? Basicamente todas operações relacionadas a adição e subtração:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">int main() {</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int a[10] = {0,1,2,3,4,5,6,7,8,9};</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> int *p = a;</span></div>
<br />
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> cout << "p = " << p << " *p = " << *p << endl;</span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> p++;</span><br />
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> ++p;</span><br />
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "p = " << p << " *p = " << *p << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> p--;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> p -= 1;</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> p += 3;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "p = " << p << " *p = " << *p << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Saída:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">p = 0x28fed4 *p = 0</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">p = 0x28fedc *p = 2</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">p = 0x28fee0 *p = 3</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Sempre observando que o tamanho da variável apontada pelo ponteiro tem efeito direto nos cálculos dos endereços.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Note que, o endereço de um elemento "N" no <i>array </i>será sempre:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
e = e0 + N * sizeof(T)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Onde "e0" é o endereço inicial do <i>array </i>e "T" é o tipo de dado do <i>array</i>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Seguindo esta lógica, podemos ver que o operador [] nada mais é do que um operador de endereçamento, que abstrai estes cálculos para o programador.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para testar assertiva, vamos fazer o seguinte (cuidado!):</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">int main() {</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> int *p = 0;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> cout << "&p[1] = " << &p[1] << endl;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;"> cout << "&p[2] = " << &p[2] << endl;</span><br />
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> cout << "&p[3] = " << &p[3] << endl;</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;"> cout << "&p[4] = " << &p[4] << endl;</span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace;"> return 0;</span></div>
<span style="font-family: 'Courier New', Courier, monospace; text-align: justify;">}</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Saída:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">&p[1] = 0x4</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">&p[2] = 0x8</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">&p[3] = 0xc</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">&p[4] = 0x10</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Note que mesmo declarando a variável "p" como um ponteiro (e não um <i>array</i>), podemos utilizar normalmente o operador []. O importante aqui é ressaltar que embora o programa tenha calculado os endereços corretamente, qualquer tentativa de acessar este espaço de memória pode ser desastrosa (por isso estou apenas imprimindo os endereços, não faço nenhum acesso a valor), logo, todo cuidado é pouco!</div>
<div style="text-align: justify;">
<br /></div>
<h2 style="text-align: justify;">
Conclusões</h2>
<div style="text-align: justify;">
O meu objetivo com este artigo era fazer um panorama geral de operações com ponteiros. Eu acredito que uma vez que fique claro que trabalhando com ponteiros estamos trabalhando com endereços de memória grande parte da "mística" que envolve os ponteiros se desfaz e eles deixam de ser instrumentos obscuros para se tornarem ferramentas poderosas para o programador.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Como nota mental, fico devendo alguns tópicos interessantes para uma próxima edição deste artigo: chamadas de funções com ponteiros, <i>arrays</i> de <i>arrays </i>e ponteiros de funções.</div>
<div style="text-align: justify;">
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-10855892071741860822013-11-18T13:22:00.000-02:002016-07-25T08:56:12.521-03:00A máquina do tempo (para a internet)<div style="text-align: justify;">
A inspiração de escrever este post veio do seguinte video:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<iframe allowfullscreen="" frameborder="0" height="360" src="//www.youtube.com/embed/TOFgDSqNRz4?feature=player_embedded" width="640"></iframe></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Basicamente, é uma apresentação de 10 minutos sobre como obter informações históricas da internet como tendências, métricas e etc, a partir de duas tecnologias: o <a href="http://httparchive.org/" target="_blank">HTTP Archive</a> e o <a href="https://developers.google.com/bigquery/" target="_blank">Big Query</a>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Isso me lembrou um "recurso" da internet que pouca gente conhece, e que por sinal é o irmão mais velho do HTTP Archive: o <a href="https://archive.org/" target="_blank">Internet Archive</a>, mais especificamente a <a href="https://archive.org/web/" target="_blank">Wayback Machine</a>. Enquanto o HTTP Archive tem o objetivo de armazenar, basicamente, metadados sobre as páginas da internet, a Wayback Machine armazena páginas da web completas. Ou seja, é possível, através de uma consulta a Wayback Machine, visualizar uma página hoje como ela era há anos atrás.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
A Wayback Machine existe desde 1996 e têm algumas páginas realmente antigas. Por exemplo, eu consegui achar minha lista de item da minha antiga coleção de video games (que infelizmente não existe mais) com um snapshot de 2004:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://web.archive.org/web/20041205164042/http://www.swi.com.br/~celsius/">https://web.archive.org/web/20041205164042/http://www.swi.com.br/~celsius/</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Porém, se eu for mais para trás, consigo achar versões dela até 1999! Além disso, domínios mortos também podem ser vistos... o próprio SWI onde eu hospedava esta listagem não existe mais. Alguns sítios muito conhecidos e usados no passado como GeoCities e NBCI também podem ser acessados... é literalmente um museu em forma online, o que não poderia ser mais apropriado para a internet! :)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Agora, uma coisa que me deixa intrigado é, se existe uma forma de consolidar o Big Query com o HTTP Archive, será que não existiria uma forma de fazer o mesmo com o Internet Archive? Ou seja, pegar os dados históricos da Internet nos últimos 17 anos (1996-2013) e fazer análises (Hadoop?) para extrair dados históricos sobre a evolução da internet como um todo? Pelo que eu vi a facilidade de fazer isso com o Big Query se deve ao fato de que os dados do HTTP Archive já estão estruturados em bases MySQL (o Biq Query roda uma versão customizada do MySQL pelo Google), porém não encontrei uma forma de fazer o mesmo com a Wayback Machine, imagino que os dados não estejam realmente disponibilizados em nenhum formato similar, embora existam algumas APIs para consultas:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://archive.org/help/wayback_api.php">https://archive.org/help/wayback_api.php</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Enfim, fica aí um desafio para as próximas gerações... eu particularmente adoraria meter a mão na massa num projeto de pesquisas desse, mas infelizmente no momento tenho outras prioridades. Quem sabe um dia. De qualquer forma, fica aí a dica para quem quiser dar uma espiada no passado da web.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-7559556184766421012013-11-13T14:48:00.002-02:002016-07-25T09:20:46.593-03:00Estruturas de Dados - Listas EncadeadasEu estou atualmente estudando uma série de principios básicos da engenharia de software em geral, començando desde estruturas de dados e algorítmos até conceitos mais complexos como inteligência artificial e programação de sistemas.<br />
<br />
Para aproveitar esta nova tendência, estou abrindo uma nova série de artigos, focando inicialmente em Estruturas de Dados e, futuramente, devo abordar outros temas seguindo esta linha. A idéia é, na verdade, ser menos conceitual e focar mais nos aspectos de implementação de cada estrutura.<br />
<br />
Como linguagem de programação estou escolhendo o C++, por questões de familiaridade. Também vou optar por trabalhar com programação genérica (templates) sempre que possível. Como eu sou <i>old school </i>e fiquei algum tempo sem programar, ainda não me adaptei ao C++11, então a maioria dos meus códigos é baseada no C++98. Pretendo utilizar novas <i>features</i> do C++11 a medida que eu for dissecando cada uma delas.<br />
<br />
Como IDE e compilador estou utilizando o Code::Blocks com gcc para Windows. Por questões particulares estou sem acesso a um Linux neste momento, mas apenas para ficar registrado, minha preferência pessoal sempre foi pelos <i>Debian</i>-like, como por exemplo, o Ubuntu, embora a interface Unity não me agrada muito e por isso troquei pelo Mint.<br />
<br />
Em termos de padrão de codificação, estou procurando seguir o mais próximo possível o <a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml" target="_blank">Google C++ Style Guide</a>. Digo o mais próximo possível porque ainda não tenho o domínio completo deste estilo e alguns hábitos são difíceis de se perder. Mas estou me esforçando neste caminho.<br />
<br />
Bom, chega de preeliminares, vamos ao que interessa: listas encadeadas!<br />
<br />
<h2>
Listas Encadeadas</h2>
<div>
<br /></div>
<div>
Listas Encadeadas são estruturas de dados dedicadas para o armazenamento de listas maneira análoga ao <i>array</i>, nativo da maioria das linguagens de programação, porém com algumas características particulares. O <i>array</i>, por definição, é uma coleção de valores de um mesmo tipo de variável num espaço contiguo de memória. Já a lista encadeada, por sua vez, não necessita uma alocação necessariamente contigua, embora possa ser. </div>
<div>
<br /></div>
<div>
O principio básico de uma lista encadeada é ser uma estrutura de dados onde cada elemento possui (pelo menos) um indice, ponteiro ou referência para o seu sucessor. As listas encadeadas podem ser tanto estáticas como dinâmicas, sendo que as listas estáticas tem um tamanho pré-definido no momento de sua alocação e geralmente são implementadas com <i>arrays</i>.</div>
<div>
<br /></div>
<div>
As listas dinâmicas, por sua vez, possuem a capacidade de alocar memória para os novos elementos sob demanda, bem como liberar memória toda vez que um elemento é apagado. Logo, elas possuem a vantagem de não necessitarem alocar toda a memória no seu primeiro uso e o programador não precisa conhecer o seu tamanho máximo no momento da compilação.</div>
<div>
<br /></div>
<div>
Neste artigo vou tratar especificamente das listas encadeadas dinâmicas, pois vejo pouca vantagem de listas encadeadas estáticas com relação aos <i>arrays</i>, tirando o aspecto didático.</div>
<div>
<br /></div>
<div>
A implementação mais simples de uma lista encadeada dinâmica é a seguinte:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">struct ListNode {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> ListNode* next_;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> void* data_;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: inherit;">Neste caso estamos assumindo uma implementação com ponteiros, sendo <b>next_</b> o ponteiro para o próximo nó e <b>data_ </b>o conteúdo do nó. </span>Claro que nesta estrutura minimalista não estamos considerando as funções para realizar as operações na lista, as quais numa linguagem estruturada como o C justamente implementamos como funções isoladas. </div>
<div>
<br /></div>
<div>
No C++, com a facilidade de se trabalhar com classes, é muito comum implementarmos as listas como "listas gerenciadas" (std::list é um exemplo de lista gerenciada), onde uma classe <i>manager</i> engloba todas as funções e controles necessários para manter a lista, abstraindo o que muitas vezes é uma interface complexa.</div>
<div>
<br /></div>
<div>
Uma última classificação sobre listas encadeadas dinâmicas é que elas podem ser simples, ou duplamente encadeadas. Listas simples permitem navegação unidirecional, de <i>head</i> para <i>tail</i>, enquanto que as listas duplamente encadeadas permitem navegação bidirecional. Neste primeiro artigo iremos começar com a lista simples, deixando a lista dupla para futuros artigos.</div>
<div>
<br /></div>
<div>
Uma implementação minimalista da classe gerenciadora segue abaixo:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">struct List {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> List() : head_(NULL) {}</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> ~List() {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> while( head_ ) { </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> ListNode* del_me = head_;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> head_ = head_->next_;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> delete del_me;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> void PushBack(ListNode* node) {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> if( !head_ )</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> head_ = node;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> else {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> </span><span style="font-family: 'Courier New', Courier, monospace;">ListNode* i = head_</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> for(; i->next_; i = i->next_) {</span><span style="font-family: 'Courier New', Courier, monospace;">}</span></div>
<div>
<span style="font-family: 'Courier New', Courier, monospace;"> i->next_ = node;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> ListNode* head_;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">};</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
Note que estamos tratando apenas a inserção de elementos no fim da lista, utilizando o método PushBack. Além disso, uma vez inserido o elemento na lista estamos passando o <i>ownership </i>do objeto ListNode para a lista, ou seja, cabe a lista, em seu destrutor, liberar a memória alocada para os nós. Em um <i>list manager</i> mais robusto, normalmente não queremos tratar a inserção a nível de ListNode, mas sim queremos inserir diretamente o tipo de dado que a lista armazena, como exemplo do push_back() da std::list. Veremos isto mais adiante na implementação.</div>
<div>
<br /></div>
<div>
Antes de partir para a implementação propriamente dita gostaria de comentar sobre algumas características das listas encadeadas dinâmicas em comparação com os <i>arrays</i>.</div>
<div>
<br /></div>
<div>
O primeiro ponto é a performance de busca. Em um <i>array</i>, por se tratar de uma área de memória contigua, a busca de um elemento pelo seu índice é uma operação de tempo constante, ou O(1) em notação <i>big-O.</i> Já numa lista encadeada é uma operação O(n), pois dado uma posição i precisamos partir do nó <i>head</i> e varrer i elementos para encontrar o nosso candidato (considerando o <i>head</i> como i = 0). No <i>array </i>essa indexação é direta, pois, supondo uma posição i, o endereço de memória do elemento alvo pode ser calculado facilmente pela equação <i>endereco = &array + </i><i>i * sizeof( array[0] ). </i>Nota:<i> </i>Este cálculo é feito automaticamente quando utilizamos a notação de <i>arrays</i>: a[i].</div>
<div>
<br /></div>
<div>
Nos <i>arrays</i>, a inserção também é uma operação em tempo constante O(1), porém não existe um mecanismo nativo para deleção, pois uma vez alocado o espaço ele fica alocado até sair de escopo. Isto geralmente implica em algum tipo de controle adicional caso haja necessidade de representar espaços em branco no <i>array, </i>o que se for o caso pode ser obtido em tempo constante O(1) (por exemplo, atribuir um valor -1 em um array onde se espera apenas números inteiros positivos). Nas listas encadeadas tanto a inserção como a deleção são O(n), pelo mesmo motivo da busca, e a deleção de fato ocorre liberando memória.</div>
<div>
<br /></div>
<div>
Finalmente, uma busca por valor tem performance de O(n) em ambos os casos, pois sempre haverá necessidade de percorrer toda a lista ou todo o <i>array </i>no pior caso.</div>
<div>
<br /></div>
<h2>
Implementação de uma Lista Encadeada Dinâmica</h2>
<div>
A implementação de lista dinâmeica completa está disponível em <a href="https://gist.github.com/danicat/7049073">https://gist.github.com/danicat/7049073</a>. Vou comentar passo a passo esta implementação.</div>
<div>
<br />
<span style="font-family: Courier New, Courier, monospace;">template<class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">class Element {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> public:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element(const T& value) : data_(value), next_(NULL) {}</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ~Element() {}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> void SetValue(const T& value) { data_ = value; }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> const T& GetValue() const { return data_; }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> void SetNext(Element<T>* next) { next_ = next; }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* GetNext() const { return next_; }</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> void Print() const { std::cout << data_ << std::endl; }</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> private:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element(); // Prevent calling the default ctor</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> T data_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* next_;</span><br />
<span style="font-family: Courier New, Courier, monospace;">};</span><br />
<br /></div>
Primeiro nós definimos o elemento ou nó que irá armazenar os valores. Se comparado com a nossa implementação minimalista logo acima pouco mudou: adicionou-se o construtor e destrutor, os métodos getters e setters para as propriedades do elemento e um método Print() para fins diagnósticos.<br />
<br />
Outra mudança, esta sim significativa, foi a abstração do elemento utilizando um template. Esta é uma abordagem mais eficaz do que definir o dado como um void* como fizemos na implementação minimalista. Também declarou-se o construtor padrão como privado, para evitar uma construção de um elemento sem conteúdo.<br />
<br />
Em seguida, define-se a classe <i>manager</i> que irá concentrar todas as funcionalidades da lista:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">class List {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> public:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> List(): head_(NULL), tail_(NULL) {}</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ~List();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> bool PushFront(const T& value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bool PushBack (const T& value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bool PopFront(T* value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bool PopBack (T* value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> int Length() const;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> void Print() const;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> bool Insert(const T& value, const int& position);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bool Delete(const int& position);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> int Find(const int& value) const;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bool Get (const int& position, T* value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> private:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* tail_;</span><br />
<span style="font-family: Courier New, Courier, monospace;">};</span><br />
<br />
Esta classe também pode ser chamada de <i>container</i>, pois ela contém os elementos da lista. A principio ela só precisaria de ter um ponteiro para o primeiro elemento da lista, o <i>head_</i>, porém, uma otimização comum é também manter um ponteiro para o final da lista, o <i>tail_.</i> No estando inicial ambos os ponteiros são nulos e a lista está vazia. A medida que são inseridos e removidos elementos na lista, estes ponteiros precisam ser atualizados.<br />
<br />
As primeiras operações implementadas são as operações Push() e Pop(). Estas operações para quem já estudou pilhas são bem familiares. Push() é a operação de colocar um valor numa pilha, e Pop() é a operação de retirar. Operações em pilhas sempre são feitas em uma das suas extremidades, mas como estamos tratando de listas e não pilhas é conveniente utilizar a mesma analogia para inserir e retirar elementos das extermidades. Logo, PushFront() e PopFront() vão inserir e retirar elementos do começo da lista, respectivamente, e PushBack() e PopBack() vão inserir e retirar elementos do fim da lista.<br />
<br />
Esta implementação de caso particular é interessante porque são funções de uso bastante comum. Muitas vezes não queremos nos preocupar com a ordem dos elementos que estamos inserindo, queremos apenas extender a lista, situação em que um PushBack(), por exemplo, pode vir bem a calhar.<br />
<br />
Em termos de performance, como mantemos um ponteiro para o <i>tail </i>da lista, inserir um elemento no fim da lista é uma operação de tempo constante, ou seja, O(1). O mesmo vale para inserir e remover elementos do começo da lista, pois operações no <i>head </i>também são tempo constante (Se não ficar claro o porque disto agora, talvez na implementação abaixo faça sentido). A única operação O(n) seria retirar um elemento do fim da lista, pois, precisamos atualizar o <i>tail </i>para o elemento <i>tail </i>- 1, mas não conseguimos saber qual elemento aponta para <i>tail </i>sem varrer toda a lista. Note que isto é uma ressalva apenas para listas simples, numa lista duplamente encadeada poderiamos partir do <i>tail</i> e encontrar o <i>tail - 1</i> em tempo constante através do ponteiro de iteração reversa.<br />
<br />
Segue a implementação das rotinas push e pop:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">// O(1)</span><br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">bool List<T>::PushFront(const T& value) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* element = new( std::nothrow ) Element<T>(value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( element ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( !head_ ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> // Special case, list is empty</span><br />
<span style="font-family: Courier New, Courier, monospace;"> head_ = element;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_ = element;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> element->SetNext(head_);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> head_ = element;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // Error allocating memory</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">// O(1)</span><br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">bool List<T>::PushBack(const T& value) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* element = new (std::nothrow) Element<T>(value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( element ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( !head_ ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> // Special case, list is empty</span><br />
<span style="font-family: Courier New, Courier, monospace;"> head_ = element;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_ = element;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_->SetNext(element);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_ = element;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">// O(1)</span><br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">bool List<T>::PopFront(T* value) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( value && head_ ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> *value = head_->GetValue();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* new_head = head_->GetNext();</span><br />
<span style="font-family: Courier New, Courier, monospace;"> delete head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> head_ = new_head;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // Error: nullptr passed as parameter or list empty</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">// O(n)</span><br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">bool List<T>::PopBack(T* value) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( value && tail_ ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> *value = tail_->GetValue();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> // Special case: one element list</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( head_ == tail_ ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> delete head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> head_ = NULL;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_ = NULL;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* new_tail;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> new_tail = head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> while( new_tail->GetNext() != tail_ ) // Skip elements till the element before tail</span><br />
<span style="font-family: Courier New, Courier, monospace;"> new_tail = new_tail->GetNext();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> new_tail->SetNext(NULL);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> delete tail_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_ = new_tail;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // Error: nullptr passed as parameteror list empty</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<br />
Em seguida temos algumas funções auxiliares, também de ordem O(n), Lenght() que retorna o tamanho da lista e Print() que imprime os valores da lista. Estas são operações O(n) porque não há outra forma de realizá-las sem varrer todos os elementos da lista.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">// O(n)</span><br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">void List<T>::Print() const {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* e;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> for(e = head_; e; e = e->GetNext() )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> e->Print();</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: 'Courier New', Courier, monospace;">// O(n)</span><br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">int List<T>::Length() const {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* e;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> int count = 0;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> for(e = head_; e; e = e->GetNext() ) ++count;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> return count;</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
Note que uma otimização simples de Lenght() seria criar uma propriedade <i>lenght </i>no <i>container </i>e fazer com que todas as operações de inserção e remoção da lista incrementassem ou decrementassem este contador. Porém, dada a quantidade de operações que podem inserir ou remover elementos, tornaria-se uma otimização um pouco mais complicada de se manter, o que poderia induzir <i>bugs</i>. <br />
<br />
Estou fazendo este comentário aqui porque, embora este seja um exercício conceitual, num código comercial decisões como esta podem afetar o esforço de manutenção do código drasticamente. Imagine, por exemplo, quantas vezes esta função vai ser chamada no código final e se vale a pena sacrificar a clareza do código em prol desta otimização. Esta é uma reflexão que deve acompanhar todas as decisões de <i>design </i>envolvendo otimizações.<br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">A próxima operação, Insert(), é uma que demanda uma certa atenção, pois estamos trabalhando com inserção posicional.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">// best O(1), avg O(n), wst O(n)</span><br />
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">bool List<T>::Insert(const T& value, const int& position) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( position < 0 )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( !position ) // Special case: position = 0, insert into head</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return PushFront(value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* element_before = head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> for(int count = 0; count < position - 1; ++count ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> element_before = element_before->GetNext();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( !element_before )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // Out of bounds</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* new_element = new (std::nothrow) Element<T>(value);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( !new_element )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> new_element->SetNext(element_before->GetNext());</span><br />
<span style="font-family: Courier New, Courier, monospace;"> element_before->SetNext(new_element);</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( element_before == tail_ ) // Special case: insert at the end</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_ = new_element;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Como era de se esperar, esta operação tem um <i>best case</i> O(1), pois inserir um elemento na posição zero se reduz a fazer uma chamada ao método PushFront(). O<i> average case</i> e <i>worst case</i> são ambos O(n), pois para as demais operações é preciso varrer toda a lista. Se soubessemos o tamanho da lista com antecedência poderiamos prever tentativas de inserir após o fim da lista em tempo constante, e também inserir no fim da lista em tempo constante, porém para isso temos que varrer toda a lista de qualquer forma chamando a função Length(), que tem tempo O(n).</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Portanto, tomamos o cuidado de varrer a lista procurando a posição especificada mas sempre checando se não estamos ultrapassando o limite, situação que deve retornar erro.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">O mesmo vale para a operação Delete():</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">bool List<T>::Delete(const int& position) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( position < 0 )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( !head_ )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // List empty</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* target = head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( !position ) {// Special case: position = 0, delete head</span><br />
<span style="font-family: Courier New, Courier, monospace;"> head_ = head_->GetNext();</span><br />
<span style="font-family: Courier New, Courier, monospace;"> delete target;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* element_before = head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> for(int count = 0; count < position - 1; ++count ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> element_before = element_before->GetNext();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( !element_before )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // Out of bounds</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> target = element_before->GetNext();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( !target )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // Out of bounds</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> element_before->SetNext(target->GetNext());</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( target == tail_ )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> tail_ = element_before;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> delete target;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: inherit;">Finalmente, as funções Find(), para buscar a posição de um valor na lista e, Get(), para retornar o valor em uma dada posição:</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">int List<T>::Find(const int& value) const {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> int position = -1;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* e = head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> for(int count = 0; e; e = e->GetNext(), ++count ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( e->GetValue() == value ) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> position = count;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> break;</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"> }</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> return position;</span><br />
<span style="font-family: Courier New, Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">template <class T></span><br />
<span style="font-family: Courier New, Courier, monospace;">bool List<T>::Get(const int& position, T* value) {</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if( position < 0 || !value )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true; // invalid input</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> Element<T>* e = head_;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> for(int count = 0; e && count < position; e = e->GetNext(), ++count ) ;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if( !e )</span><br />
<span style="font-family: Courier New, Courier, monospace;"> return true;</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> *value = e->GetValue();</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> return false;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: inherit;">Ambas são operações O(n) para <i>average </i>e <i>worst case</i>, pois necessitam varrer a lista para encontrar os respectivos valores.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Claro que esta implementação não é exaustiva, e algumas simplificações e omissões foram feitas para torná-la mais didática. Na prática, estaríamos trabalhando preferencialmente com uma lista duplamente encadeada. Além disso, para ser um verdadeiro <i>container</i> comparável aos fornecidos pela biblioteca padrão, no mínimo deveríamos definir semânticas de cópia, <i>move</i>, atribuição e implementar operadores comuns como o de indexação [].</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Enfim, espero que estes comentários ajudem, e na próxima vez pretendo dar continuidade ao assunto tratando de outras estruturas de dados.</span>Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-54426096538820287262013-06-27T10:05:00.000-03:002016-07-25T09:20:06.214-03:00Utilizando a compressão de índices no Oracle<div style="text-align: justify;">
Eu preparei recentemente este <i>test case</i> para mostrar o funcionamento da <b>compressão de índices</b> para um de nosso clientes e achei interessante compartilhá-lo, pois eu sei que esta é uma <i>feature</i> que é muito pouco utilizada por aqui e isso se deve de maneira geral pela falta de conhecimento de sua existência ou do seu funcionamento.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Também devemos levar em conta que é muito comum encontrarmos na prática bancos onde a área alocada para índices é igual ou até mesmo maior que a área de dados. Empregando a compressão de índices conseguimos em média uma economia de 20% de área de <i>storage</i>. Se colocar isso dentro de um contexto onde hoje busca-se reduzir custos ao máximo, aumentar a longevidade do <i>hardware</i>, reduzir o TCO, obter uma melhor performance... não existe motivo para não utilizar uma tecnologia que está ali a disposição que pode auxiliar em todos estes quesitos.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Além de mostrar como a compressão funciona, a idéia é criar uma metodologia para automatizar a seleção dos candidatos, pois o próprio Oracle consegue nos dar todas as informações que precisamos com relação ao melhor nível de compressão que podemos obter.</div>
<div style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Primeiro vamos comentar algumas caracteri</span>sticas básicas:</div>
</div>
<ul>
<li style="text-align: justify;"><span lang="PT-BR" style="text-indent: -18pt;">A
compressão de indices é uma <i>feature</i> padrão do Oracle, não necessita de
licenciamento especial, estando inclusive habilitada no Oracle <i>standard</i>.</span></li>
<li style="text-align: justify;"><span lang="PT-BR" style="text-indent: -18pt;">Esta
compressão se baseia na compressão de repetições dentro da estrutura da arvore
binária, portanto é altamente dependente da ordem das colunas</span></li>
<li style="text-align: justify;"><span lang="PT-BR" style="text-indent: -18pt;">Em
função da característica acima, indices que começam com uma coluna única não
conseguem ser comprimidos</span></li>
</ul>
<div style="text-align: justify;">
Para
estimar a compressão de um indice existe uma metodologia bem prática. Vamos por
partes.</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">O comando
ANALYZE INDEX ... VALIDATE STRUCTURE popula uma view chamada INDEX_STATS. Esta
view sempre irá conter um indice por vez, ou seja, cada vez que você executar o
VALIDATE STRUCTURE seu conteúdo é apagado e populado com os dados do indice
solicitado.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Estamos
interessados em duas colunas desta view: OPT_CMPR_COUNT e OPT_CMPR_PCTSAVE.
OPT_CMPR_COUNT é o número ideal de colunas que deve ser especificado no momento
da compressão. OPT_CMPR_PCTSAVE é o ganho esperado com a compressão utilizando
o número recomendado de colunas.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Uma vez
determinado o número de colunas, para executar a compressão é bem simples:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR"><span style="font-family: "courier new" , "courier" , monospace;">ALTER INDEX
... REBUILD COMPRESS n</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Onde ‘n’ é
o número de colunas indicado por OPT_CMPR_COUNT.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Considerando
isso que foi dito acima, eu criei uma package que possui duas procedures: uma
para analisar todos os indices do usuário atual e a outra para executar a
compressão de acordo com o indice recomendado. O test case completo está em
anexo (pronto para rodar com um @ do sqlplus), vou comentando abaixo:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Primeiro
vou criar uma tabela com 1.000.000 linhas para servir de massa de dados:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">create table t(pedido primary key, produto, cliente,
dt_pedido) as<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">select rownum
pedido, <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;"> mod(rownum,
1000) produto, <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;"> mod(rownum,
100) cliente,<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;"> sysdate +
mod(rownum, 100) dt_pedido <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> from
dual connect by level <= 1000000;</span><span style="font-family: "courier new";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Note que
com essa sintaxe eu garanto que todo pedido é unico (numero sequencial) e que
tenho 1000 produtos distintos e 100 clientes.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Em seguida
vou criar uma série de indices, tentando imitar as características de uma
aplicação convencional:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">create index t_idx1
on t(pedido, produto, cliente);<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">create index t_idx2
on t(produto, cliente);<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">create index t_idx3 on t(produto, cliente, dt_pedido);<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">create index t_idx4 on t(cliente, produto, pedido);<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">create index t_idx5
on t(cliente);</span><span style="font-family: "courier new";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Com o
modelo pronto, vou criar agora as ferramentas para trabalhar com a compressão.
Como a view INDEX_STATS é volátil, eu vou criar uma cópia dela chamada
IDX_STATS:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">create table idx_stats as<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new"; mso-ansi-language: PT-BR;"><span style="font-family: "courier new" , "courier" , monospace;">select * from index_stats;</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Depois
criamos a package responsável pela estimativa e compressão:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">create or replace
package pkg_idx_compress as<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";"> procedure
idx_compress_analyze;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";"> procedure
idx_compress_execute(pctsave number default 10);<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">end
pkg_idx_compress;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">/<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">create or replace
package body pkg_idx_compress as<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">procedure
idx_compress_analyze as<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">begin<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> for r in
(select user as owner, <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> index_name
<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> from
user_indexes)<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> loop<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">
execute immediate 'analyze index ' || r.owner || '.' || r.index_name || '
validate structure';<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">
insert into idx_stats select * from index_stats;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> end loop;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> commit;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">end
idx_compress_analyze;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">procedure
idx_compress_execute(pctsave number default 10) as<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">begin<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> for r in
(select user as owner, name, opt_cmpr_count from idx_stats where
opt_cmpr_pctsave >= pctsave)<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> loop<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> execute
immediate 'alter index ' || r.owner || '.' || r.name || ' rebuild compress ' ||
r.opt_cmpr_count;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> end loop;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">end
idx_compress_execute;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">end pkg_idx_compress;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new"; mso-ansi-language: PT-BR;"><span style="font-family: "courier new" , "courier" , monospace;">/</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Note que a
procedure idx_compress_analyze simplesmente chama a ANALYZE INDEX VALIDATE
STRUCTURE uma vez para cada indice do usuário e guarda uma cópia da informação
na tabela IDX_STATS. A procedure idx_compress_execute irá varrer a tabela
IDX_STATS em busca de indices que tenham uma estimativa de melhoria maior ou
igual a 10%, ou o valor especificado.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Tendo todas
as ferramentas na mão podemos analisar o cenário antes e depois da compressão:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">SQL> select
table_name, index_name, bytes / 1024 as kbytes<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">
2 from user_indexes ui,<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">
3 user_segments us<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";"> 4
where ui.index_name = us.segment_name;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">TABLE_NAME
INDEX_NAME KBYTES<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">------------------------------
--------------- ----------<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX4
26624<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
SYS_C0012678 17408<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX1
26624<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX2
20480<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX3
29696<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX5
16384<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new"; mso-ansi-language: PT-BR;"><span style="font-family: "courier new" , "courier" , monospace;">6 linhas selecionadas.</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Executando
a estimativa:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">SQL> exec pkg_idx_compress.idx_compress_analyze;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new"; mso-ansi-language: PT-BR;"><span style="font-family: "courier new" , "courier" , monospace;">Procedimento PL/SQL concluído com sucesso.</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">SQL> select user
as owner,<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">
2 name as index_name,<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">
3 opt_cmpr_count,<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">
4 opt_cmpr_pctsave<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new";">
5 from idx_stats;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">OWNER
INDEX_NAME OPT_CMPR_COUNT
OPT_CMPR_PCTSAVE<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">---------- --------------- --------------
----------------<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">DANI SYS_C0012678
0
0<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">DANI T_IDX1
0
0<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">DANI T_IDX2
2
38<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">DANI T_IDX3
3
57<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">DANI T_IDX4
2
29<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new" , "courier" , monospace; mso-ansi-language: PT-BR;">DANI T_IDX5
1
21<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new"; mso-ansi-language: PT-BR;"><span style="font-family: "courier new" , "courier" , monospace;">6 linhas selecionadas.</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Note que tanto
o indice SYS_C0012678 (que é a nossa PK) como o indice T_IDX1 que possui a
coluna pedido como primeira coluna tem estimativa zero. Isso se deve ao fato da
questão da repetição que eu falei. Os demais apresentam bons indices de
compressão esperados em função da grande quantidade de repetição.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Agora,
vendo o resultado na prática:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">SQL> exec
pkg_idx_compress.idx_compress_execute;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new"; mso-ansi-language: PT-BR;"><span style="font-family: "courier new" , "courier" , monospace;">Procedimento PL/SQL concluído com sucesso.</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">SQL> select
table_name, index_name, bytes / 1024 as kbytes<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">
2 from user_indexes ui,<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">
3 user_segments us<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"> 4
where ui.index_name = us.segment_name;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">TABLE_NAME
INDEX_NAME KBYTES<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">------------------------------
--------------- ----------<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX4
18432<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
SYS_C0012678 17408<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX1
26624<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX2
13312<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX3
13312<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">T
T_IDX5
13312<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: "courier new"; mso-ansi-language: PT-BR;"><span style="font-family: "courier new" , "courier" , monospace;">6 linhas selecionadas.</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">No fim das
contas houve uma pequena diferença com relação ao estimado, mas dá para ver que
a compressão indicada foi bem eficiente.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Claro que
trata-se de um caso artificial, mas na minha vida de DBA eu já utilizei
estratégias similares com bons resultados. Inclusive esse procedimento pode ser
feito online.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR">Para
finalizar, segue o trecho do manual que trata de compressão de indices
(extraido de <a href="http://docs.oracle.com/cd/E11882_01/server.112/e17118/statements_1010.htm">http://docs.oracle.com/cd/E11882_01/server.112/e17118/statements_1010.htm</a>):<o:p></o:p></span></div>
<div style="text-align: justify;">
<span lang="PT-BR"><br /></span></div>
</div>
<div class="subhead2">
<div style="text-align: justify;">
<b><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" name="BABHFFHI"></a><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" name="SQLRF52764"></a><span class="italic1"><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;">key_compression</span></span></b><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;"> <a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2854" name="sthref2854"></a><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2855" name="sthref2855"></a><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2856" name="sthref2856"></a><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2857" name="sthref2857"></a><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2858" name="sthref2858"></a><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2859" name="sthref2859"></a><o:p></o:p></span></div>
<div style="text-align: justify;">
<b><span class="italic1"><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;"><br /></span></span></b></div>
</div>
<div style="text-align: justify;">
<span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;">Specify </span><code><span lang="EN" style="color: #222222; font-size: 11.0pt;">COMPRESS</span></code><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;"> to enable key compression, which eliminates repeated
occurrence of key column values. Use </span><span class="codeinlineitalic1"><span lang="EN" style="color: #222222; font-family: "courier new"; font-size: 11.0pt;">integer</span></span><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;"> to
specify the prefix length (number of prefix columns to compress).<o:p></o:p></span></div>
<div style="margin-left: 36.0pt; mso-list: l1 level1 lfo2; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
<br /></div>
<ul>
<li style="text-align: justify;">For
unique indexes, the range of valid prefix length values is from 1 to the number
of key columns minus 1. The default prefix length is the number of key columns
minus 1.</li>
<li style="text-align: justify;">For nonunique
indexes, the range of valid prefix length values is from 1 to the number of key
columns. The default prefix length is number of key columns.</li>
</ul>
</div>
<div style="text-align: justify;">
<span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;">Oracle Database compresses indexes that are
nonunique or unique indexes of at least two columns. If you want to use
compression for a partitioned index, then the index must have compression
enabled at the index level.<o:p></o:p></span></div>
<div style="text-align: justify;">
<span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;">Specify </span><code><span lang="EN" style="color: #222222; font-size: 11.0pt;">NOCOMPRESS</span></code><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;"> to disable key compression. This is the default.<o:p></o:p></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="SQLRF52765" name="SQLRF52765"></a><span class="subhead31"><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;">Restriction on Key Compression<a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2860" name="sthref2860"></a><a href="http://www.blogger.com/blogger.g?blogID=8208730947417975246" id="sthref2861" name="sthref2861"></a> </span></span><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;">You cannot specify </span><code><span lang="EN" style="color: #222222; font-size: 11.0pt;">COMPRESS</span></code><span lang="EN" style="color: #222222; font-family: "tahoma" , "sans-serif"; font-size: 10.0pt;"> for a bitmap index.<o:p></o:p></span></div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-70449371533311396712012-08-15T11:11:00.000-03:002016-07-25T09:20:06.220-03:00Optimizer Extensible InterfaceHoje convido a todos a ler o meu mais novo artigo publicado na Oracle Technology Network:<br />
<br />
<a href="http://www.oracle.com/technetwork/pt/articles/sql/como-usar-as-funcoes-pipelined-11g-1719765-ptb.html">Extendendo o otimizador do oracle 11g para obter estatísticas de funções pipelined</a><br />
<br />
Este artigo trata de um recurso avançado do Oracle para adicionar estatísticas a funções pipelined, que sem isso seriam apenas estimadas gerando planos nem sempre ótimos. Eu entendo que esta é uma <i>feature</i> muito interessante e pouco conhecida, e com alguns <i>tweaks</i> pode ser adaptada para obter estatísticas de qualquer objeto/coleção tratado com o operador TABLE.<br />
<br />
Para maiores informações, recomendo a leitura do artigo do Adrian Billington abaixo:<br />
<br />
<a href="http://www.oracle-developer.net/display.php?id=427">setting cardinality for pipelined and table functions</a><br />
<br />
E para quem quiser conhecer mais artigos técnicos publicados pela OTN, acessem o link abaixo:<br />
<br />
<a href="http://www.oracle.com/technetwork/pt/articles/index.html">http://www.oracle.com/technetwork/pt/articles/index.html</a>Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com1tag:blogger.com,1999:blog-8208730947417975246.post-74260608189191140592012-07-18T04:00:00.000-03:002016-07-25T09:03:47.022-03:00DespivotandoRecentemente eu comecei a participar nos forums da Oracle Technology Network para ajudar a comunidade (e também ser ajudado). Há pouco tempo atrás respondi uma pergunta interessante que gostaria de compartilhar com vocês, pois mostra o uso de uma nova feature do Oracle 11g: a clausula UNPIVOT do SELECT.<br />
<br />
O objetivo da pergunta era, dado uma tabela com N colunas, mostrar através de uma query quais colunas tem valores nulos e em quais linhas. A principio uma solução simples porém trabalhosa, como apontado pelo OP, seria fazer uma query com diversas clausulas OR testando cada coluna isoladamente por NULL. Porém isso ainda envolveria um trabalho adicional para analisar o result set e identificar quais são as colunas nulas, possivelmente envolvendo uma infinidade de CASEs, ou ainda, substituindo o OR por UNION ALL e criando uma query monstruosa.<br />
<br />
Pois bem, é aí que entra a mágica do UNPIVOT. Em uma única clausula podemos transformar todas as colunas separadas numa única coluna e varrer apenas esta coluna pelos valores nulos. Infelizmente não tenho o Oracle 11g disponível aqui para postar o resultado, mas encorajo vocês a executarem o código abaixo:<br />
<br />
<span style="background-color: white;"><span style="font-family: monospace; font-size: 13px; white-space: pre;">select *
from (select rownum row_num,
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>case</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> when dbms_random.value < 0.5
then </span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>null</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;">
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>else</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> dbms_random.value
end a,
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>case</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> when dbms_random.value < 0.5
then </span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>null</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;">
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>else</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> dbms_random.value
end b,
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>case</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> when dbms_random.value < 0.5
then </span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>null</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;">
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>else</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> dbms_random.value
end c,
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>case</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> when dbms_random.value < 0.5
then </span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>null</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;">
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>else</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> dbms_random.value
end d,
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>case</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> when dbms_random.value < 0.5
then </span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>null</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;">
</span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>else</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> dbms_random.value
end e
from dual
connect by level <= 10)
unpivot include nulls (my_value </span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>for</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;"> my_column in(a, b, c, d, e))
where my_value is </span><span style="color: navy; font-family: monospace; font-size: 13px; white-space: pre;"><b>null</b></span><span style="font-family: monospace; font-size: 13px; white-space: pre;">;</span></span><br />
<span style="background-color: #eeeeee; font-family: monospace; font-size: 13px; white-space: pre;"><br /></span>
Para quem quiser acessar a pergunta original, basta seguir o link:<br />
<br />
<a href="https://forums.oracle.com/forums/message.jspa?messageID=10434991">https://forums.oracle.com/forums/message.jspa?messageID=10434991</a><br />
<br />Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-17590135644598601842012-07-16T22:18:00.002-03:002016-07-25T09:04:48.840-03:00Publicações na Oracle Technology NetworkHoje tenho o prazer de divulgar a vocês o resultado positivo do meu último trabalho: a publicação de dois artigos meus na <a href="http://www.oracle.com/technetwork/pt/index.html">Oracle Technology Network</a>. Estes artigos tratam basicamente da relação das trocas de contexto com a performance de procedimentos e os mecanismos para otimizá-las. Para quem quiser conferir, basta seguir os links abaixo:<br />
<div>
<br /></div>
<div>
<a href="http://www.oracle.com/technetwork/pt/articles/sql/execucao-de-querys-e-blocos-pl-sql-1697151-ptb.html">Aumentando a performance de procedimentos através da redução de trocas de contexto</a></div>
<div>
<br /></div>
<div>
<a href="http://www.oracle.com/technetwork/pt/articles/sql/operacoes-dml-com-comando-forall-1697017-ptb.html">Otimizando operações DML com o uso de FORALL</a></div>
<div>
<br /></div>
<div>
Além disto, para quem tem vocação para a escrita e gostaria de compartilhar seu conhecimento nas tecnologias da Oracle, gostaria de fazer o convite para enviarem artigos para a OTN. Os detalhes estão no link abaixo:</div>
<div>
<br /></div>
<div>
<a href="http://www.oracle.com/technetwork/pt/articles/otn-submit-101843-ptb.html">http://www.oracle.com/technetwork/pt/articles/otn-submit-101843-ptb.html</a></div>
<div>
<br /></div>
<div>
Para finalizar, agradeço o apoio que me foi dado pela publicação destes artigos e fiquem ligados que em breve devo apresentar novos tópicos tanto neste blog como na OTN.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-37130780927295133362012-06-24T20:06:00.000-03:002016-07-25T09:05:40.807-03:00Habilitando as setas no sqlplus para Linux<div style="text-align: justify;">
Hoje vou postar um truque rápido que me ajudou muito nos últimos dias. Quem já utilizou o <b>sqlplus</b> em Windows e depois migrou para Linux já deve ter percebido uma limitação irritante da versão para Linux que é a falta da usabilidade das setas do teclado, tanto para navegar na linha atual (setas direita e esquerda) como para buscar um comando no histórico (setas para cima e para baixo).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Pois bem, hoje vou apresentar um simples utilitário que "devolve" essa capacidade para o sqlplus. Ele é chamado de <b>rlwrap</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Como estou usando uma variante do Ubuntu (o Lubuntu para ser mais exato), vou mostrar como instalá-lo utilizando o <b>apt-get</b>. Porém acredito que outras distribuições também devem ter pacotes disponíveis para ele (ex.: usando o <b>yum</b> no RHEL). Vamos a sua instalação:</div>
<div style="text-align: justify;">
<br /></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">paulo@sayuri:~$ sudo apt-get install rlwrap</span></div>
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Reading package lists... Done</span></div>
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Building dependency tree </span></div>
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Reading state information... Done</span></div>
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">The following NEW packages will be installed:</span></div>
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> rlwrap</span></div>
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><...></span></div>
<br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Uma vez concluída a instalação vamos modificar o comando sqlplus para ser chamado pelo rlwrap:</div>
<div style="text-align: justify;">
<br /></div>
<br />
<div style="text-align: justify;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">paulo@sayuri:~$ alias sqlplus='rlwrap sqlplus'</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Pronto! Agora basta invocar o sqlplus normalmente pela linha de comando e as setas estarão disponíveis.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-27465512394167394422012-03-01T02:20:00.004-03:002016-07-25T09:20:06.207-03:00Caso de Performance 3: Bind variables<div style="font-family: inherit;">
Olá pessoal. Hoje vou continuar com a demonstração do efeito de usar (e não usar) <i>bind variables</i> no Oracle. Começo ressaltando que embora eu esteja usando um exemplo em PL/SQL pela praticidade, isto é válido para qualquer linguagem que se comunica com o banco, incluindo java, C++ e outras. De modo geral, vou provar para vocês que montar uma <i>query</i> com valores concatenados sempre é uma má idéia, pois força o <i>hard parsing</i> aumentando intensamente o consumo de recursos pelo banco e simplesmente destrói a <i>shared pool</i> no curto prazo.</div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
O código de exemplo é bastante simples: vamos montar uma tabela T com duas colunas, X e Y, ambas numéricas e com valores de 1 a 1000. Em seguida, vamos fazer um bloco anônimo em PL/SQL que lê esta tabela passando o valor de X e retornando Y para uma variável em memória. Faremos este bloco repetir este processamento 100 vezes (portanto, executamos 100.000 vezes a <i>query</i> de recuperação de valor) e tomamos o tempo gasto nesta operação.</div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
O bloco anônimo primeiramente vai ser implementado usando a concatenação de valores e, num segundo momento, vai ser reescrito para utilizar <i>bind variables</i>. A nossa prova será a diferença de tempo entre as execuções e também as estatisticas de parsing da sessão.</div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
Vamos passo a passo: </div>
<div style="font-family: inherit;">
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">/tmp$ sqlplus paulo/paulo<br /><br />SQL*Plus: Release 10.2.0.1.0 - Production on Thu Mar 1 01:02:01 2012<br /><br />Copyright (c) 1982, 2005, Oracle. All rights reserved.<br /> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Connected to:<br />Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production<br /> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">SQL> drop table t;<br /> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Table dropped.<br /> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">SQL> create table t(x number, y number);<br /><br />Table created.<br /> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">SQL> insert into t<br /> 2 select rownum, rownum from dual connect by level <= 1000;<br /> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">1000 rows created.<br /> </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">SQL> commit;</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Commit complete.</span></div>
<div>
<br /></div>
<div style="font-family: inherit;">
<span style="font-size: small;">Ok, com a tabela criada vamos primeiro tomar a medida da quantidade de <i>parses</i> executadas até o momento para termos como base. Isto é feito com a <i>query</i> abaixo:</span><span style="font-size: small;"> </span></div>
<div style="font-family: inherit;">
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">SQL> select sn.name, vm.value<br /> 2 from v$mystat vm,<br /> 3 v$statname sn<br /> 4 where vm.statistic# = sn.statistic#<br /> 5 and sn.name like '%parse%';<br /><br />NAME VALUE<br />---------------------------------------------------------------- ----------<br />parse time cpu 16<br />parse time elapsed 19<br />parse count (total) 445<br />parse count (hard) 95<br />parse count (failures) 0</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: inherit; font-size: small;">Esta <i>query</i> resume as principais estatísticas da sessão com relação ao <i>parse</i>. Estamos mais interessados, no entanto, no <b>parse count (total)</b> e no <b>parse count (hard)</b>. Tenha em mente o seguinte: o parse count (total) é a soma de todos os parses executados, sejam eles <i>hard</i> ou <i>soft</i>. A diferença entre um parse <i>hard</i> e um <i>soft</i> é que no <i>hard parse</i> o banco precisa validar a <i>query</i> e estabelecer o plano de execução, um processo bastante demorado e consumidor de recursos. Já no <i>soft parse</i>, o banco apenas verifica se a <i>query</i> já existe na <i>shared pool</i> e reaproveita o plano existente, economizando aí um tempo bastante significativo. Pelas estatisticas acima, para saber a quantidade de <i>soft parses</i> basta subtrair a quantidade de <i>hard parses</i> do total.</span></div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
<span style="font-size: x-small;"><span style="font-size: small;">Vamos então executar o bloco anônimo com o código que utiliza concatenação de valores para gerar as diversas <i>querys</i>. </span></span></div>
<div style="font-family: inherit;">
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">SQL> declare<br /> 2 v_num number;<br /> 3 t0 number := dbms_utility.get_time;<br /> 4 <br /> 5 begin<br /> 6 for r1 in (select rownum from dual connect by level <= 100)<br /> 7 loop<br /> 8 for r2 in (select rownum from dual connect by level <= 1000)<br /> 9 loop<br /> 10 execute immediate 'select y from t where x = ' || r2.rownum into v_num;<br /> 11 end loop;<br /> 12 end loop;<br /> 13 dbms_output.put_line('hsecs=' || (dbms_utility.get_time - t0));<br /> 14 end;<br /> 15 /<br />hsecs=11859<br /><br />PL/SQL procedure successfully completed.</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div style="font-family: inherit;">
<span style="font-size: x-small;"><span style="font-size: small;">Como vocês podem ver, esta operação tomou um tempo significativo do banco: 11859 centésimos de segundo, ou 118.59 segundos. Acompanhe a estatistica de <i>parses</i>:</span></span></div>
<div>
<br />
<span style="font-family: Courier New, Courier, monospace;">SQL> select sn.name, vm.value<br /> 2 from v$mystat vm,<br /> 3 v$statname sn<br /> 4 where vm.statistic# = sn.statistic#<br /> 5 and sn.name like '%parse%';<br /><br />NAME VALUE<br />---------------------------------------------------------------- ----------<br />parse time cpu 10881<br />parse time elapsed 10980<br />parse count (total) 200494<br />parse count (hard) 100113<br />parse count (failures) 0</span></div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
<span style="font-size: small;">Agora, temos duas coisas interessantes para observar: primeiro, a contagem de hard parses foi lá em cima, como esperado, mas por que ainda sim tivemos quase 50% de soft parses? A resposta está no fato de que sempre existem querys recursivas, ou internas do banco, que são executadas quando enviamos qualquer comando para o banco, e certamente elas foram escritas para serem reaproveitadas. Isso explica também porque a quantidade de hard parses foi um pouco acima do esperado (100.000). Enfim, vamos ao segundo teste:</span></div>
<div>
<br />
<span style="font-family: Courier New, Courier, monospace;">SQL> declare<br /> 2 v_num number;<br /> 3 t0 number := dbms_utility.get_time;<br /> 4 <br /> 5 begin<br /> 6 for r1 in (select rownum from dual connect by level <= 100)<br /> 7 loop<br /> 8 for r2 in (select rownum from dual connect by level <= 1000)<br /> 9 loop<br /> 10 execute immediate 'select y from t where x = :1' into v_num using r2.rownum;<br /> 11 end loop;<br /> 12 end loop;<br /> 13 dbms_output.put_line('hsecs=' || (dbms_utility.get_time - t0));<br /> 14 end;<br /> 15 /<br />hsecs=798<br /><br />PL/SQL procedure successfully completed.</span></div>
<div style="font-family: inherit;">
<span style="font-size: x-small;"><br /></span></div>
<div style="font-family: inherit;">
<span style="font-size: x-small;"><span style="font-size: small;">Desta vez fizemos do jeito certo: com <i>bind</i> <i>variables</i>. E o resultado é surpreendente: de 118.59 segundos agora a mesma query executou em apenas 7.98 segundos! Vejamos como ficou a estatística da sessão:</span></span></div>
<div>
<br />
<span style="font-family: Courier New, Courier, monospace;">SQL> select sn.name, vm.value<br /> 2 from v$mystat vm,<br /> 3 v$statname sn<br /> 4 where vm.statistic# = sn.statistic#<br /> 5 and sn.name like '%parse%';<br /><br />NAME VALUE<br />---------------------------------------------------------------- ----------<br />parse time cpu 10883<br />parse time elapsed 10983<br />parse count (total) 200537<br />parse count (hard) 100127<br />parse count (failures) 0</span></div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
<span style="font-size: small;">Lembre-se que estamos na mesma sessão do bloco anterior, ou seja, 200.537 - 200.494 = 43 <i>parses</i> a mais, sendo que destes apenas 14 são do tipo <i>hard</i>! Isso quer dizer que a nossa <i>query</i> com <i>bind</i> <i>variables</i> foi 100% reaproveitada em todas as passadas. Acredito que ficou nítida a diferença de performance que isso proporciona.</span></div>
<div style="font-family: inherit;">
<span style="font-size: small;"><br /></span></div>
<div style="font-family: inherit;">
<span style="font-size: small;">Para encerrar, deixo uma pergunta no ar: era esperado que todas as <i>querys</i> recursivas e as <i>querys</i> dos cursores r1 e r2 fossem reaproveitadas já que estamos na mesma sessão, e portanto seriam feitos apenas<i> soft parses</i> das mesmas. Agora, se você parar para pensar, a <i>query</i> do cursor r2 é executada 100 vezes mas temos muito menos de 100 <i>soft parses.</i> Qual seria a explicação para isso? Infelizmente eu não tenho a resposta, mas se alguém tiver fique a vontade para postar nos comentários.</span></div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
<span style="font-size: x-small;"><span style="font-size: small;">E por hoje é só pessoal! :) </span></span></div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-64422425867357614432011-12-11T15:06:00.001-02:002016-07-25T09:20:06.217-03:00Otimização de parsing usando bind variablesHoje vou apresentar a vocês um dos grandes responsáveis pela degradação de performance nos bancos de dados Oracle: trata-se do excessivo uso de <i>hard parsing</i>, ou seja, a pequena reusabilidade dos planos nas diretivas SQL.<br />
<br />
Para quem não conhece, o <b>hard parse</b> ocorre quando o banco vê uma <i>query</i> pela "primeira vez" e não tem uma estratégia definida sobre como irá acessar os dados. Logo, ele precisa analisar todas as combinações possíveis de métodos de acesso para obter aquela informação solicitada. Esta análise inclui, mas não está limitada a, definir a ordem de join das tabelas, análise de estatísticas (de tabelas e do sistema), a decisão de fazer a leitura por índices ou full table scans (FTS), a reescrita da query para uma equivalente mais rápida, criar ou não tabelas intermediárias para <i>views</i>, enfim, uma infinidade de operações que, quando mais complicada for a <i>query</i>, mas possibilidades existem e mais recursos são consumidos para estabelecer este <b>plano de execução</b>.<br />
<br />
Uma vez estabelecido, o plano de execução tende a ser reutilizado todas as vezes que a <i>query</i> for executada, desde que este plano consiga se manter em memória. Acontece que, se muitas querys distintas forem executadas, a área disponível para armazenamento de planos na <i>shared pool</i> pode não ser suficiente, e os planos mais antigos começam a ser descartados. Numa situação destas, um plano previamente estabelecido pode ser sobrescrito por um plano de outra <i>query</i> e ao reexecutarmos uma <i>query</i> mais antiga ela acabará tendo que passar pelo processo de <i>hard parse n</i>ovamente (e por sua vez sobrescrevendo o plano de outra <i>query</i>).<br />
<br />
Agora, o que determina a quantidade de <i>hard parsing</i> no banco, e como evitar? Bom, primeiro, um dos critérios é o tamanho em memória da <i>shared pool. </i>Esta área armazena todos os planos atualmente disponíveis para o Oracle. Não vou entrar em detalhes neste momento sobre quanta memória é o ideal para esta área, pois para os fins deste artigo é o critério seguinte que nos interessa: a quantidade de <i>querys</i> distintas que existem no banco em um dado momento.<br />
<br />
Para responder esta questão a primeira coisa que precisamos levar em conta é: como o Oracle faz para identificar que uma <i>query</i> já existe ou não na <i>shared pool</i>? E a reposta é, de modo geral, com uma comparação textual <b>exata</b> da <i>query </i>solicitada com as <i>querys</i> disponíveis na<i> shared pool.</i> Digo de modo geral porque este comportamento pode ser modificado com o parâmetro de sistema <i>cursor_sharing</i> (voltarei a falar sobre ele adiante).<br />
<br />
Suponha por exemplo, que você executou a query a seguir:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
select * from t where x = 1;</div>
<br />
E em seguida executou a query:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">select * from t where x = 1;</span><br />
<br />
A primeira vista as duas <i>querys</i> podem parecer iguais, mas na segunda eu incluí um espaço a mais antes do asterisco (*). Isto por si só já é o suficiente para que a segunda query falhe na comparação textual com a primeira, e portanto as duas serão submetidas a um <i>hard parse</i>.<br />
<br />
Este conceito fica mais evidenciado quando estamos lidando com SQL dinâmico, pois é muito comum as pessoas codificarem a passagem dos valores para a query utilizando a concatenação de valores:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
execute immediate 'select * from t where x = ' || valor;</div>
<br />
Agora considere este código dentro de uma stored procedure que recebe a variável 'valor' como parâmetro. Esta SP vai ter o poder de gerar infinitos cursores, pois cada valor concatenado vai forçar uma query nova (vai falhar na comparação textual) e toda chamada desta SP, além de passar por um hard parse, vai ainda retirar um cursor mais antigo da <i>shared pool</i> que poderia ser reaproveitado. Ou seja, além da lentidão do parse, corremos o risco de destruir a shared pool inteira, se por exemplo, executarmos esta SP dentro de um loop.<br />
<br />
No próximo artigo irei apresentar um caso de performance de um código com bind variables contra um código sem binds. Fiquem ligados!Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-47795382907359424672011-12-06T21:12:00.001-02:002016-07-25T09:08:37.691-03:00Os melhores blogs sobre OracleSei que o título parece um pouco pretensioso, mas o objetivo deste post é listar os melhores blogs que existem tratando do assunto banco de dados Oracle ou PL/SQL. A idéia é manter a lista sempre atualizada acrescentando sites a medida do necessário.<br />
<br />
Estou fazendo isso principalmente porque no meu recente <i>crash </i>de HD perdi muita informação, sendo meus bookmarks uma parte disso. Portanto, decidi manter meus bookmarks oficialmente online neste post, e de quebra posso ajudar alguém que esteja procurando novas fontes de informação.<br />
<br />
Se alguém tiver uma sugestão de blogs fique a vontade para postar nos comentários abaixo que eu adicionarei a lista oficial.<br />
<br />
<b>Melhores blogs sobre banco de dados Oracle</b><br />
<br />
<b>Internacionais</b><br />
<a href="http://jonathanlewis.wordpress.com/"></a><br />
<br />
<a href="http://blogs.oracle.com/optimizer/">Inside the Oracle Optimizer - Removing the black magic</a> (Maria Colgan) <br />
<a href="http://jonathanlewis.wordpress.com/">Oracle Scratchpad </a>(Jonathan Lewis)<br />
<a href="http://richardfoote.wordpress.com/">Richard Foote’s Oracle Blog</a><br />
<a href="http://www.stevenfeuerstein.com/">Steven Feuerstein</a><br />
<a href="http://structureddata.org/">Structured Data</a> (Greg Rahn) <br />
<a href="http://tkyte.blogspot.com/">The Tom Kyte Blog</a><br />
<a href="http://www.oracle-developer.net/">oracle-developer.net (Adrian Billington)</a><br />
<br />
<b>Nacionais</b><br />
<br />
<a href="http://miltonbastos.com/">ORA-01000 cc – miltonbastos.com</a><br />
<br />
<b>Nota:</b> a lista está longe de estar completa, mas estou postando ela agora justamente para divulgar e angariar sugestões de novos blogs com os leitores.Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-8368356747006144232011-12-02T23:30:00.001-02:002016-11-23T17:01:16.267-02:00Utilizando o tkprof para localizar hotspots de SQLFinalmente, dando continuidade ao post sobre <a href="http://oraculodosul.blogspot.com/2011/11/metodologia-para-tuning-de_26.html">Metodologia de tuning parte 3</a>, vou falar um pouco mais sobre como funciona a ferramenta <b>tkprof</b> para localizar <i>hotspots</i> de SQL.<br />
<br />
Como havia dito anteriormente, infelizmente eu tive problemas com o HD da minha máquina e perdi a versão anterior deste artigo. Então, para poder publicá-lo no menor tempo possível resolvi ao invés de utilizar o exemplo complexo que eu havia elaborado, reaproveitar o código de exemplo do post <a href="http://oraculodosul.blogspot.com/2011/11/caso-de-performance-2-tabelas.html">Caso de Performance 2 - Tabelas Temporárias</a>, com algumas pequenas adaptações. Na realidade, o código que utilizarei neste post pouco importa, o que vale é a técnica de utilização da ferramenta.<br />
<br />
Dito isto, as adaptações realizadas no código original foram as seguintes: primeiro, eu transformei os blocos anônimos em duas stored procedures. A primeira, <b>slow_proc</b>, é o método lento, utilizando tabelas temporárias. A segunda, <b>fast_proc</b>, é o método rápido, utilizando arrays. Além disso, para simplificar o trabalho, coloquei as etapas de criação do ambiente em um arquivo texto chamado prepara_trace.sql que eu irei invocar para zerar o ambiente em cada etapa do tutorial. Segue seu conteúdo na íntegra:<br />
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">drop table heap_table;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">create table heap_table(x number);</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">drop table temp_table;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">create global temporary table temp_table(x number);</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">create or replace procedure slow_proc as</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> t number := dbms_utility.get_time;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> procedure lp_dummy is</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> begin</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> insert into heap_table</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> select * from temp_table;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> end;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">begin</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> for r in (select rownum from dual connect by level <= 1000)</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> loop</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> delete temp_table;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> insert into temp_table</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> select rownum from dual connect by level <= 100;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> lp_dummy;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> end loop;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> dbms_output.put_line('hsecs=' || (dbms_utility.get_time - t));</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">end;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">/</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">create or replace procedure fast_proc as</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> t number := dbms_utility.get_time;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> type typ_heap is table of heap_table%rowtype index by pls_integer;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> a_heap typ_heap;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> procedure lp_dummy is</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> begin</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> forall i in a_heap.first .. a_heap.last</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> insert into heap_table values a_heap(i);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> end;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">begin</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> for r in (select rownum from dual connect by level <= 1000)</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> loop</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> select rownum bulk collect into a_heap </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> from dual connect by level <= 100;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> lp_dummy;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> end loop;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;"> dbms_output.put_line('hsecs=' || (dbms_utility.get_time - t));</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">end;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">/</span></span></blockquote>
Agora, para começar, lembre-se de verificar o diretório de destino do trace no <b>sqlplus </b>com o comando:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">show parameter user_dump_dest</span></div>
<br />
Além disso, você vai precisar se conectar com o usuário <b>oracle</b> ou um usuário que pertence ao grupo <b>dba</b> para poder ler o arquivo do trace.<br />
<br />
Feito estes preparativos vamos ao processo:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">$ sqlplus dani/dani<br /><br />SQL*Plus: Release 10.2.0.1.0 - Production on Sun Dec 4 21:52:11 2011<br /><br />Copyright (c) 1982, 2005, Oracle. All rights reserved.<br /><br /><br />Connected to:<br />Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production<br /><br />SQL> set serveroutput on<br />SQL> @/tmp/prepara_trace<br /><br />Table dropped.<br /><br /><br />Table created.<br /><br /><br />Table dropped.<br /><br /><br />Table created.<br /><br /><br />Procedure created.<br /><br /><br />Procedure created.<br /><br /><br />SQL> alter session set tracefile_identifier = 'slow';<br /><br />Session altered.<br /><br />SQL> alter session set sql_trace = true;<br /><br />Session altered.<br /><br />SQL> call slow_proc();<br />hsecs=235<br /><br />Call completed.<br /><br />SQL> alter session set sql_trace = false;<br /><br />Session altered.<br /><br />SQL> alter session set tracefile_identifier = 'fast';<br /><br />Session altered.<br /><br />SQL> alter session set sql_trace = true;<br /><br />Session altered.<br /><br />SQL> call fast_proc();<br />hsecs=38<br /><br />Call completed.<br /><br />SQL> alter session set sql_trace = false;<br /><br />Session altered.<br /><br />SQL> exit</span></blockquote>
Agora temos 2 arquivos de trace, correspondentes a cada uma das execuções. Vamos analisá-los com o tkprof:<br />
<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">$ ls -ltrh | tail -n 2<br />-rw-r----- 1 oracle dba 283K 2011-12-04 21:53 xe_ora_2946_slow.trc<br />-rw-r----- 1 oracle dba 236K 2011-12-04 21:54 xe_ora_2946_fast.trc</span></blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;">$ tkprof xe_ora_2946_slow.trc slow.txt</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">TKPROF: Release 10.2.0.1.0 - Production on Sun Dec 4 21:57:26 2011</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">Copyright (c) 1982, 2005, Oracle. All rights reserved.</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">$ tkprof xe_ora_2946_fast.trc fast.txt</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">TKPROF: Release 10.2.0.1.0 - Production on Sun Dec 4 21:57:39 2011</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "courier new" , "courier" , monospace;">Copyright (c) 1982, 2005, Oracle. All rights reserved.</span></span></blockquote>
Primeiro, vamos analisar o arquivo <b>slow.txt.</b> Uma maneira bem tranquila para se localizar os comandos SQL que estão tomando mais tempo é observar as linhas de sumário para <i>total</i> - <i>elapsed</i>, ou seja, o tempo real decorrido de execução do comando. Com o comando <b>grep</b> do Linux/Unix podemos listar rapidamente as linhas de totais:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">$ grep total slow.txt<br />total 1 0.00 0.00 0 0 0 0<br />total 4 0.00 0.00 0 0 0 2<br />total 2 0.14 0.19 0 0 0 0<br />total 4 0.00 0.00 0 4 0 1<br />total 3 0.00 0.00 0 2 0 0<br />total 3 0.00 0.00 0 2 0 1<br />total 3 0.00 0.00 0 2 0 1<br />total 3 0.00 0.00 0 1 0 1<br />total 3 0.00 0.00 0 2 0 0<br />total 4 0.00 0.00 0 4 0 1<br />total 3 0.00 0.00 0 1 0 0<br />total 1 0.00 0.00 0 0 0 0<br />total 13 0.00 0.00 0 0 0 1000<br />total 6 0.00 0.00 0 2 0 0<br /><b>total 1001 1.08 1.37 0 31947 103235 99900</b><br />total 5 0.00 0.00 0 4 0 0<br />total 1001 0.33 0.29 0 1183 3018 100000<br />total 3 0.00 0.00 0 3 0 1<br />total 1001 0.46 0.41 0 32384 2869 100000<br />total 108 0.00 0.00 0 92 0 27<br />total 32 0.00 0.00 0 50 16 16<br />total 32 0.00 0.00 0 80 16 16<br />total 2 0.00 0.00 0 0 0 0<br />total 9 0.15 0.20 0 0 0 2<br />total 3229 1.90 2.09 0 65763 109154 300965</span></blockquote>
Todas as linhas mostradas representam o sumário de um comando SQL contido no arquivo, com exceção das duas últimas que representam os sumários do tkprof. Agora, eu falei que era importante olhar para as colunas elapsed, certo? Para recordar, estas linhas "total" que mostramos com o comando anterior fazem parte de tabelas como esta aqui:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">call count cpu elapsed disk query current rows<br />------- ------ -------- ---------- ---------- ---------- ---------- ----------<br />Parse 1 0.00 0.00 0 0 0 0<br />Execute 1000 1.08 1.36 0 31947 103235 99900<br />Fetch 0 0.00 0.00 0 0 0 0<br />------- ------ -------- ---------- ---------- ---------- ---------- ----------<br /><b>total 1001 1.08 1.37 0 31947 103235 99900 </b></span></blockquote>
No caso, destaquei em negrito a linha "total" na tabela acima e na lista anterior para você se situar melhor onde quero chegar. A coluna 4 da lista de resultado do grep corresponde exatamente ao tempo <i>elapsed</i>. Então ao olhar esta coluna sabemos exatamente quais são os comandos SQL que devemos buscar no arquivo do trace baseado nos seus tempos. Se você abrir o arquivo slow.txt e buscar pelo tempo 1.37 vai cair nesta tabela e vai descobrir que ela corresponde à linha <b>delete temp_table</b> da procedure <b>slow_proc</b>.<br />
<br />
Agora repare que interessante: com exceção da última linha, que corresponde ao sumário, esta é a linha que mais consome tempo, ou seja: perdemos mais tempo limpando nossa tabela de trabalho do que fazendo qualquer processamento útil para nossa "regra de negócio". Sei que é um exemplo artificial, mas na vida real já vi acontecerem situações similares.<br />
<br />
E para você que teve paciência de ler até aqui vai um macete de presente. Primeiro, observe que este é um trace pequeno e mesmo assim tem 25 linhas total para serem avaliadas. Imagine uma procedure "de verdade", com dezenas de linhas e de chamadas a outras procedures... vai ser um caos localizar manualmente estas querys, certo? Então fique de olho no comando a seguir:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">$ grep total slow.txt | awk '{if($4>0.1) {print $4}}'<br />0.19<br />1.37<br />0.29<br />0.41<br />0.20<br />2.09</span></blockquote>
Qual é a mágica? Utilizando o comando <b>awk</b>, adicionei um filtro na coluna 4 (variável <b>$4</b>) para mostrar apenas os valores que forem maiores que 0,1 . Assim eu estabeleço um critério sobre quais SQL eu quero avaliar - apenas aqueles que gastaram mais que um tempo <b>x</b>. Se você quiser mostrar a linha inteira, pode substituir o<b> print $4 </b>por<b> print $0:</b><br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: xx-small;"><br /></span></div>
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">$ grep total slow.txt | awk '{if($4>0.1) {print $0}}'<br />total 2 0.14 0.19 0 0 0 0<br />total 1001 1.08 1.37 0 31947 103235 99900<br />total 1001 0.33 0.29 0 1183 3018 100000<br />total 1001 0.46 0.41 0 32384 2869 100000<br />total 9 0.15 0.20 0 0 0 2<br />total 3229 1.90 2.09 0 65763 109154 300965</span></blockquote>
<br />
Aí, tendo em mãos esta lista de valores, você pode facilmente pegar seu editor de texto favorito e fazer uma busca textual pelo valor da coluna 4 que encontrará a tabela de sumário. Logo acima desta tabela estará a query responsável por aquele tempo.<br />
<br />
Enfim, esta é a técnica que eu gostaria de mostrar para identificar hotspots de SQL em um arquivo de trace. É de certa forma bastante rudimentar mas já me quebrou o galho muitas vezes. Apenas gostaria de acrescentar mais uma informação para aqueles que utilizam RedHat ou derivados, adicione a função <b>strtonum()</b> na coluna $4 ao fazer a comparação com o valor de limite:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">$ grep total slow.txt | awk '{if(strtonum($4)>0.1) {print $0}}'</span></blockquote>
E para finalizar, vou mostrar o resultado do grep no arquivo fast.txt:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">$ grep total fast.txt | awk '{if($4>0.1) {print $0}}'<br />total 2001 0.18 0.18 0 0 0 100000<br />total 3054 0.27 0.26 0 210 2240 201009</span></blockquote>
<br />
Apenas 2 ocorrências, sendo que uma delas é o sumário... definitivamente, remover o overhead do tratamento das temporárias deixou o código muito mais level e eficiente!<br />
<br />
Aconselho você a executar este exemplo em casa e conferir os resultados. Tem muita informação nos arquivos de trace e tkprof que eu não consigo cobrir em um único post, então aproveite para tirar dúvidas na seção de comentários abaixo. Até a próxima!Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-45652270036065277282011-12-01T13:52:00.001-02:002016-07-25T09:14:45.578-03:00Problemas técnicos e EnqueteBoa tarde pessoal. Gostaria de publicar apenas uma rápida nota avisando que estou passando por alguns problemas técnicos com meu notebook onde eu estava rodando os códigos de exemplo. Basicamente o HD dele apresentou defeito e junto com ele foi o novo artigo que eu estava preparando sobre o tkprof. Em termos de conteúdo não se perdeu muito, pois isso ainda está fresco na minha cabeça... o problema maior vai ser arrumar tempo para organizar o setup de novo e também trocar o HD defeituoso.<br />
<br />
Enquanto isso se resolve, gostaria de chamar a atenção de vocês para uma enquete que eu coloquei na barra lateral do blog, sobre a expectativa de quais artigos eu devo me concentrar no futuro. Por favor votem, pois assim posso dar um direcionamento melhor ao conteúdo de maneira a agradar a todos os leitores.<br />
<br />
No mais, espero que até o fim de semana eu já tenha a estrutura para continuar o ritmo normal de publicações. Fiquem ligados!<br />
<br />Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-33716176142221218592011-11-26T21:12:00.001-02:002016-07-25T09:20:06.211-03:00Metodologia para Tuning de Procedimentos - Parte 3Dando continuidade a série de posts sobre metodologia de tuning hoje vou falar sobre as estratégias que dispomos para identificar os <i>hotspots</i>, ou seja, os pontos que estão gastando mais tempo do nosso processo e que portanto necessitam de ajustes.<br />
<br />
A ferramenta primordial para localizar estes pontos é o SQL Trace. Este é um recurso do banco de dados Oracle que habilita a gravação de um arquivo de log com todas as operações realizadas dentro de uma determinada sessão (ou de várias sessões, no caso de uma conexão MTS). O arquivo de log gerado pelo SQL trace fica sempre armazenado no sistema de arquivos do servidor, dentro da pasta apontada pelo parâmetro <b>user_dump_dest</b>. Abaixo mostro duas formas de recuperar o valor deste parâmetro:<br />
<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">paulo@hitomi:~$ sqlplus paulo/paulo</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL*Plus: Release 11.2.0.2.0 Beta on Sat Nov 26 21:23:12 2011</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Copyright (c) 1982, 2010, Oracle. All rights reserved.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Connected to:</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Beta</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> show parameter user_dump_dest</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">NAME<span class="Apple-tab-span" style="white-space: pre;"> </span> TYPE<span class="Apple-tab-span" style="white-space: pre;"> </span> VALUE</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------------------------------------ ----------- ------------------------------</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">user_dump_dest<span class="Apple-tab-span" style="white-space: pre;"> </span> string<span class="Apple-tab-span" style="white-space: pre;"> </span> /u01/app/oracle/diag/rdbms/xe/</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span> XE/trace</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> select value from v$parameter where name = 'user_dump_dest';</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">VALUE</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">--------------------------------------------------------------------------------</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">/u01/app/oracle/diag/rdbms/xe/XE/trace</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> </span><br />
<div>
<br /></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">E, para habilitar o SQL trace da sessão atual, basta executar:</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> alter session set sql_trace = true;</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Session altered.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> select 1 from dual;</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span> 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span> 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> alter session set sql_trace = false;</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Session altered.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> </span></div>
</div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">Um arquivo <b>.trc</b> será gerado no diretório de<b> user_dump_dest</b> com o resultado do trace desta sessão. Se você for neste diretório e tentar localizar o arquivo pode abri-lo com um editor de textos comum, como o <b>vi</b> ou o <b>nano</b>. Pode a principio ser um pouco complicado localizar o arquivo, pois é comum que o banco armazene traces automáticos para seus processos internos, então é um bom costume criar um identificador para o arquivo para facilitar sua busca.</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">Fazemos isso usando outra variável de sessão, o <b>tracefile_identifier</b>. Exemplo de uso:</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> alter session set tracefile_identifier = 'paulo';</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Session altered.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> alter session set sql_trace = true;</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Session altered.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> select 1 from dual;</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span> 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span" style="white-space: pre;"> </span> 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> alter session set sql_trace = false;</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Session altered.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL> </span></div>
</div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">Agora, basta procurar por todos os arquivos com este identificador no diretório dos arquivos de trace:</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">oracle@hitomi:/u01/app/oracle/diag/rdbms/xe/XE/trace$ ll *paulo*</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">-rw-r----- 1 oracle dba 2351 2011-11-26 21:34 XE_ora_25084_paulo.trc</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">-rw-r----- 1 oracle dba 82 2011-11-26 21:34 XE_ora_25084_paulo.trm</span></div>
<div style="font-family: inherit;">
<br /></div>
</div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">No caso, o </span><span class="Apple-style-span" style="font-family: inherit;">arquivo <b>XE_ora_25084_paulo.trc</b> é o trace gerado para a sessão acima.</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">Ok, agora que temos o trace como utilizá-lo? Uma rápida vista neste arquivo mostrará que mesmo uma sessão tão simples quanto a que apresentei neste exemplo vai popular o arquivo com uma infinidade de comandos que a princípio vão parecer praticamente "criptografados". A verdade é que este arquivo possui uma estrutura bastante lógica, e é possível sim ler ele diretamente para buscar informações. No entanto, não é o nosso neste momento aprender a interpretá-lo, por isso vou passar direto para mostrar a próxima ferramenta que vai simplificar bastante este trabalho. Trata-se do <b>tkprof</b>.</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">O <b>tkprof</b> é um utilitário que faz a conversão do arquivo de trace em um relatório mais "legível" para os seres humanos. Estaremos utilizando ele bastante sempre que houver a necessidade de localizar <i>hotspots</i> de SQL em nossos procedimentos. No caso, isto se deve ao fato de que o trace por si só coleta informação de querys, e não de PL/SQL, o que pode ser uma limitação aparentemente inconveniente, mas existem outras formas de obter esta informação. </span>De qualquer forma, o tkprof é uma ferramenta fundamental para localizar querys problemáticas dentro de hierarquias de procedimentos e funções. Vamos ao seu uso:</div>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">oracle@hitomi:/u01/app/oracle/diag/rdbms/xe/XE/trace$ tkprof XE_ora_25084_paulo.trc paulo.txt</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">TKPROF: Release 11.2.0.2.0 - Development on Sat Nov 26 21:45:40 2011</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">oracle@hitomi:/u01/app/oracle/diag/rdbms/xe/XE/trace$</span></div>
</div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">Simples assim! Passamos o arquivo de trace como entrada e um arquivo txt como saída. A resposta é o arquivo txt apresentando um relatório muito mais legível do que o trace puro. Abaixo, coloco na íntegra o relatório do trace que gerei nos passos acima:</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">oracle@hitomi:/u01/app/oracle/diag/rdbms/xe/XE/trace$ cat paulo.txt</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">TKPROF: Release 11.2.0.2.0 - Development on Sat Nov 26 21:45:40 2011</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Trace file: XE_ora_25084_paulo.trc</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Sort options: default</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">********************************************************************************</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">count = number of times OCI procedure was executed</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">cpu = cpu time in seconds executing </span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">elapsed = elapsed time in seconds executing</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">disk = number of physical reads of buffers from disk</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">query = number of buffers gotten for consistent read</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">current = number of buffers gotten in current mode (usually for update)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">rows = number of rows processed by the fetch or execute call</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">********************************************************************************</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL ID: 1hgzr5xxpmt7h Plan Hash: 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">alter session set sql_trace = true</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">call count cpu elapsed disk query current rows</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parse 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Execute 1 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Fetch 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 1 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Misses in library cache during parse: 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Misses in library cache during execute: 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Optimizer mode: ALL_ROWS</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parsing user id: 48 </span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">********************************************************************************</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL ID: 520mkxqpf15q8 Plan Hash: 1388734953</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">select 1 </span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">from</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> dual</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">call count cpu elapsed disk query current rows</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parse 1 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Execute 1 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Fetch 2 0.00 0.00 0 0 0 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 4 0.00 0.00 0 0 0 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Misses in library cache during parse: 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Optimizer mode: ALL_ROWS</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parsing user id: 48 </span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Number of plan statistics captured: 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Rows (1st) Rows (avg) Rows (max) Row Source Operation</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">---------- ---------- ---------- ---------------------------------------------------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 1 1 1 FAST DUAL (cr=0 pr=0 pw=0 time=8 us cost=2 size=0 card=1)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">********************************************************************************</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">SQL ID: 988n7wn97ptgf Plan Hash: 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">alter session set sql_trace = false</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">call count cpu elapsed disk query current rows</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parse 1 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Execute 1 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Fetch 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 2 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Misses in library cache during parse: 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Optimizer mode: ALL_ROWS</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parsing user id: 48 </span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">********************************************************************************</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">call count cpu elapsed disk query current rows</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parse 2 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Execute 3 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Fetch 2 0.00 0.00 0 0 0 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 7 0.00 0.00 0 0 0 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Misses in library cache during parse: 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Misses in library cache during execute: 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">call count cpu elapsed disk query current rows</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Parse 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Execute 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Fetch 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">------- ------ -------- ---------- ---------- ---------- ---------- ----------</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Misses in library cache during parse: 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 3 user SQL statements in session.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 0 internal SQL statements in session.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 3 SQL statements in session.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">********************************************************************************</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Trace file: XE_ora_25084_paulo.trc</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Trace file compatibility: 11.1.0.7</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Sort options: default</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 1 session in tracefile.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 3 user SQL statements in trace file.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 0 internal SQL statements in trace file.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 3 SQL statements in trace file.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 3 unique SQL statements in trace file.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 47 lines in trace file.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> 17 elapsed seconds in trace file.</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">oracle@hitomi:/u01/app/oracle/diag/rdbms/xe/XE/trace$ </span></div>
<div style="font-family: inherit;">
<br /></div>
</div>
<div>
<span class="Apple-style-span" style="font-family: inherit;">Como você pode ver, no relatório do tkprof estão todos os comandos SQL executados a partir do início do trace. Num procedimento real, as tabelas de resumo apresentadas (com as contagens de <i>parse</i>, <i>execute</i> e <i>fetch</i>) vão acumular os dados das n-vezes que a determinada query for executada. Por exemplo, se eu executasse 100 vezes a query 'select 1 from dual', todas as 100 estariam agregadas na mesma tabela de sumário.</span></div>
<div>
<span class="Apple-style-span" style="font-family: inherit;"><br /></span></div>
<div>
Isto é muito útil para localizar quais querys estão consumindo mais tempo de execução, baseado no seu tempo total decorrido (coluna <i>elapsed </i>do relatório). Uma maneira fácil de analisar este arquivo é executar uma busca por todas as linhas contendo a palavra 'total':</div>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">oracle@hitomi:/u01/app/oracle/diag/rdbms/xe/XE/trace$ grep total paulo.txt </span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 1 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 4 0.00 0.00 0 0 0 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 2 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 7 0.00 0.00 0 0 0 1</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">total 0 0.00 0.00 0 0 0 0</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">oracle@hitomi:/u01/app/oracle/diag/rdbms/xe/XE/trace$ </span></div>
</div>
<div>
<br /></div>
<div>
No caso, este arquivo não é um bom exemplo porque todas as querys foram instantâneas, mas num procedimento mais complexo você poderia localizar exatamente quais são as querys mais pesadas com este comando. No próximo post trarei um exemplo melhor para mostrar como funciona esta técnica.</div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-75272276048812900292011-11-25T21:57:00.001-02:002016-07-25T09:20:06.222-03:00Metodologia para Tuning de Procedimentos - Parte 2No <a href="http://oraculodosul.blogspot.com/2011/11/metodologia-para-tuning-de.html">post anterior</a> eu falei sobre o primeiro requisito para uma tarefa de tuning: a <b>reprodutibilidade.</b> Dando continuidade ao assunto, hoje vou abordar o segundo requisito: o <b>objetivo</b>. Toda tarefa de tuning necessita ter muito bem estabelecido o seu objetivo logo no início do processo. Eu sempre pergunto para as pessoas "Qual é a meta para este procedimento?", ou seja, qual é o tempo de resposta esperado como resultado da tarefa de tuning?<br />
<br />
Estabelecer este tempo logo no início evita que seja gasto um esforço muito grande para otimizar o processo além do necessário e, digo isso principalmente porque, considerando que estamos falando de um processo complexo, <b>sempre</b> é possível extrair mais performance. O grande problema é o nível de <b>esforço</b> que vai ser gasto para obter as melhorias sucessivas, pois a cada nível de melhoria a tendência é que o processo para obter melhora seja mais complexo e mais demorado. Fundamentalmente, encontrar um equilibro entre objetivo de tuning e esforço é o segredo do tuning bem sucedido.<br />
<br />
Algumas vezes o objetivo não está bem definido quando nós recebemos a tarefa, e é aí que ter feito todo o preparo que eu comentei sobre a reprodutibilidade vai entrar no jogo. Primeiro executamos o processo sem nenhuma intervenção para obter uma <i>baseline</i> na qual iremos nos basear durante todo o trabalho. Em alguns casos isso não é possível, como por exemplo, eu já recebi algumas tarefas onde a especificação dizia algo parecido com "este processo não roda mais... leva horas e não termina". Neste tipo de situação a baseline pode ser estabelecida em um processo parcial. Existem várias formas para fazer isto e tratarei de comentar sobre isso adiante.<br />
<br />
Se você conseguir estabelecer a <i>baseline</i> no processo completo melhor, porém em processos muito grandes, ou mesmo, "infinitos", podemos utilizar as seguintes abordagens: 1) gerar um volume de dados de entrada menor para o processo (assumindo que estes dados são estatisticamente relevantes); 2) dividir o processo em etapas e analisando cada uma delas de forma independente ou; 3) utilizar o recurso de amostragem do Oracle (e ele se preocupa em reduzir o volume de dados por você).<br />
<br />
Sobre o recurso de amostragem, talvez um recurso que poucos conheçam, trata-se da clausula <b>SAMPLE</b> do SELECT. Observe:<br />
<br />
<br />
oracle@hitomi:~$ sqlplus paulo/paulo<br />
<br />
SQL*Plus: Release 11.2.0.2.0 Beta on Sat Nov 26 13:45:03 2011<br />
<br />
Copyright (c) 1982, 2010, Oracle. All rights reserved.<br />
<br />
<br />
Connected to:<br />
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Beta<br />
<br />
SQL> create table t as select rownum x from dual connect by level <= 100;<br />
<br />
Table created.<br />
<br />
SQL> select count(*) from t;<br />
<br />
COUNT(*)<br />
----------<br />
100<br />
<br />
SQL> select count(*) from t sample(10);<br />
<br />
COUNT(*)<br />
----------<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>12<br />
<br />
SQL> /<br />
<br />
COUNT(*)<br />
----------<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> 7<br />
<br />
SQL> /<br />
<br />
COUNT(*)<br />
----------<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> 4<br />
<br />
SQL> /<br />
<br />
COUNT(*)<br />
----------<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>11<br />
<br />
SQL> select * from t sample(10);<br />
<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> X<br />
----------<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span> 8<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>15<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>22<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>30<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>76<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>94<br />
<br />
6 rows selected.<br />
<br />
SQL><br />
<div>
<br /></div>
<div>
Neste exemplo, foi criada uma tabela t com 100 linhas. Em seguida, demonstro o uso da cláusula <b>sample</b> com uma amostragem de 10%. Note que, por ser um conjunto de dados pequenos, existe uma grande variação no número de linhas retornadas. Para conjuntos de dados maiores esta cláusula tende a representar subconjuntos bastante significativos.</div>
<div>
<br /></div>
<div>
A grande vantagem do seu uso, também, é o fato de que você não precisa modificar a sua massa de dados de origem e consegue reduzir o tempo de execução necessário para cada teste de alteração no procedimento em que se está fazendo o tuning.</div>
<br />
<br />
Uma vez estabelecidos os critérios de reprodutibilidade, o objetivo do tuning e a <i>baseline</i> de referência, seja esta para a massa de dados completa ou parcial, podemos então partir efetivamente para a tarefa de tuning.<br />
<br />
Nesta próxima etapa precisamos tomar o cuidado de manter um controle rigoroso das alterações que fazemos, alterando de preferência uma coisa de cada vez. As vezes é muito tentador fazer várias modificações ao mesmo tempo, porém corremos sempre o risco de perder a referência e ter que voltar atrás várias vezes até descobrir qual alteração melhorou e qual piorou a performance do processo.<br />
<br />
Eu recomendo o uso de uma planilha do Excel como controle de execuções, alterações, efeitos esperados e efeitos obtidos. Para não tornar este post demasiadamente extenso, continuarei a falar sobre isso na parte 3 desta série... fiquem ligados!Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-8530856754406291412011-11-24T22:56:00.000-02:002016-07-25T09:20:06.231-03:00Metodologia para Tuning de Procedimentos - Parte 1É comum no meu dia-a-dia receber chamados para a otimização de um determinado procedimento ou query que está demasiado lento. Para realizar uma tarefa como esta, o banco nos oferece diversas ferramentas que facilitam bastante a nossa vida, porém sem uma metodologia adequada elas podem não só se mostrarem ineficientes como também prejudicar o processo como um todo.<br />
<div>
<br /></div>
<div>
É por este motivo que eu gostaria de iniciar hoje uma discussão sobre uma metodologia para otimização, focando principalmente em código PL/SQL, mas também comentando alguns aspectos sobre o tuning de querys. Esta é a parte 1 de uma série de artigos que virão na sequencia para comentar sobre este tema.</div>
<div>
<br /></div>
<div>
O primeiro critério para um tuning bem sucedido é a <b>reprodutibilidade</b>. De modo geral eu costumo gastar um bom tempo na preparação do ambiente para que eu possa reproduzir a situação-problema inúmeras vezes. Dependendo do processo isso vai envolver apagar dados de tabelas chave, salvar valores de colunas numa tabela de backup, truncar tabelas inteiras... enfim, é importante mapear todas as condições para um restart limpo e deixar elas a mão em um script de limpeza (pode ser o próprio script de execução da rotina), pois a cada modificação do cenário é necessário recomeçar do zero ou corremos o risco de obter uma falsa sensação de objetivo cumprido e o processo voltar a dar problema nas mãos do usuário.</div>
<div>
<br /></div>
<div>
Uma ressalva importante na questão da reprodutibilidade é que você não pode ignorar as características do banco, ou seja, não se trata apenas de código pois algumas features fundamentais que fazem o banco Oracle ter uma performance excelente podem atrapalhar você na hora do tuning. </div>
<div>
<br /></div>
<div>
Vai ficar mais claro com um exemplo: suponha que o problema da sua query está diretamente relacionada a um excesso de I/O físico (<i>physical reads</i>). No caso, ao executar ela pela primeira vez ela estará bastante lenta... aí você modifica um ou outro código e bota ela para rodar de novo. Para sua surpresa a query executa quase instantâneamente! "Problema resolvido!" você pensa, mas pode estar muito enganado! Acontece que ao executar a primeira vez a query os blocos das tabelas estavam no disco e não na memória... um <i>cache miss</i> no <b>db block cache</b> então solicita a carga das tabelas para memória (este é um processo lento). Ao executar a segunda query, independente dela ser diferente ou não, seu tempo de acesso vai ser mais rápido porque o <i>cache miss</i> agora é um <i>cache hit, </i>ou seja, o banco vai acessar diretamente o dado das tabelas em memória e o gargalo do I/O físico vai aparentemente desaparecer, para voltar apenas quando os blocos em cache forem <i>aged out </i>(removidos).</div>
<div>
<br /></div>
<div>
Uma forma de se ver livre deste viés é fazer um flush do buffer cache:</div>
<div>
<br /></div>
<div>
Alter System Flush buffer_cache;</div>
<div>
<br /></div>
<div>
Porém jamais faça isso em produção, pois este comando não é nada seletivo e <b>todos</b> os blocos em memória são descarregados para o disco. Seus usuários agradecem!</div>
<div>
<br /></div>
<div>
Outro fator que pode impactar é o <i>parsing</i> da query. No Oracle existem duas formas de parse: o <b>hard parse</b> e o <b>soft parse.</b> No hard parse é feita a completa validação e avaliação da query, desde a elaboração do melhor plano de execução até a construção do result set. Este parse é bastante demorado em função de que diversos algoritmos são aplicados para escolher o plano ótimo. Por outro lado, o soft parse se baseia num plano de execução pronto e após uma validação mais rápida da query parte direto para a fase de execução (<i>execute</i>) e aquisição (<i>fetch</i>) dos dados. Por este motivo o soft parse é muito mais rápido e é sempre desejável.</div>
<div>
<br /></div>
<div>
Agora, sempre que uma query não está em memória o Oracle necessita fazer um hard parse, mas uma vez carregada ele vai fazer o soft parse sempre que possível. Portanto, ao executar pela segunda vez uma query a tendência é que ela seja mais rápida por não necessitar mais do parse completo. Mais uma vez existe um comando para eliminar este viés, que é:</div>
<div>
<br /></div>
<div>
Alter system flush shared_pool;</div>
<div>
<br /></div>
<div>
Estes dois comandos são um tanto radicais, pois ambos destroem completamente os dados carregados em memória. Por isto, não recomendo o seu uso exceto em ocasiões muito especiais. Além disto, existem algumas formas de contornar estas otimizações do Oracle de forma menos agressiva, como por exemplo, no caso do parsing, executar um gather stats da tabela alvo com o parametro no_invalidade=>false. Este parâmetro força a reavaliação dos planos de todas as querys que dependem da tabela. Ou ainda, se o parâmetro <b>cursor_sharing</b> da instância estiver setado para <b>exact</b>, basta fazer uma modificação simples da query como inserir um espaço em branco ou modificar a caixa de uma letra que a query será tratada como uma query totalmente nova (a comparação das querys no Oracle é textual/binária).</div>
<div>
<br /></div>
<div>
No caso do db block cache, eu procuro nivelar o terreno para o <i>tuning</i> desconsiderando a primeira execução e utilizando como métrica sempre a segunda em diante. Existem algumas outras técnicas, mas para não me estender muito vou deixar para comentar sobre isso num post futuro.</div>
<div>
<br /></div>
<div>
Sumarizando então o tópico da reprodutibilidade, é importante garantir uma metodologia para executar o procedimento sempre nas mesmas condições, tanto em termos de dados como de infraestrutura de banco. Esta preocupação é necessária para termos uma <i>baseline</i> para trabalhar com a qual poderemos medir as influências das nossas alterações e identificar resultados positivos e negativos das intervenções. Existem alguns fatores externos que também devemos sempre procurar minimizar, como por exemplo, a concorrência, mas nem sempre temos poder sobre isso... neste caso o importante é lembrar que ela existe e que o seu resultado nem sempre estará "puro".</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com0tag:blogger.com,1999:blog-8208730947417975246.post-32229253834055156322011-11-23T19:52:00.000-02:002016-07-25T09:19:10.591-03:00Caso de Performance 2: Tabelas temporáriasEu comentei no <a href="http://oraculodosul.blogspot.com/2011/11/performance-com-plsql.html">post inicial sobre performance em PL/SQL</a> que as tabelas temporárias em Oracle, se mal utilizadas, podem causar uma grande dor de cabeça em termos de perfomance ruim. O caso que eu utilizei como referência, se vocês se recordam, foi o da passagem de parâmetros em massa para uma procedure, dentro de um loop.<br />
<div>
<br /></div>
<div>
Pode parecer um caso bastante específico, porém é uma prática comum em outros bancos onde esta estratégia não só é perfeitamente válida como também proporciona uma ótima performance. O caso em questão é que no Oracle existe uma alternativa melhor e mais performática, que é a passagem de valores múltiplos por arrays. Cabe aqui uma ressalva, que pelo fato de arrays serem estruturas de memória, não convém passar milhões de registros desta forma. De modo geral passamos no máximo algumas centenas ou poucos milhares de registros de uma vez só, visto que mais do que isso pode resultar em um grande consumo de memória pelo nosso processo. Já testemunhei casos extremos onde alocar um array para muitos registros derrubou o banco por consumo excessivo de memória.</div>
<div>
<br /></div>
<div>
Para estas situações onde se processam muitos milhares ou mesmo milhões de registros cabe sim o uso de tabelas temporárias, no entanto ainda fica o alerta para que este tipo de processamento jamais seja feito em loops com o uso de comandos DELETE para limpar a temporária entre cada passada.</div>
<div>
<br /></div>
<div>
Dito tudo isto, vamos ao exemplo do dia. Eu demorei um pouco para elaborar um caso para este exemplo justamente pela sua especificidade. De modo geral, minha intenção era elaborar uma situação onde: existe um loop externo que controla o processamento; a cada iteração deste loop é carregado um conjunto de dados em uma estrutura (tabela temporária ou array) e; finalmente, esta estrutura é processada em um subprocedimento. A idéia é avaliar o impacto de passar esta massa de dados para o subprocedimento através de uma tabela temporária e através de um array.</div>
<div>
<br /></div>
<div>
No exemplo o loop de controle está programado para 100 repetições e a cada loop são carregadas 100 linhas no "portador" (array ou tabela temporária). Para simplificar Aa etapa do processamento, é feita simplesmente a inserção destes dados em uma tabela física. Tomei o cuidado de no exemplo com array fazer o insert na tabela utilizando o comando FORALL para eliminar a influencia de trocas de contexto (comparativamente um FORALL equivale a um INSERT SELECT, pois ambos são resolvidos em apenas uma troca de contexto). O mesmo vale para a carga dos portadores: no caso da tabela temporária é feito um INSERT SELECT e para carga do array utilizo um BULK COLLECT.</div>
<div>
<br /></div>
<div>
Os tempos, mais uma vez, são representados em centésimos de segundo.</div>
<div>
<br /></div>
<div>
<div>
oracle@hitomi:~$ sqlplus paulo/paulo</div>
<div>
<br /></div>
<div>
SQL*Plus: Release 11.2.0.2.0 Beta on Wed Nov 23 13:15:34 2011</div>
<div>
<br /></div>
<div>
Copyright (c) 1982, 2010, Oracle. All rights reserved.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Connected to:</div>
<div>
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Beta</div>
<div>
<br /></div>
<div>
SQL> create global temporary table temp_table(x number);</div>
<div>
<br /></div>
<div>
Table created.</div>
<div>
<br /></div>
<div>
SQL> create table heap_table(x number);</div>
<div>
<br /></div>
<div>
Table created.</div>
<div>
<br /></div>
<div>
SQL> set serveroutput on</div>
<div>
SQL> declare </div>
<div>
2 t number := dbms_utility.get_time();</div>
<div>
3 procedure lp_dummy is</div>
<div>
4 begin</div>
<div>
5 insert into heap_table</div>
<div>
6 select * from temp_table;</div>
<div>
7 end;</div>
<div>
8 begin</div>
<div>
9 for r in (select rownum from dual connect by level <= 100)</div>
<div>
10 loop</div>
<div>
11 delete temp_table;</div>
<div>
12 insert into temp_table select rownum from dual connect by level <= 100;</div>
<div>
13 lp_dummy;</div>
<div>
14 end loop;</div>
<div>
15 dbms_output.put_line('hsecs=' || to_char(dbms_utility.get_time()-t));</div>
<div>
16 end;</div>
<div>
17 /</div>
<div>
hsecs=112</div>
<div>
<br /></div>
<div>
PL/SQL procedure successfully completed.</div>
<div>
<br /></div>
<div>
SQL> / </div>
<div>
hsecs=116</div>
<div>
<br /></div>
<div>
PL/SQL procedure successfully completed.</div>
<div>
<br /></div>
<div>
SQL> /</div>
<div>
hsecs=120</div>
<div>
<br /></div>
<div>
PL/SQL procedure successfully completed.</div>
<div>
<br /></div>
<div>
SQL> rollback;</div>
<div>
<br /></div>
<div>
Rollback complete.</div>
<div>
<br /></div>
<div>
SQL> declare</div>
<div>
2 t number := dbms_utility.get_time();</div>
<div>
3 type typ_heap is table of heap_table%rowtype index by pls_integer;</div>
<div>
4 a_heap typ_heap;</div>
<div>
5 procedure lp_dummy is</div>
<div>
6 begin</div>
<div>
7 forall i in a_heap.first .. a_heap.last</div>
<div>
8 insert into heap_table values a_heap(i);</div>
<div>
9 end;</div>
<div>
10 begin</div>
<div>
11 for r in (select rownum from dual connect by level <= 100)</div>
<div>
12 loop</div>
<div>
13 select rownum bulk collect into a_heap from dual connect by level <= 100;</div>
<div>
14 lp_dummy;</div>
<div>
15 end loop;</div>
<div>
16 dbms_output.put_line('hsecs=' || to_char(dbms_utility.get_time()-t));</div>
<div>
17 end;</div>
<div>
18 /</div>
<div>
hsecs=23</div>
<div>
<br /></div>
<div>
PL/SQL procedure successfully completed.</div>
<div>
<br /></div>
<div>
SQL> / </div>
<div>
hsecs=26</div>
<div>
<br /></div>
<div>
PL/SQL procedure successfully completed.</div>
<div>
<br /></div>
<div>
SQL> /</div>
<div>
hsecs=25</div>
<div>
<br /></div>
<div>
PL/SQL procedure successfully completed.</div>
<div>
<br /></div>
<div>
SQL> </div>
</div>
<div>
<br /></div>
<div>
Nitidamente a abordagem por arrays é significativamente mais rápida, sendo de 4 a 5 vezes mais rápida neste exemplo. Vale ressaltar que o grande impacto da abordagem por tabelas temporárias, além do tempo de delete, é o gasto de recursos inserindo undo e redo para estas operações, que literalmente são descartáveis.</div>
Anonymoushttp://www.blogger.com/profile/02759924073306319531noreply@blogger.com2