instruções para tuning de sql

Upload: marcelobol

Post on 07-Apr-2018

222 views

Category:

Documents


0 download

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