Você está na página 1de 4

Artigo SQL Magazine 1 - Otimizao de Comandos SQL

Artigo da Revista SQL Magazine - Edio 1. 4 http://www.devmedia.com.br/artigo-sql-magazine-1-otimizacao-de-comandossql/6926

Regras de Utilizao de ndices Um ndice ser usado se : o ndice existir; a coluna ndice for referenciada na clusula WHERE; Igualdade: SELECT e.empno, e.ename FROM emp e WHERE e.job = CLERK; Intervalo ilimitado: SELECT e.empno, e.ename FROM emp e WHERE e.job > CLERK; Intervalo limitado: SELECT e.empno, e.ename FROM emp e WHERE e.job BETWEEN CLERK AND JONES; A criao de ndices deve ser feita com critrio. A atualizao (inserts, updates e deletes) em tabelas de dados gera uma ao equivalente nos ndices, sendo que o tempo de atualizao dos ndices superior ao de atualizao das tabelas, pois alm da colocao do registro em seqncia dentro do ndice necessrio a atualizao dos ramos das rvores do ndice. Considerando os detalhes acima, ndices devem ser criados somente quando necessrio, pois a sua simples existncia no implica em melhoria de performance, podendo muitas vezes ser a origem de perda de performance. Condies de no utilizao de ndices 1) Funes ou Operadores Aritmticos Se a coluna ndice for modificada por uma funo ou por operadores aritmticos (+,-,*,/), o ndice no ser utilizado. Um ndice sobre SAL ou ENAME no ser utilizado nos seguintes casos: SELECT e.ename, e.empno FROM emp e WHERE e.sal*12 = 2400; SELECT e.ename, e.empno FROM emp e WHERE SUBSTR(e.ename,1,3) = JON Nos casos acima, as seguintes modificaes permitem o uso de ndice: SELECT e.ename, e.empno FROM emp e WHERE e.sal = 2400/12 SELECT e.ename, e.empno FROM emp e WHERE e.ename LIKE JON% 2) Converso de Dados A converso de dados pode inibir a utilizao do ndice da coluna em questo se usado inadvertidamente. Na seguinte sentena, um ndice sobre a coluna HIREDATE no ser usado: SELECT e.ename, e.empno FROM emp e WHERE TO_CHAR(e.hiredate, month dd,yyyy) = january 23,1982 Esta mesma sentena SQL, modificada, usar o ndice: SELECT e.ename, e.empno FROM emp e WHERE e.hiredate = to_date(january 23,1982 , month dd,yyyy) Se na clusula WHERE os predicativos utilizam dados de tipos diferentes, o ORACLE automaticamente converte um deles sem a preocupao sobre a melhor escolha para a utilizao

Um ndice pode ser usado para testes de:

Mesmo um aplicativo bem projetado poder experimentar problemas de desempenho se a frase SQL que usa for mal construda. Falhas no projeto do aplicativo e na construo do SQL causam a maioria dos problemas de desempenho em bancos de dados projetados adequadamente. Veremos neste artigo como melhorar o comando SQL, para garantir maior performance em sua execuo, tendo como base o ORACLE. A forma como o banco de dados se organiza para responder a requisio de um aplicativo diretamente influenciada pela maneira como a frase SQL construda. Existem vrios pontos a serem observados nesta construo. O caminho mais curto o uso de ndices para auxiliar a pesquisa mas, importante observar, a simples criao de um ndice nem sempre o melhor caminho para otimizao de comandos SQL. Alguns conceitos importantes Antes de partir para como e quais as melhores formas de se aplicar e se escrever comandos SQL importante relembrarmos alguns conceitos importantes. Existem dois mtodos bsicos utilizados pelos SGDBs para localizar dados, tambm conhecidos como caminhos de acesso. So eles: - Full Table Scan: Leitura seqencial, bloco por bloco, de toda a tabela. Neste mtodo, so verificados registro a registro os critrios de seleo. - Index Search: Procura de um ndice sobre a coluna definida no critrio de seleo, identificando a localizao dos registros qualificados. O ORACLE possui seu prprio mecanismo de otimizao, chamado otimizador, para executar comandos SQL e dinamicamente determinar que caminho de acesso seguir, dependendo das informaes disponveis. O melhor caminho de acesso , geralmente, o uso de ndices, mas isso nem sempre verdadeiro. Por exemplo, se existir uma forma de identificar diretamente um registro pelo seu endereo fsico, a resposta ser mais rpida. (neste caso estamos falando do rowid, endereo fsico do registro em uma tabela ORACLE). Ex.: SELECT rowid INTO :emp_rowid FROM EMP WHERE emp.empno = 5353 FOR UPDATE OF emp.ename; UPDATE emp SET emp.ename = "OTIMIZADOR" WHERE rowid = :emp_rowid; Excluindo registros duplicados: DELETE FROM emp e WHERE e.rowid > (SELECT MIN(x.rowid) FROM emp x WHERE x.empno = e.empno); Algumas informaes otimizador: para auxiliar o acesso do

