instruções para tuning de sql
TRANSCRIPT
-
8/4/2019 Instrues para Tuning de SQL
1/7
Instrues para Tuning de SQL
1. Padronizao na escrita de SQLs:
Cada comando SQL processado basicamente em trs fases:
Anlise (parse) Execuo (execute) Retorno das linhas selecionadas (fetch).
A padronizao na escrita de SQLs permite a reutilizao dos mesmos, inclusive pordiferentes sesses e usurios, diminuindo sensivelmente o tempo e o consumo de recursos
na realizao do parse (verificao sinttica, semntica e montagem do plano de acesso)dos comandos.
O objetivo no ter 300 usurios utilizando o mesmo SQL, mas ter um mesmo SQL, que executado 300 vezes ou mais, sendo reutilizado todas as vezes.
Assim, abaixo vo algumas instrues para atingir este objetivo:
a) padronizao no uso de maisculas/minsculas: recomendamos utilizarsempre maisculas.
b) padronizao no uso de espaos em branco entre as clusulas do comando:recomendamos utilizar sempre 1 (um) espao em branco.
c) utilizao de bind variables ao invs de literais concatenados s clusulasdo comando. Essa a instruo mais importante quanto formao do SQL, uma vezque o mesmo comando, se construdo sem as bind variables, passar pelo processo deparse cada vez que for executado, como no exemplo a seguir:
SELECT PESS_NOME FROM PESSOAS WHERE PESS_IDEN = 1;SELECT PESS_NOME FROM PESSOAS WHERE PESS_IDEN = 2;
Devendo ser utilizada a seguinte forma:SELECT PESS_NOME FROM PESSOAS WHERE PESS_IDEN = :V_IDEN;
Ou, no caso de utilizao de JDBC, da seguinte forma:
SELECT PESS_NOME FROM PESSOAS WHERE PESS_IDEN = ?;
Marcelo Ferreira - [email protected]
1
-
8/4/2019 Instrues para Tuning de SQL
2/7
Alm disso, o nome e o tipo das bind variables devem ser iguais entre 2 comandos. Oexemplo a seguir ilustra esse caso:
SELECT PESS_NOME FROM PESSOAS WHERE PESS_IDEN = :V_IDEN;SELECT PESS_NOME FROM PESSOAS WHERE PESS_IDEN = :V_ID;
As formaes acima no so reutilizadas entre si, devendo ser utilizada somente aseguinte forma:
SELECT PESS_NOME FROM PESSOAS WHERE PESS_IDEN = :V_IDEN;
No caso do JDBC, no informado o nome. Internamente, os ? so substitudos por :1, :2, etc, o que garante que os nomes sero os mesmos. Mas o tipo de atribuio usado,setInt ou setLong por exemplo, faz diferena, e o SQL pode no ser reutilizado.
2. Evitar o uso de sentenas do tipo SELECT * FROM TABELA:
Em lugar disso, procurar definir sempre as colunas que vo ser necessrias. Isso evitar quedados no necessrios sejam transferidos do Banco de Dados para a aplicao, alm degarantir que uma eventual alterao na tabela no cause uma interrupo no funcionamentodo SQL. Assim, utilizar uma formao como segue:
SELECT PESS_NOME, PESS_DATA_NASC FROM PESSOAS;
3. Fazer uso de procedures, functions e triggers:
Em operaes que demandam um grande nmero de acessos ao Banco de Dados,retornando para a aplicao um pequeno numero de linhas, deve-se fazer uso de proceduresou functions de Banco de Dados. Por exemplo: rotinas de cpia de tabelas, atualizaes emlote, relatrios complexos, etc.
Em operaes que podem ser executadas automaticamente pelo Banco de Dados, utilizartriggers. Por exemplo: totalizao de campos, replicao de campos, gravao de tabelas dehistricos, etc.
4. Evitar o uso de funes nas clusulas WHERE:
O uso de funes nas clusulas WHERE pode impedir a utilizao de ndices no acessos tabelas. Por exemplo:
Marcelo Ferreira - [email protected]
2
-
8/4/2019 Instrues para Tuning de SQL
3/7
SELECT PESS_NOME FROM PESSOASWHERE TO_CHAR(PESS_DATA_NASC,YYYYMMDD) = :DATA_NASC;
Esse comando no utilizaria um ndice que porventura existisse na colunaPESS_DATA_NASC, devendo ser utilizada a seguinte forma:
SELECT PESS_NOME FROM PESSOASWHERE PESS_DATA_NASC = TO_DATE(:DATA_NASC,YYYYMMDD);
Alm disso, o uso de funes para formatao das colunas selecionadas deve ser substitudopor tratamento especfico no prprio programa. Isso garante uma certa independncia doBanco de Dados utilizado, alm de aliviar o processamento por parte do Banco de Dados.Por exemplo:
SELECT DECODE(COL1,1,Compra,2,Aluguel,...) INTO :V_TIPOFROM TABELA1;
Deve ser substitudo por:
SELECT COL1 INTO :V_COL1 FROM TABELA1;
E, no programa, fazer um tratamento apropriado do tipo:
CASE V_COL1WHEN 1 THEN V_TIPO := CompraWHEN 2 THEN V_TIPO := AluguelWHEN 3 THEN V_TIPO := Leasing...
5. Evitar o uso de expresses com operandos de tipos diferentes:
Em expresses cujos operandos so de tipo diferente, por exemplo:
SELECT COL2 FROM TABELA1 WHERE COL1 = 1;
Onde COL1 definida do tipo CHAR(1), uma converso implcita sempre ocorre, e essaexpresso transformada para:
SELECT COL2 FROM TABELA1 WHERE TO_NUMBER(COL1) = 1;
Com isso, qualquer ndice que exista na COL1 deixar de ser utilizado. Deve ser utilizada aseguinte forma:
Marcelo Ferreira - [email protected]
3
-
8/4/2019 Instrues para Tuning de SQL
4/7
SELECT COL2 FROM TABELA1 WHERE COL1 = TO_CHAR(1);
6. Uso de clusulas IN versus EXISTS:
Via de regra, o que deve direcionar o uso dessas clusulas a comparao entre aquantidade de registros que deve retornar na subquery e a quantidade de registros que deveretornar na query externa, ou seja, qual das clusulas WHERE mais seletiva. Porexemplo:
SELECT D.ID, D.CREDOR FROM DOCUMENTOS DWHERE EXISTS(SELECT NULL FROM PARCELAS PWHERE P.DOC_ID = D.ID
AND P.VENCIMENTO = TO_DATE(:V_DATA,YYYYMMDD));
Supondo que exista um ndice na coluna DOC_ID da tabela PARCELAS, o plano deexecuo para o comando anterior fazer uma leitura total (full table scan) na tabelaDOCUMENTOS, pois a clusula WHERE pouco seletiva, no indicando uso de nenhumndice, e depois fazer uma leitura pelo ndice em DOC_ID na tabela PARCELAS.
Supondo que exista um ndice na coluna VENCIMENTO da tabela PARCELAS, o SQLpoderia ser escrito usando a clusula IN, forando o plano de execuo a fazer primeirouma leitura pelo ndice em VENCIMENTO na tabela PARCELAS, que mais seletivo,retornando poucas linhas, e depois fazer uma leitura pelo ndice em ID na tabela
DOCUMENTOS, uma vez que a clusula WHERE agora indica a utilizao do mesmo.
SELECT D.ID, D.CREDOR FROM DOCUMENTOS DWHERE D.ID IN(SELECT DOC_ID FROM PARCELAS PWHERE P.VENCIMENTO = TO_DATE(:V_DATA,YYYYMMDD));
7. Reduzir o nmero de chamadas ao Banco de Dados:
Quando apropriado, utilize INSERT, UPDATE, ou DELETE ... RETURNING ... para
atualizar e selecionar dados com uma nica chamada. Alm de otimizar o acesso ao Bancode Dados, diminui o trfego na rede. Veja um exemplo:
DELETE FROM TABELA1 WHERE COL1 = :V_COL1 RETURNING COL2, COL3;
8. Evitar o uso de clusulas GROUP BY, ORDER BY e DISTINCT:
Marcelo Ferreira - [email protected]
4
-
8/4/2019 Instrues para Tuning de SQL
5/7
O uso dessas clusulas sempre provoca a leitura de todas as linhas que satisfazem aclusula WHERE do SQL, a sua classificao, e, somente depois, o retorno das mesmas
para a aplicao.
Muitas vezes o uso dessas clusulas exigido pelo projeto das tabelas e necessidades daaplicao. Porm, na maioria das vezes, existem alternativas para evitar o seu uso.
A clusula ORDER BY, por exemplo. uma boa alternativa descarregar os dadosdesordenados dentro de uma tabela interna e, depois, efetuar a classificao nessa tabelainterna segundo os critrios requeridos, que poderiam ser variveis, sem a necessidade defazer nova chamada ao Banco de Dados.
J a clusula DISTINCT, muitas vezes, denota a falta de uma join condition na clusula
WHERE, ou seja, devido a uma falha na composio das join conditions o SQL retornalinhas repetidas, e, para resolver, coloca-se o DISTINCT. Isso um erro grave, e deve serevitado.
9. Ateno especial clusula WHERE:
Podemos dizer que existem dois tipos de condies a serem codificadas na clusulaWHERE: join conditions e filter conditions.
As join conditions so as condies de ligao e correspondncia entre duas tabelas.
Normalmente so montadas em cima de foreign keys e tem boa chance de serematendidas por ndices. Exemplo: WHERE P.DOC_ID = D.ID;
J as filter conditions so as condies de filtro aplicadas a uma tabela de cada vez.Exemplo: WHERE P.VENCIMENTO = TO_DATE(:V_DATA,YYYYMMDD).
Assim, importante que as join conditions sejam as primeiras a serem codificadas econtemplem todas as colunas que compem a ligao entre as tabelas, ou seja, todas ascolunas da foreign key. Isso facilita muito a codificao da clusula WHERE e garanteque no resultar um produto cartesiano indesejado.
A ordem das join conditions tambm importante, sendo que as colunas da tabeladirecionadora (driving table) devem aparecer esquerda nas comparaes e os joinsmais seletivos devem aparecer primeiro. No exemplo a seguir, a driving table a TABA,supondo ser a que apresenta maior seletividade na aplicao da filter condition:
SELECT INFO FROM TABA A, TABB B, TABC CWHERE A.KEY1 = B.KEY1
Marcelo Ferreira - [email protected]
5
-
8/4/2019 Instrues para Tuning de SQL
6/7
AND A.KEY2 = C.KEY2AND A.ACOL BETWEEN :ALOW AND :AHIGHAND B.BCOL BETWEEN :BLOW AND :BHIGHAND C.CCOL BETWEEN :CLOW AND :CHIGH;
Normalmente, a escolha da driving table e do driving index baseada na aplicao dasfilter conditions. Assim, tabelas que apresentam menor cardinalidade efetiva, ou seja,suas chaves apresentam maior nmero de valores e menor nmero de ocorrncias com omesmo valor, so candidatas a serem a driving table.
s vezes conveniente efetuar um estudo do contedo da tabela, a fim de obter umconhecimento maior do estado dos dados dentro da mesma. Isto pode auxiliar bastante nacodificao da clusula WHERE.
Como ltima recomendao, vale ressaltar que para garantir a utilizao de algum ndice, a
clusula WHERE deve contemplar pelo menos a primeira coluna do ndice. No adiantainformar as outras colunas, se a primeira no estiver na clusula WHERE, o ndice no serusado.
10. Sempre usar o EXPLAIN PLAN:
muito importante que seja gerado e revisto o plano de execuo de todos os SQLs paragarantir uma boa performance. E essa operao feita em duas etapas.
Para gerar o plano de execuo, usamos o comando EXPLAIN PLAN, cujo formato o
seguinte:
EXPLAIN PLANSET STATEMENT_ID = 'XXX'FOR
SQL a ser examinado;
Para verificar o plano gerado, o comando o seguinte:
SELECT LPAD(' ',2*(LEVEL-1))||OPERATION||' '||OPTIONS||' '||OBJECT_NAME||' '||DECODE(ID, 0, 'COST = '||POSITION) "QUERY PLAN"
FROM PLAN_TABLESTART WITH ID = 0 AND STATEMENT_ID = 'XXX'CONNECT BY PRIOR ID = PARENT_ID AND STATEMENT_ID = 'XXX';
A dica salvar esses comandos em arquivos (scripts) de fcil acesso para serem executadosa partir do SQL Plus. Os nomes dos arquivos poderiam ser ExplainPlan.sql e
Marcelo Ferreira - [email protected]
6
-
8/4/2019 Instrues para Tuning de SQL
7/7
ConsultaPlan.sql. E para que se possa fazer novo EXPLAIN com os mesmos scripts,acrescentar ao script de consulta o seguinte comando:
DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = 'XXX';
importante lembrar que o plano de execuo gerado deve ser examinado com cuidado eavaliado segundo algumas premissas. Por exemplo, nem sempre um table full scan ruim. No caso de tabelas pequenas, ele at desejado. O acesso por ndice nem sempre amelhor alternativa. No caso de ser necessrio acessar todas as linhas de uma tabela, o tablefull scan pode apresentar melhor resultado. O fundamental observar possveis falhas naconstruo do SQL, por exemplo, se um ndice que deveria estar sendo usado no estdevido falta de uma join condition.
Marcelo Ferreira - [email protected]
7