Funções analiticas LAG/LEAD

Ambas as funções tem como sua sintaxe parecidas:

LAG  (value_expression [,offset] [,default]) OVER ([query_partition_clase] order_by_clause)
LEAD (value_expression [,offset] [,default]) OVER ([query_partition_clase] order_by_clause)

LAG

Esta é uma função analitica. Que provem o acesso a mais que um registro de uma tabela ao mesmo tempo sem precisar fazer um join na própria tabela self join. A busca irá retornar uma ou mais registros anteriores a da possição atual (current).

value_expression - É a expressão que irá retornar da query.
offset - É opcional, caso não seja informar o padrão é 1. Onde este é o campo que podes informar quantos registros deverá retornar.
default - É opcional, caso não seja informado o valor será null.
query_partition_clase - É opcional pois se tiveres particionamento podes colocar a clausula de particionamento .
order_by_clause - É opcional pois desta forma irá informar a ordem que queres pegar a informação anterior.

Exemplo para simplificar:
Para fins estatisticos podemos verificar quanto em estoque temos que ter de um determinado produto ou tivemos que ter entre um mês e outro.

drop table estoque;
create table estoque (produto char(1), dat date, qtde number);
insert into estoque select 'A',trunc(sysdate-((dbms_random.value(1,90))*30/10)),trunc(dbms_random.value(1,100)) from dual connect by level < = 100;
insert into estoque select 'B',trunc(sysdate-((dbms_random.value(1,90))*30/10)),trunc(dbms_random.value(1,100)) from dual connect by level <= 100;
insert into estoque select 'C',trunc(sysdate-((dbms_random.value(1,90))*30/10)),trunc(dbms_random.value(1,100)) from dual connect by level <= 100;
commit;

select produto,to_char(dat, 'FMYYYY/MM', 'nls_date_language=portuguese') mes,
sum(qtde) soma_normal,
sum(qtde) + nvl(lag(sum(qtde))
over(order by to_char(dat, 'FMYYYY/MM', 'nls_date_language=portuguese')),
0) ACUMULADO
from estoque
where produto ='A'
group by (produto,to_char(dat, 'FMYYYY/MM', 'nls_date_language=portuguese'))
order by produto,to_char(dat, 'FMYYYY/MM', 'nls_date_language=portuguese');

PRODUTO    MES        SOMA_NORMAL    ACUMULADO
A        2008/1    514            514
A        2008/2    1073        1587
A        2008/3    805            1878
A        2008/4    287            1092
A        2008/5    633            920
A        2008/6    355            988
A        2008/7    236            591
A        2008/8    625            861
A        2008/9    457            1082

LEAD

Simplesmente é o contrario do LAG, ele irá pegar o proximo valor.

Funções analiticas
LEAD
LAG

Fake/Virtual Index (Indice Virtual)

Após muitas leituras sobre tuning e performance, achei algo interessante e rápido para postar aqui no site e que possa ser muito util para os programadores e administradores de Banco Oracle.
Preciso melhorar a performance do meu SQL, será que esse indice vai me ajudar?

Uma boa pergunta, pois até então criar um indice em uma tabela sempre há um custo.
Porem como irei saber se aquele indice vai ser útil mesmo sem poder testar na prática?
Uma das novas features do 11g é criar indices invisiveis, não interferindo no ambiente(produção como no exemplo), uhuuuu claro estou dizendo em produção nada em ambiente teste, pois nem todo mundo tem essa maravilha que é um ambiente de teste bom e legal p/ testar sua aplicação.
Ai vem o X da questão, nas versões anteriores(8i, 9i e 10g) não tem nada para nos ajudar?
Isso mesmo lendo um bucado achei o FAKE INDEX ou VIRTUAL INDEX.

Ok, agora vou mostrar com um exemplo simples do seu funcionamento.

1. Lembrando que esta prática serve para o Oracle informar, se o indice a ser criado, realmente será usado pelo otimizador e seu custo.
2. Ao ser criado, estara somente no dicionario de dados e não será criado o indice mesmo, não haverá segmentos (NOSEGMENT).
3. Há um parametro não documentado pela oracle, que faz parte do Oracle Enterprise Manager Tuning Wizard para que esta pratica seja bem sucessida.

Ex.:
Tabela teste com 398698 registros

SQL> DESC teste
Nome                                      Nulo?    Tipo
----------------------------------------- -------- ----------------------------
CAMPO1                                             CHAR(10)
CAMPO2                                    NOT NULL NUMBER(11)
CAMPO3                                             VARCHAR2(4000)
 
SQL> SELECT campo1,count(1) FROM teste
2  GROUP BY campo1;
 
CAMPO1       COUNT(1)
---------- ----------
111111111       57789
444444444       10000
BBBB            10000
CCCCCCCCCC      10000
DDDDDDDDDD      10000
EEEEEEEEEE      10000
FFFFFFFFFF      10000
GGGGGGGGG       10000
HHHHHHHHH       19999
JJJJJJJJJ       10000
RRRRRRRRR       10000
WWWWWWWWW        6551
ddddddddd       10000
hhhhhhhhh       10000
iiiiiiiii       10000
mmmmmmmmm       10000
nnnnnnnnn       10000
ppppppppp       10000
qqqqqqqqq       50000
rrrrrrrrr       10000
uuuuuuuuu       20000
vvvvvvvvv       10000
xxxxxxxxx       64359
yyyyyyyyy       10000

