Beruflich Dokumente
Kultur Dokumente
Objetivo : nivelar o Conhecimento de todos os Participantes sobre os elementos básicos da Arquitetura física e lógica
do RDBMS Oracle, para que possa haver pleno Aproveitamento das técnicas de otimização e dos levantamentos de
ineficiências que ocorrerão no Curso.
Instância e database : o software RDBMS Oracle é um sistema composto por diversos módulos que devem ser
carregados para a memória – não há um único executável monolítico que é responsável por todo e qualquer
processamento. Esses módulos normalmente são implementados como processos residentes em memória no
Operacional (ou no caso do Windows, como threads de um processo oracle.exe) , e são carregados por um
executável temporário, o bootstrap loader, que também cria uma área de memória compartilhada a ser utilizada
pelos processos background Oracle, a SGA (System Global Area), de acordo com os settings especificados num
arquivo de configuração (pfile ou spfile), criando o que se chama de database em mount status . Após isso, os
arquivos em disco com dados (tablespaces dos usuários) e com metadados (tablespace SYSTEM, principalmente)
serão abertos, a informação necessária lida/carregada e o database é dito ABERTO.
Os processos background mais notáveis a se destacar sob a ótica da performance e tuning são :
Archiver Processes (ARCn) : são os processos encarregados de arquivar (copiar) os arquivos com logs de
alterações do database. Se a sessão do database e/ou a task do SO forem apontados pelas ferramentas e
procedimentos de tuning que discutiremos no Curso, isso pode indicar ineficiência no hardware e/ou na
configuração do dispositivo de gravação utilizado, ou no tamanho do logfile (Arquivamento é em termos
básicos uma cópia do logfile cheio, e logfiles muito pequenos podem levar á cópias frequentes), ou então
Aplicação gerando quantidade excessiva de alterações, que precisam ser logadas (caso em que o Tuning
deve ser feito na Aplicação ou, em alguns casos, alterando-se o modelo físico da aplicação e/ou as estruturas
de armazenamento no database , em especial utilização de INSERTs em modo NOLOGGING) .
Checkpoint Process (CKPT) : para maior eficiência, a informação lida a partir dos arquivos de dados é
mantida em memória nas áreas apropriadas da SGA, mesmo após COMMIT – posteriormente,
vagarosamente e em background, a informação comitada presente em memória é gravada pelo processo
DBWR. O trabalho do Checkpoint é registrar nos controles existentes no cabeçalho dos datafiles a
atualização feita nos datafiles , juntamente com o SCN (um número sequencial que indica o horário/tempo
da atualização) . Obviamente, quanto mais tempo demorar um checkpoint isso é undicador que mais
informação está sendo mantida em memória e mais archives serão necessários numa eventual recuperação,
o que interfe em SLAs.
Database Writer Process (DBWn) : é o processo (ou processos, se o database estiver configurado para
utilizar múltiplos DBWRs) chamado(s) por quaisquer outros processos background que precisem gravar
informações na área de dados dos datafiles. Para fins de tuning, ele se relaciona com alta quantidade de
informações sendo alteradas, ou com ineficiências no acesso para gravação aos datafiles, EM ESPECIAL não
uso de Direct e/ou Asynchronous I/O .
Job Queue Processes : são os processos que executam JOBs programados pelo usuário (ou alguns Jobs
administrativos internos, no caso de databases 10g e superiores) – para fins de tuning não há alteração
possível no database, mas sim no scheduling de Jobs e no Tuning da rotina sendo executada pelo JOB.
Log Writer Process (LGWR) : as alterações feitas num database (com poucas exceções, tal como INSERTs em
modo NOLOG) precisam ser registradas, de modo a permitir a recuperação em caso de crash. No RDBMS
Oracle as alterações são logadas primeiro num buffer específico na SGA (log buffer) e posteriormente
periodicamente esse buffer é passado para disco (inserido nos log files) pelo LGWR. Ineficiências apontando
para este processo podem indicar Aplicação gerando número excessivo de alterações ou issues na gravação
dos logfiles, e em casos mais raros tamanho ou localização dos logfiles em si.
Process Monitor Process (PMON) e System Monitor Process (SMON) : PMON é o processo responsável por
liberar recursos no SO após o término de um processo de usuário servindo a uma conexão, e SMON libera
recursos nas sessões terminadas, além de fazer rotinas administrativas não especializadas (como
shrink/diminuição de áreas de rollback/undo e temporárias não mais em uso ou desnecessárias para
recover).
Para fins de tuning, quando estes processos e/ou a sessão correspondente são apontado como relevante ,
provavelmente há algum bug levando à desconexão/perda de conexões e/ou a processos zumbis.
:
Tablespaces, Blocos, Extents e Segmentos: Num bd Oracle as informações são armazenadas em tabelas, compostas
por linhas (também chamadas de tuplas ou registros), sendo que todas as informações duma linha residem em
colunas (também chamadas de campos ou atributos). Fisicamente em disco o espaço de armazenamento disponível
para o banco Oracle é composto por arquivos (os chamados datafiles), agrupados em tablespaces, sendo cada datafile
dividido em blocos (de tamanho normalmente fixo, mas opcionalmente ajustável, tanto a nível de database quanto
para cada tablespace de usuário). Cada bloco contém várias linhas duma dada tabela, e automaticamente o RDBMS
mantém em cada bloco uma lista das linhas que contém.
Esses fatos permitem duas otimizações básicas :
a) O fato dos datafiles serem divididos em pedaços (blocos) de tamanho fixo e conhecido permite, uma vez
identificado o bloco aone a informação reside, que a mesma seja recuperada sem uma varredura total do
arquivo : sabendo-se que a informação está no bloco X e que o block size é n bytes, o RDBMS solicita uma
operação de file seek, posicionando um ponteiro na posição x*n do datafile necessário, e lendo apenas os n bytes
após esta posição
b) Sempre é feito um aceso por bloco : assim, mesmo o menor SQL, que acesse apenas uma linha, no primeiro
acesso aos dados terá que acessar ao menos o bloco aonde a linha desejada reside. Uma vez lido o bloco do disco
(é a operação chamado PIO, Physical I/O), ele automaticamente vai para o cache de blocos em RAM do banco (DB
BLOCK BUFFER, área dentro da SGA), de onde caso necessário as demais linhas futuramente serão lidas, poupando
novo acesso físico ao disco.
Uma leitura do cache é chamada de LIO, Logical I/O. A importância de se compreender este mecanismo é que as
tools Oracle de teste e otimização que usaremos neste Treinamento dão informações de I/O em número de blocos
: esta é a razão , por exemplo, de a quantidade de I/Os em disco (PIOs) ser menor numa segunda execução do
mesmo SQL, estamos nesse caso vendo o reflexo dos blocos em cache não mais serem lidos do disco.
DEMONSTRAÇÃO
O Objetivo desta Demonstração é evidenciar a estrutura de dados do RDBMS e exemplificar as tools básicas de
report de LIOs (Logical I/Os) e PIOs (Physical I/Os)
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SYSTEM:@orcl:SQL>set timing on
SYSTEM:@orcl:SQL>set autotrace on
SYSTEM:@orcl:SQL>select * from hr.employees where rownum < 10;
9 rows selected.
Elapsed: 00:00:00.18
Execution Plan
----------------------------------------------------------
Plan hash value: 1424567464
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 1197 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| EMPLOYEES | 107 | 14231 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------
1 - filter(ROWNUM<10)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
168 recursive calls
0 db block gets
232 consistent gets
22 physical reads
0 redo size
1789 bytes sent via SQL*Net to client
437 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
9 rows processed
(neste report :
recursive calls = SQLs internos, executados nas tabelas internas do RDBMS para encontrar os metadados necessários, fazer a compilação (PARSE) do SQL, verificar as
permissões e status dos objetos envolvidos, etc
db block gets = blocos (contendo dados de usuário OU contendo dados internos do database) sem alteração/transação aberta (lidos em modo corrente, como
vieram do disco) que necessitaram ser acessados para responder ao SQL
consistent gets = blocos obtidos em modo consistente, ie, para a leitura dos quais o RDBMS verificou se existiam alterações em curso e em caso positivo buscou nos
blocos de UNDO/ROLLBACK a versão da informação tal como estava antes da alteração não-comitada em curso.
DB BLOCK GETS + CONSISTENT GETS = LIOs
physical reads = physical IO, PIOs
redo size = qtdade de redo gerado para se poder eventualmente desfazer o SQL antes do COMMIT
sorts (memory)/(disk) = qtdade de sorts
)
Repetindo-se o mesmo SQL, vemos o efeito do CACHING reduzindo qtd de PIOs (pois dados antes vindos do
disco passaram para o cache) quanto de LIOs (pois o SQL foi compilado e o plano em memória foi usado,
Evitando diversas consultas às tabelas internas e a necessidade de se montar plano de execução e validar
completamente o SQL e os objetos dependentes) :
SYSTEM:@orcl:SQL>l
1* select * from hr.employees where rownum < 10
SYSTEM:@orcl:SQL>/
9 rows selected.
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 1424567464
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 1197 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| EMPLOYEES | 107 | 14231 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------
1 - filter(ROWNUM<10)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
1789 bytes sent via SQL*Net to client
437 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
9 rows processed
SYSTEM:@orcl:SQL>
Continuando, além disto para maior eficiência quando uma tabela é criada ou quando novos dados são acrescentados
e mais espaço se faz necessário, a alocação em disco não é feita um bloco por vez, mas sim é alocada uma quantidade
fixa de blocos pré-definida para a tabela, o chamado EXTENT : a importância do extent é que no caso de acessos a
mais de uma linha e dados duma só vez, e/ou varredura de toda a tabela em busca de dados, tipicamente serão lidos
extents duma só vez, e não bloco a bloco, e os blocos desses extents vão para o cache (respeitando limites internos do
banco, normalmente 10% do cache, para evitar saturação), o que se refletirá em consultas futuras. Naturalmente,
informações não são apenas lidas num bd, mas também alteradas e deletadas, E por paradigma no bd Oracle leituras
nunca sofrem interferência/bloqueio por alterações, E uma alteração não comitada NUNCA se reflete numa leitura :
assim, nesses casos o bloco desejado é lido para o cache igualmente, mas é feita uma cópia dele no estado atual
antes da alteração (o chamado undo ou rollback), o bloco original em cache será alterado, mas é a cópia que será lida
pelas outras sessões que não podem ver as alterações não comitadas. Para que seja possível se re-aplicar uma
operação a qualquer tempo, também é gerado o redo, ie, os bytes da alteração no bloco são armazenados em RAM e
depois no disco, nos redo log files. Da mesma forma, num ambiente multi-usuário, pode acontecer que o banco
receba dois pedidos de acesso ao mesmo bloco, assim há um mecanismo de controle de acesso aos blocos, uma
“trava” simples e rápida em memória, um indicador de que naquele instante há alguém acessando o bloco, outras
sessões devem aguardar, esse controle é o LATCH, que não pode ser confundido com locks/bloqueios: já os LOCKs
impedem o acesso a linhas ou tabelas inteiras, são de longa duração, e impedem totalmente, fazem falhar o acesso
por parte de outrem, enquanto os latches são de curtíssima duração (frações de segundo, tipicamente), e em caso de
falha de obtenção de um dado latch a sessão interessada não falha, simplesmente fica em waiting por alguns
momentos e retoma a tentativa de acesso.
Os conceitos de latch, lock, undo e redo serão importantes em pontos futuros deste Workshop.
DEMONSTRAÇÃO
O Objetivo desta demonstração é evidenciar (através da Instrumentação básica presente num RDBMS Oracle, que
será usada intensamente neste Treinamento) o registro das operações internas :
Metodologia : abriremos 3 terminals (um para consultar e outros dois acessando os mesmos objetos ao mesmo
tempo, para Evidenciar)
(notar que as estatísticas/eventos do database são incrementais , então o que nos interessa é a diferença entre
duas coletas)
SID SERIAL#
------ --------
39 37
Table created.
(na sessão monitorada vou executar um SQL que tenho certeza não existir antes) :
SYSTEM:@orcl:SQL>
SYS:AS SYSDBA@orcl:SQL>select t1.sid, t1.name, t1.value Valor1, t2.value Valor2, t2.value - t1.value Diferenca
from TEMP_STATS_TBL t1, TEMP_STATS_TBL t2
where t1.sid = t2.sid
and t1.name = t2.name
and t1.exec# = 1
and t2.exec# = 2
and t1.value <> t2.value
order by 1,2;
66 rows selected.
Table dropped.
(abro nova sessão , refaço a monitoração e executo exatamente o mesmo SQL, notar que os parses e consumo de
hardware diminuíram) :
SYSTEM:@orcl:SQL>exit
SID SERIAL#
------ --------
39 11
SYSTEM:@orcl:SQL>
Table created.
SYSTEM:@orcl:SQL>
SYS:AS SYSDBA@orcl:SQL>insert into TEMP_STATS_TBL (
select sid, name, value, 2 exec#
from v$sesstat ss, v$statname sn
where sn.statistic#=ss.statistic#
and sid=39);
SYS:AS SYSDBA@orcl:SQL>select t1.sid, t1.name, t1.value Valor1, t2.value Valor2, t2.value - t1.value Diferenca
from TEMP_STATS_TBL t1, TEMP_STATS_TBL t2
where t1.sid = t2.sid
and t1.name = t2.name
and t1.exec# = 1
and t2.exec# = 2
and t1.value <> t2.value
order by 1,2;
39 rows selected.
Notar que diminuiu sensivelmente a quantidade de PARSEs de SQLs, isso foi devido ao cache – dificilmente essa
estatística de performance chega a zero, pois em qualquer momento há SQLs os mais diversos sendo executados
num banco de dados (inclusive os SQL recursivos, internos, gerados pelo próprio RDBMS, que se controla via
tabelas, acessadas via SQL) - , mas houve Aproveitamento.