ATUALIZADO EM 12/03/2015
Olá pessoal,
No artigo de hoje explicarei em detalhes a resposta de uma pergunta que é realizada por alunos em quase toda turma presencial de
SQL ou
SQL Tuning que eu leciono:
Existe diferença de desempenho entre instruções SQL escritas no padrão ANSI ou no padrão Oracle? Antes de dar a resposta, vamos entender primeiro o que é SQL e o que são os padrões
ANSI SQL e
Oracle.
Resumindo, a Structured Query Language, mais conhecida pela sigla SQL, é uma linguagem que foi desenvolvida no início dos anos 70, pela IBM, para manipular bancos de dados relacionais. A partir de então, diversos fabricantes de Sistemas Gerenciadores de Bancos de Dados Relacionais (SGBDRs), como por exemplo a Oracle, começaram a desenvolver versões próprias da linguagem SQL (chamadas de dialetos ou extensões) e isso levou à necessidade da criação de uma linguagem SQL padronizada.
Com a sua popularização e sucesso, organizações como o
Instituto Americano Nacional de Padrões (ANSI) e a
Organização Internacional de Padronização (
ISO), resolveram padronizar a linguagem SQL. Em 1986 foi criado um padrão ANSI e em 1987 foi criado um padrão ISO. A partir de então, surgiram várias versões do padrão SQL, onde cada versão acrescenta novos comandos ou funcionalidades. Seguem abaixo alguns detalhes sobre algumas versões do padrão ANSI:
- SQL-86:
- Primeira versão da linguagem, lançada em 1986, consiste basicamente na versão inicial da linguagem criada pela IBM.
- SQL-92:
- Lançada em 1992, inclui novos recursos tais como tabelas temporárias, novas funções, expressões nomeadas, valores únicos, instrução CASE etc.
- SQL:1999 (SQL3):
- Lançada em 1999, foi a versão que teve mais recursos novos significativos, entre eles: a implementação de expressões regulares, recursos de orientação a objetos, queries recursivas, triggers, novos tipos de dados (boolean, LOB, array e outros), novos predicados etc.
- SQL:2003:
- Lançada em 2003, inclui suporte básico ao padrão XML, sequências padronizadas, instrução MERGE, colunas com valores auto-incrementais etc.
-
SQL:2006:
- Lançada em 2006, não inclui mudanças significativas para as funções e comandos SQL. Contempla basicamente a interação entre SQL e XML
Atualmente, os principais fabricantes de SGBDRs, implementam em seus Bancos de Dados, além das instruções SQL referentes ao seu "dialeto", as instruções SQL do padrão ANSI mais recente. No caso de instruções SQL no SGBD Oracle, o que o pessoal costuma chamar de padrão Oracle, é o dialeto SQL da Oracle. As instruções dos dialetos normalmente surgem quando o fabricante necessita implementar recursos no SGBD, que ainda não possuem instruções correspondentes no padrão ANSI .
Um exemplo muito utilizado de comando SQL do dialeto Oracle, é a ligação OUTER JOIN, que o pessoal costuma escrever utilizando o caractere +. Vejam a diferença nos exemplos abaixo e na imagem 01:
Instrução SQL com ligação representando LEFT JOIN utilizando o dialeto Oracle:
SELECT e.first_name || e.last_name NAME,
D.DEPARTMENT_NAME
FROM HR.EMPLOYEES E,
HR.DEPARTMENTS D
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID (+);
Instrução SQL com ligação representando LEFT JOIN utilizando o padrão ANSI:
SELECT E.FIRST_NAME || E.LAST_NAME NAME,
D.DEPARTMENT_NAME
FROM HR.EMPLOYEES E
LEFT JOIN HR.DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
 |
| Imagem 01 - Instrução SQL no padrão Oracle e padrão ANSI |
Agora que já sabemos o que é o padrão Oracle e o que é o padrão ANSI, vou comentar sobre alguns itens que me fazem defender o uso do padrão ANSI, antes de falar especificamente sobre a performance dos 2 padrões:
1- Permite que você migre a aplicação contendo as instruções SQL para outro BD sem ter que fazer qualquer alteração;
2- As ligações entre colunas são mais fáceis de serem identificadas, pois ficam fora da cláusula WHERE, separadas das condições de filtro. Essa característica pode muitas vezes facilitar manutenções futuras e evitar queries ruins. Já vi muita gente escrever queries no padrão Oracle e esquecer de incluir na cláusula WHERE a(s) coluna(s) necessária(s) para efetuar a ligação correta entre 2 tabelas. Neste caso, para evitar linhas duplicadas resultantes do produto cartesiano gerado pela falta da(s) coluna(s) necessária(s) na ligação, o desenvolvedor inclui a cláusula DISTINCT, "uma grande gambiarra para corrigir um erro de programação, que gera degradação da performance da query". Ligações no padrão ANSI forçam a inclusão de uma cláusula ON que obrigam a inclusão de uma ligação entre as tabelas;
Bom... agora quanto à performance, de um modo geral, não há diferença entre o plano de execução gerado nos 2 padrões, até porque, internamente, muitas instruções escritas no padrão ANSI são convertidas para o dialeto Oracle, porém o padrão ANSI tem uma vantagem bastante conhecida, como por exemplo, permitir fazer um
FULL OUTER JOIN com melhor performance e com menor complexidade do que a alternativa correspondente no dialeto Oracle. Nas Imagens 02 e 03 vemos uma instrução SQL equivalente e seu respectivo plano de execução nos padrões Oracle e ANSI. Nelas podemos observar (destacado em vermelho) que o custo da instrução SQL no padrão ANSI (7) é bem menor que o do dialeto Oracle (15) e isso implica em melhor desempenho na primeira.
 |
| Imagem 02 - Full Outer Join no dialeto Oracle |
 |
| Imagem 03 - Full Outer Join no padrão ANSI |
O padrão ANSI é ensinado atualmente nos treinamentos oficiais de instruções SQL da Oracle e nos meus treinamentos
Aprendendo SQL! Por todos os motivos que citei neste artigo, sugiro fortemente a
utilização do padrão ANSI!
Bom pessoal, por hoje é só! Espero que tenham gostado!
[]s
Referências:
- SQL: http://pt.wikipedia.org/wiki/SQL
- ANSI SQL: http://allthingsoracle.com/ansi-sql/
- Padrão SQL e sua Evolução: http://www.ic.unicamp.br/~geovane/mo410-091/Ch05-PadraoSQL-art.pdf
- História do Padrão SQL: http://www.altabooks.com.br/capitulos_amostra/sql_cap_amostra.pdf
- Oracle Database SQL Reference: http://docs.oracle.com/cd/B12037_01/server.101/b10759/queries006.htm
- Oracle Database SQL Language Reference 11GR2:
http://docs.oracle.com/cd/E11882_01/server.112/e10592/queries006.htm#i2054062
- Execution Plans: Part 1 Finding plans
- http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#SQLRF01702