Agora conhecendo a tabela de teste

Código:

SQL> SET autotrace traceonly EXPLAIN
SQL> SELECT * FROM teste WHERE campo1 = 'xxxxxxxxx';
Plano de Execução
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=116 Card=16612 Bytes=315628)
1    0   TABLE ACCESS (FULL) OF 'TESTE' (Cost=116 Card=16612 Bytes=315628)

Criando o índice
Código:

SQL> CREATE INDEX teste_i01 ON teste(campo1) nosegment;

Agora ver se ele vai usar o indice criado:

SQL> SELECT * FROM teste WHERE campo1 = 'xxxxxxxxx';
Plano de Execução
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=116 Card=16612 Bytes=315628)
1    0   TABLE ACCESS (FULL) OF 'TESTE' (Cost=116 Card=16612 Bytes=315628)

Agora deves estar se perguntando porque o meu select não utilizou o meu indice?
Bingo agora vamos para o que nos interessa.

SQL> ALTER session SET "_use_nosegment_indexes" = true;
Plano de Execução
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=36 Card=16612 Bytes=315628)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TESTE' (Cost=36 Card=16612 Bytes=315628)
2    1     INDEX (RANGE SCAN) OF 'TESTE_I01' (NON-UNIQUE) (Cost=2 Card=16612)

Obs.: Não esqueça de fazer um analyze na tabela.
Para utilizar por definitivo o indice, deve-se dropar o indice virtual e cria-lo sem a clausula NOSEGMENT.

Importante: Como o indice é virtual sem segmento, o tempo de execução não pode ser calculado pois o indice virtual serve somente para ver seu custo quando for criado realmente. No 11g a história muda.

ref.
Oracle 11g Database New Features - 1.2.9.4 Invisible Indexes
Creating an Invisible Indexes
Making an Index Invisible
Dica - Indices Virtuais

Banco de Dados Oracle alcança novo recorde mundial

Benchmark TPC-C analisa o banco de dados Oracle 11g com Windows executado em servidor Dell PowerEdge 2900

A Oracle anunciou o novo recorde mundial no benchmark TPC-C para o banco de dados Oracle® 11g Standard Edition One executado no Windows(1). Com esse resultado, a Oracle passa a deter as três primeiras posições na categoria das dez na relação preço x performance do benchmark TPC-C. Essa análise é mais uma demonstração do compromisso da Oracle em fornecer escalabilidade e desempenho com baixo custo para clientes de qualquer porte.

O banco de dados Oracle 11g Standard Edition One executado em um servidor Dell PowerEdge 2900, equipado com um processador Intel Quad-Core Xeon de 2,66 GHz e sistema operacional Windows alcança 97.083 transações por minuto com relação preço x performance de US$ 0,68/tpmC. Isso representa o melhor custo por transação por minuto já alcançado com o benchmark TPC-C. Dessa forma, a Oracle permanece líder na categoria com os melhores resultados em Windows e Linux.

"O resultado do benchmark demonstra mais uma vez que a Oracle pode oferecer desempenho inigualável por um preço acessível, independentemente do sistema operacional escolhido pelo cliente", afirma Sushil Kumar, diretor sênior da Gerência de Produto de Disponibilidade, Capacidade de Gerenciamento e Desempenho do Banco de Dados da Oracle. "O banco de dados Oracle 11g Standard Edition One que roda no servidor Dell PowerEdge 2900 fornece aos clientes benefícios inegáveis, com uma solução escalável e de alta performance para ambientes baseados em Windows."

O Oracle 11g Standard Edition One é um banco de dados acessível e de recursos completos para servidores com até dois soquetes. Oferece desempenho e segurança corporativa, é simples de gerenciar, compatível com versões superiores e pode ser dimensionado facilmente, conforme a demanda do cliente. Para obter mais informações sobre o banco de dados Oracle 11g Standard Edition One, visite o site www.oracle.com/database/std_one.html.

Sobre o TPC-C

O TPC-C é um benchmark de OLTP (processamento de transações on-line) desenvolvido pelo Transaction Processing Performance Council (TPC). O benchmark TPC-C define um padrão rigoroso para calcular o desempenho e a relação custo x performance medidas em transações por minuto (tpmC) e US$/tpmC, respectivamente. Mais informações estão disponíveis no site www.tpc.org. As 10 mais do TPC-C por preço x performance: www.tpc.org/tpcc/results/tpcc_price_perf_results.asp.

Sobre o banco de dados Oracle 11g

O Oracle é o único banco de dados projetado para grid computing. Com mais de 400 novos recursos, 36 mil pessoas ao mês de desenvolvimento e 15 milhões de horas de testes, o banco de dados Oracle 11g torna a gestão das informações empresariais mais fácil, permitindo que os clientes dediquem mais tempo aos seus negócios e inovem com agilidade. O Oracle 11g oferece desempenho superior, escalabilidade, disponibilidade, segurança e facilidade de gerenciamento em um grid de servidores e armazenamento padrão de mercado.

Fonte: Segs.com.br

Query’s SQL para XML

Rapidinha: O oracle tem como default a função de transformar query's sql para XML

Exemplo:

 
SET long 5000
SET pagesize 5000
SET linesize 132
SELECT
     dbms_xmlgen.getxml(’SELECT * FROM user_tables’) XMLQUERY
 FROM dual;