Verificar nas colunas dentro da clusula WHERE: Que colunas so ndices; Que colunas esto definidas como NOT NULL; Que ndices podem ser usados.

possvel ajudar o otimizador a procurar o melhor caminho de acesso atravs da criao de ndices e clusters, o que ser considerado a partir de agora.

dos ndices. A converso por default escolhida, pelo caso mais comum (Ex.: O valor de uma coluna, onde o tipo number, rowid ou date, comparado com uma constante de tipo char). Em qualquer caso muito recomendado o controle da converso dos dados de maneira explcita. 3) Caso de colunas com valores NULL Os ndices no contm referncia para valores do tipo null. Isto quer dizer que os valores null podem ser recuperados somente atravs de uma leitura seqencial completa da tabela (Full Table Scan). No comando abaixo o ndice sobre a coluna COMM no ser utilizado: SELECT e.ename, e.empno FROM emp e WHERE e.comm is null Neste cdigo o otimizador considera que a maioria dos registros dentro da tabela so valores not null e ir escolher a leitura seqencial (Full Table Scan): SELECT e.ename, empno FROM emp e WHERE e.comm > = 100 A velocidade de execuo depender dos dados da tabela. Se a maioria dos registros contiver valores no nulos, a clusula "comm is not null" ser mais rpida. Os ndices concatenados no tero referncia para os registros onde todas as colunas que o compem tiverem valores nulos. 4) Caso de predicados com a condio "NOT EQUAL" Os ndices sobre colunas referenciadas pela condio not equal no sero usadas. O otimizador considera que o nmero de registros que iro satisfazer a condio ser maior do que os registros que no a satisfazem. O ndice sobre DEPTNO no ser usado na seguinte sentena SQL: SELECT e.ename, e.empno FROM emp e WHERE e.deptno !=10 No comando abaixo, o ndice sobre deptno ser utilizado: SELECT e.ename, e.empno FROM emp e WHERE not e.deptno > 20 O ORACLE executar a sentena SQL como e.deptno <= 20 5) Casos de sentenas SQL com clusula "ORDER BY" A clusula ORDER BY aumenta consideravelmente a necessidade de recursos para execuo de uma sentena SQL. Em geral, tabelas temporrias sero necessrias para operao de sort. possvel evitar a utilizao de tabelas temporrias se um ndice sobre a coluna alvo do order by existir. As seguintes condies devem ser cumpridas: - A coluna order by deve ser definida com not null; - A coluna order by deve ser uma simples coluna ndice ou as primeiras colunas de ndice concatenado; - A clusula order by deve conter somente colunas e no expresses; - No deve haver qualquer clusula group by, distinct ou for update; - No deve haver nenhum outro acesso alternativo que seja prioritrio sobre o ndice da coluna order by; A seguinte sentena SQL ser executada via ndice em DNAME se os requisitos mencionados acima forem respeitados: SELECT d.dname FROM dept d order by d.dname; SELECT d.dname, d.deptno FROM dept d WHERE d.loc = dallas order by d.dname; SELECT d.dname, d.loc FROM dept d WHERE d.dname != accouting order by d.dname;

Na sentena abaixo, se um ndice sobre a coluna LOC existir, tornar-se- prioritrio e o ndice sobre dname no ser usado: SELECT d.dname, d.deptno FROM dept d WHERE d.loc = dallas order by d.dname; 6) Casos de sentenas SQL contendo funes MAX ou `MIN Um ndice ser usado para executar uma sentena SQL com MAX ou MIN se as seguintes condies forem satisfeitas: MAX ou MIN devem ser apenas expresses da lista de seleo; - A lista de seleo no deve ter qualquer outro operador de concatenao ou adio a no ser somente MAX ou MIN; - A lista de seleo no deve conter qualquer outra coluna a no ser uma simples ocorrncia da coluna como agrupamento de MAX ou MIN; - A sentena SQL no pode ser um JOIN; - A clusula WHERE e group by no podem ser utilizadas; - A coluna alvo do MAX ou MAX deve ser indexada ou fazer parte das primeiras colunas de um ndice concatenado. A seguinte sentena SQL utilizar um ndice sobre a coluna SAL: SELECT (max(e.sal)*2) + 10000 FROM emp e; 7) Sentenas SQL recuperam informaes sobre uma simples tabela Uma sentena SQL pode ter vrios ndices nicos e/ou no nicos disposio do otimizador. A escolha do ndice a ser usado depende da presena de: - ndices nicos e no nicos: os ndices nicos sero favorecidos sobre os ndices no nicos. - Vrios ndices no nicos: os registros identificados pelo caminho de acesso do ndice condutor (o primeiro nome na sentena SQL) sero unidos com aquele identificado por outro ndice. A meta identificar os registros pertencentes a todos os ndices. Se o otimizador no tiver clara escolha concernente a qual ndice usar, ento ir arbitrariamente escolher o primeiro mencionado dentro da sentena SQL como ndice condutor (Driving Index). 8) Caso de sentena SQL com interseo de vrios predicados de igualdade dentro da clusula WHERE com ndice no nico. O ndice no nico ser sorteado pela coluna rowid a fim de minimizar o nmero de comparaes necessrias. Se ns temos ndice no nico sobre JOB e DEPTNO: SELECT e.ename FROM emp e WHERE e.job = manager and e.deptno = 20; a. Procura a primeira ou prxima referncia do ndice sobre job (driving index) contendo manager. b. Procura a primeira ou a prxima referncia do ndice deptno contendo valor 20. Compara as duas rowid. - Se as duas forem iguais, registro encontrado. Vai a prxima referncia de "a." e compara com a prxima referncia de "b.". - Se forem diferentes guarda a referncia de "a." e passa a prxima referncia de "b.". - c. Continua a procura at que no existam mais referncias sobre o ndice de job (driving index). 9) Caso de sentena SQL com interseo de um

predicado de igualdade com um predicado sem limite, dentro da clusula WHERE com ndice no nico. Somente o ndice sobre a igualdade ser usado. No exemplo que segue, se ndices no nicos existirem sobre as colunas JOB e DEPTNO, o ndice sobre JOB ser utilizado, os registros correspondentes sero recuperados e verificada a validade do segundo predicado. SELECT e.ename FROM emp e WHERE e.job = manager and e.deptno > 10 10) Caso de ndice Concatenado ndices concatenados so ndices formados por vrias colunas representados como se fosse simplesmente uma nica coluna. a) Interseo de vrios predicados de igualdade. Se um ndice concatenado existir sobre DEPTNO e JOB, somente uma referncia ser necessria para localizar a rowid correspondente: SELECT e.ename FROM emp e WHERE e.job = manager and e.deptno = 10 b) Interseo de predicados sem limite com predicados de igualdade. Se um ndice concatenado existir sobre DEPTNO e JOB, ser utilizado para executar a seguinte sentena SQL : SELECT e.ename FROM emp e WHERE e.job = manager and e.deptno > 10 c) Interseo de predicado sem limite. Se um ndice concatenado existir sobre DEPTNO e JOB, ser utilizado para executar a seguinte sentena SQL: SELECT e.ename FROM emp e WHERE e.job > manager and e.deptno > 10 d) Utilizao parcial ou total dos ndices concatenados. O otimizador pode somente usar a ou as primeira(s) parte(s) do ndice concatenado. No seguinte caso, um ndice concatenado foi criado sobre as colunas EMPNO, ENAME e DEPTNO: A seguinte sentena concatenado: SQL usa plenamente o ndice

SQL. O otimizador favorecer a utilizao do ndice nico. No seguinte caso o ndice no nico existe em SAL e um ndice nico em EMPNO: SELECT e.ename FROM emp e WHERE e.sal = 3000 and e.empno = 7902 O ndice nico ser usado para procurar a rowid correspondente ao empno = 7902. Nos registros recuperados sero verificados o valor de sal. 12) Caso de vrios ndices na mesma sentena SQL. Se vrios ndices nicos esto disponveis, o otimizador ir escolher o primeiro mencionado na sentena SQL. Por exemplo, se ndices nicos existirem sobre ENAME e EMPNO, e um ndice no nico existir sobre SAL, a seguinte sentena SQL ser executada sobre o ndice ENAME SELECT e.deptno FROM emp e WHERE e.sal = 3000 and e.ename = scott and e.empno = 7602

Otimizao da clusula OR (Unio de predicados) O caminho de acesso determinado como se a clusula OR e suas ramificaes estivessem ausentes. O caminho determinado considerando cada ramificao da clusula OR separadamente. Exemplo A - ndice existente sobre SAL e JOB. SELECT e.ename FROM emp e WHERE e.deptno = 10 and (e.sal = 3000 or e.job = clerk) Anlise: 1) Para DEPTNO = 10 - Pesquisa seqencial na tabela; 2) Para SAL = 3000 - ndice no nico sobre SAL; Para JOB = clerk - ndice no nico sobre JOB; Neste caso, o caminho de acesso identificado por "2" melhor que o identificado por "1", ento a clusula OR otimizada para utilizao dos ndices. Exemplo B - Somente ndice sobre SAL utilizando a mesma sentena do exemplo A Anlise: 1) Para DEPTNO = 10 - Pesquisa seqencial na tabela 2) Para SAL = 3000 - ndice no nico sobre SAL Para JOB = clerk - Pesquisa seqencial na tabela Os dois caminhos de acesso identificado por "2" no so melhores que o identificado por "1", ento os ndices no sero utilizados e ocorrer uma pesquisa seqencial na tabela. O otimizador na Clusula OR exige a presena dos ndices utilizveis dentro de cada coluna referenciada dentro da clusula OR. Verificando o Caminho de Acesso do otimizador Podemos verificar o caminho de acesso utilizado pelo SGDB para executar uma determinada frase SQL. Chamaremos esse caminho de Acesso de Plano de Execuo. No plano de execuo so verificados todos os procedimentos feitos pelo SGDB, como utilizao ou no de ndices, clusters, rowid, alm da verificao da quantidade de passos realizados pelo banco para execuo do comando. Este procedimento muito til, pois pode ser utilizado como recurso para verificarmos se as alteraes efetuadas em um comando realmente otimizam a execuo do mesmo. A verificao do plano de execuo feita no Oracle atravs do comando EXPLAIN PLAN. A sintaxe do comando a seguinte: EXPLAIN PLAN

SELECT * FROM emp e WHERE e.empno = 7369 and e.ename = smith and e.depnto = 20 SELECT * FROM emp e WHERE e.ename = smith and e.empno = 7369 and e.deptno = 20 As seguintes sentenas SQL utilizam parcialmente o ndice concatenado: Uso parcial do ndice usando somente EMPNO e ENAME: SELECT * FROM emp e WHERE e.empno = 7369 and e.ename = smith Uso parcial do ndice usando somente EMPNO e ENAME : SELECT*FROM emp e WHERE e.empno = 7369 and e.deptno = 20 As seguintes sentenas SQL no usam o ndice : SELECT * FROM emp e WHERE e.ename = smith and e.deptno = 20 SELECT * FROM emp e WHERE e.ename = smith SELECT * FROM emp e WHERE e.deptno = 20 11) Casos de ndice nico e no nico na mesma sentena

SET STATEMENT_ID = 'COMAND_ID' INTO OUTPUT FOR COMANDOSQL; Onde: - COMAND_ID um String identificador para posterior visualizao do plano de execuo. - OUTPUT tabela onde o plano de execuo gerado. O usurio que executar o EXPLAIN PLAN deve ter direitos de INSERT sobre a mesma. O comando para criao desta tabela indicado na Listagem 1. O Script para criao desta tabela chama-se UTLXPLAN.SQL e instalado juntamente com Oracle e a sua localizao depende da verso do banco. - COMANDOSQL o comando a ser analisado.

EXPLAIN PLAN SET STATEMENT_ID = 'SQLMagazine Com Indice' INTO PLAN_TABLE FOR SELECT * FROM EMP WHERE EMPNO = 50; A verificao do plano de execuo feita de seguinte forma: SELECT SUBSTR(LPAD(' ',2*(LEVEL-1))||operation,1,50) operation, options, object_name, position FROM PLAN_TABLE START WITH id = 0 AND statement_id = 'SQLMagazine Com Indice' CONNECT BY PRIOR id = parent_id AND statement_id = 'SQLMagazine Com Indice'; O resultado com o plano de execuo o seguinte:

Analisando este resultado comprovamos que o ndice referente a chave primria foi utilizado. Vamos verificar agora o mesmo comando alterado: EXPLAIN PLAN SET STATEMENT_ID = 'SQLMagazine Sem Indice' INTO PLAN_TABLE FOR SELECT * FROM EMP WHERE TO_CHAR(EMPNO) = 50; A verificao do plano de execuo feita de seguinte forma: SELECT SUBSTR(LPAD(' ',2*(LEVEL-1))||operation,1,50) operation, options, object_name, position FROM PLAN_TABLE START WITH id = 0 AND statement_id = 'SQLMagazine Sem Indice' CONNECT BY PRIOR id = parent_id AND statement_id = 'SQLMagazine Sem Indice'; Para verificao do plano de execuo gerado pelo EXPLAIN PLAN devemos consultar a tabela informada no comando. Este procedimento pode ser efetuado de vrias maneiras, uma delas a que segue: SELECT SUBSTR(LPAD(' ',2*(LEVEL-1))||operation,1,50) operation, options, object_name, position FROM OUTPUT START WITH id = 0 AND statement_id = 'COMAND_ID' CONNECT BY PRIOR id = parent_id AND statement_id = 'COMAND_ID'; Onde, COMAND_ID um String identificador do plano de execuo informado no EXPLAIN PLAN OUTPUT tabela onde o plano de execuo gerado. Vamos exemplificar a execuo do EXPLAIN PLAIN validando a seguinte informao: Um ndice utilizado se ele existir e se a coluna que faz parte deste ndice estiver contida na clausula WHERE do comando SQL. Este mesmo ndice no utilizado se existirem funes de converso de dados envolvendo esta coluna. Em outras palavras: a execuo do comando SELECT * FROM EMP WHERE EMPNO = 50 utilizar o ndice da chave primria, que contm a coluna EMPNO, e a execuo do comando SELECT * FROM EMP WHERE TO_CHAR(EMPNO) = 50, no utilizar o ndice. Utilizaremos o comando da Listagem 1 para criao da tabela que receber o plano de execuo, com o nome de PLAN_TABLE. Em seguida executaremos o EXPLAIN PLAN para verificao da utilizao do ndice com o seguinte comando:

Este resultado mostra que a utilizao do ndice foi anulada pela funo aplicada a coluna. Concluso Os cuidados a serem tomados com o acesso a dados da aplicao so parte importante de um projeto. A forma como as consultas so escritas e como o banco de dados est projetado influencia diretamente na performance do produto. Esses fatores no devem andar separados. Na maioria dos casos necessria a perfeita integrao entre a consulta escrita e o estado do banco de dados. Muitas vezes uma simples arrumao na consulta, trocando algumas clusulas ou mudando um pouco a lgica das condicionais, garante um ganho na velocidade de execuo e resposta da mesma. No esquea nunca de analisar se o ndice a ser criado realmente necessrio, para no adicionar um mais um processo para o seu banco. Boa sorte e bons projetos! Sobre o Autor: Everson Borges Volaco
Everson Borges Volaco (everson@rhealeza.com.br) desenvolvedor e instrutor certificado Borland, com experincia em aplicaes cliente/servidor, usando Delphi, Interbase e Oracle. Possui trs certificaes oficiais Borland: Borland Delphi 7.0, Borland CaliberRM 6.0 e Borland StarTeam 6.0.