{"id":85,"date":"2010-11-17T10:24:00","date_gmt":"2010-11-17T12:24:00","guid":{"rendered":"http:\/\/www.soudba.com.br\/?p=85"},"modified":"2010-11-17T10:24:00","modified_gmt":"2010-11-17T12:24:00","slug":"como-uma-consulta-pode-influenciar-em-performance","status":"publish","type":"post","link":"https:\/\/www.soudba.com.br\/?p=85","title":{"rendered":"Como uma consulta pode influenciar em performance"},"content":{"rendered":"<div style=\"text-align:center;\"><b><span style=\"font-size:large;\">Performance de Consultas<\/span><br \/><\/b><\/div>\n<p><b>Otimizador<\/b> &#8211; \u00c9 o programa que est\u00e1 preparado internamentamente pelo oracle para diagnosticar qual ser\u00e1 a melhor proposta para se recuperar a informa\u00e7\u00e3o. Seria ele o respons\u00e1vel por gerar o plano (caminho) para se buscar os dados das tabelas e indices. O Oracle nas vers\u00f5es mais recentes ( a partir 9iR2 se n\u00e3o me engano) se utiliza-se de custo como padr\u00e3o e n\u00e3o recomenda usar regra em suas consultas.<\/p>\n<p><b>Custo<\/b> &#8211; \u00c9 a melhor estimativa do numero de I\/Os que devem ser feitos para a execu\u00e7\u00e3o de uma consulta.<\/p>\n<p><b>Estimativas<\/b> &#8211; S\u00e3o empregadas t\u00e9cnicas para se gerar o melhor plano e s\u00e3o usadas como base as estimativas. Os tipos s\u00e3o: seletividade, cardinalidade e custo;<br \/>A cardinalidade \u00e9 derivada da seletividade e o custo depende da cardinalidade.<br \/>Se as estatisticas est\u00e3o atualizadas, ser\u00e3o empregadas na gera\u00e7\u00e3o dos planos, se caso n\u00e3o estejam ser\u00e3o usadas valores padr\u00e3o de estatisticas usando se o parametro para isso: OPTIMIZER_DYNAMIC_SAMPLING.<\/p>\n<p><b>Seletividade<\/b> &#8211; \u00c9 uma propor\u00e7\u00e3o estimada de um conjunto de linhas retorndas a partir de um predicado (filtro) ou uma combina\u00e7\u00e3o de predicados.<br \/>F\u00f3rmula: (numero de linhas que satisfazem o filtro\/total de numero de linhas &#8211; baseado em histogramas)<\/p>\n<p>Ex:<br \/>select last_name from employees where last_name =&#8217;JOHN&#8217;;<\/p>\n<p>A f\u00f3rmula pode ser melhor entendida assim:<br \/>a) O n\u00famero de linhas que satisfazem o filtro para o predicado \u00e9 2.<br \/>b) O n\u00famero de linhas que precisam ser lidas para satisfazer o retorno \u00e9 200 baseando se em nomes distintos que existem na coluna last_name.<br \/>A seletividade ser\u00e1: 2\/200&nbsp; = 0,01 &#8211; alta seletividade &#8211; utilizar\u00e1 indices.<\/p>\n<p>Os valores sao entre 0.0 e 1.0, se diz uma alta seletividade: baixo numero de linhas, baixa seletividade: numero alto de linhas.<\/p>\n<p>&#8211; Um indice n\u00e3o ser\u00e1 usado porque temos uma baixa seletividade. \u00c9 melhor percorrer a tabela ao inves de percorrer varias linhas no indice.<\/p>\n<p>&#8211; Um indice pode ser usado porque temos uma alta seletividade. O numero de linhas pequeno a ser retornado \u00e9 mais provavel se usar o indice para localizar rapidamente estas linhas na tabela quando esta quantidade de linhas nao exceder 3% a 4% do total de linhas da tabela.<\/p>\n<p>O c\u00e1lculo da seletividade se base em duas fontes: <br \/>a) Estat\u00edsticas &#8211; se caso nao exista usuar\u00e1 exemplos dinamicos.<br \/>b) Histogramas &#8211; Analisa a distribui\u00e7\u00e3o das linhas, como a quantidade de informa\u00e7\u00f5es distintas em uma coluna (ideal para indices BTREE e quando varios valores distintos melhor para BITMAP).<\/p>\n<p><b>Cardinalidade<\/b> &#8211; Expectativa do n\u00famero de linhas a serem retornadas de uma tabela para uma opera\u00e7\u00e3o em particular. Analisa o n\u00famero de linhas distinas, o n\u00famero total de linhas da tabela e a seletividade. \u00c9 usado para determinar jun\u00e7\u00f5es, filtros, agrupamentos e custo de ordena\u00e7\u00e3o.<br \/>F\u00f3rmula &#8211; seletividade\/n\u00famero total de linhas baseadas no histograma<\/p>\n<p>F\u00f3rmula: (numero de linhas que satisfazem o filtro\/n\u00famero total de linhas baseadas no histograma)\/n\u00famero total de linhas da tabela<br \/><b><br \/><\/b><br \/><b>Custo &#8211; <\/b>\u00c9 o melhor estimativa que existe para saber qual seria o n\u00famero de I\/Os que se devem ser feitos para satisfazer o retorno de uma consulta. Uma unidade de custo equivale a leitura de uma&nbsp; leitura para um bloco em forma rand\u00f4mica.<br \/>S\u00e3o feitos os seguintes calculos para se conseguir a estimativa correta:<br \/>a) Estimativa de Tempo de leitura de blocos de forma rand\u00f4mica.<\/p>\n<p>b) Estimativa de Tempo de leitura de blocos em leitura em lote.<br \/>c) Estimativa de Tempo de uso de CPU pelo processo para leitura de uma unidade de custo.<\/p>\n<p>Gera\u00e7\u00e3o de planos<\/p>\n<p>Para se gerar planos, o melhor \u00e9 utilizar da seguinte forma:<br \/>a) Sqldeveloper &#8211; da pr\u00f3pria oracle &#8211; gratuito.<br \/>b) Linha de comandos no sqlplus.<\/p>\n<p>C:UsersAndre&gt;sqlplus \/ as sysdba<\/p>\n<p>SQL*Plus: Release 10.2.0.3.0 &#8211; Production on Qua Nov 17 09:41:49 2010<\/p>\n<p>Copyright (c) 1982, 2006, Oracle.&nbsp; All Rights Reserved.<\/p>\n<p>Conectado a:<br \/>Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 &#8211; Production<br \/>With the Partitioning, OLAP and Data Mining options<\/p>\n<p>SQL&gt; alter user scott identified by tiger account unlock;<\/p>\n<p>Usu\u00e1rio alterado.<br \/>SQL&gt; EXPLAIN PLAN<br \/>&nbsp; 2&nbsp; SET STATEMENT_ID = &#8216;badsql1&#8217;<br \/>&nbsp; 3&nbsp; FOR<br \/>&nbsp; 4&nbsp; SELECT ename FROM emp;<\/p>\n<p>Explicado.<\/p>\n<p>SQL&gt; SELECT cardinality &#8220;Rows&#8221;,<br \/>&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpad(&#8216; &#8216;,level-1)||operation||&#8217; &#8216;||<br \/>&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; options||&#8217; &#8216;||object_name &#8220;Plan&#8221;<br \/>&nbsp; 4&nbsp;&nbsp;&nbsp; FROM PLAN_TABLE<br \/>&nbsp; 5&nbsp; CONNECT BY prior id = parent_id<br \/>&nbsp; 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND prior statement_id = statement_id<br \/>&nbsp; 7&nbsp;&nbsp;&nbsp; START WITH id = 0<br \/>&nbsp; 8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND statement_id = &#8216;badsql1&#8217;<br \/>&nbsp; 9&nbsp;&nbsp;&nbsp; ORDER BY id;<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rows<br \/>&#8212;&#8212;&#8212;-<br \/>Plan<br \/>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14<br \/>SELECT STATEMENT<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 14<br \/>&nbsp;TABLE ACCESS FULL EMP<\/p>\n<p>http:\/\/download.oracle.com\/docs\/cd\/B10500_01\/server.920\/a96533\/ex_plan.htm<\/p>\n<div style=\"text-align:center;\"><b>Uma consulta eficiente<\/b><\/div>\n<p><b>Alta seletividade<\/b> &#8211; Index scan &#8211; N\u00famero de retorno de linhas pequeno. Uso aconselhado de \u00edndices na pesquisa onde as tabelas s\u00e3o maiores que 4% do valor do total de numero de linhas retornadas. Aconselhado em sistemas comerciais ou OLTP.<\/p>\n<p><b>Baixa seletividade<\/b> &#8211; Full table scan &#8211; N\u00famero de retorno de linhas alto. Aconselhado a busca direta dos dados sem a utiliza\u00e7\u00e3o de indices. \u00c9 melhor percorrer toda a tabela ao inv\u00e9s de usar o \u00edndice para buscar muitas linhas. Baseado em sistemas de Data Warehouse ou Bussiness Inteligence. Pode se melhorar a leitura sequencial dos registros na tabela atrav\u00e9s do aumento no valor do param\u00eatro: DB_FILE_MULTIBLOCK_READ_COUNT e se aplica tamb\u00e9m:<\/p>\n<ul>\n<li>Tabelas pequenas<\/li>\n<li>Alto grau de paralelismo<\/li>\n<li>Nenhum indice atende ao filtro<\/li>\n<li>Nenhum filtro na consulta ou baixa seletividade<\/li>\n<li>Uso de hint &#8211; FULL (NOMETABELA)<\/li>\n<\/ul>\n<p>Custo menor &#8211; Sempre que possivel analise o custo e veja as referencias para que se construa bases eficazes para a analise do otimizador.<\/p>\n<p><\/p>\n<div style=\"text-align:center;\"><span style=\"font-size:large;\"><b>\u00cdndices<\/b><\/span><\/div>\n<p>Quando fazemos a consulta geralmente no plano, temos retornos do uso do \u00edndice e para interpreta-los:<br \/>Lembre-se INDICE BTREE significa indice balanceado.<\/p>\n<p><b>INDEX UNIQUE SCAN<\/b> &#8211; Os predicados s\u00e3o baseados em filtros onde existem indices de chaves unicas. \u00c9 retornado um unico ROWID.<\/p>\n<div style=\"clear:both;text-align:center;\"><a href=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/9a2c1-indexscanunique.jpg\" style=\"margin-left:1em;margin-right:1em;\"><img fetchpriority=\"high\" decoding=\"async\" border=\"0\" height=\"193\" src=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/9a2c1-indexscanunique.jpg?w=300\" width=\"320\" \/><\/a><\/div>\n<p><b>INDEX RANGE SCAN<\/b> &#8211; S\u00e3o baseadas em consultas que necessitam varrer o \u00edndice para buscar os valores, geralmente s\u00e3o utilizadas quando combinamos predicados um filtro utilizando se do \u00edndice e outro em uma coluna que n\u00e3o est\u00e1 presente no \u00edndice.<\/p>\n<div style=\"clear:both;text-align:center;\"><a href=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/2fba2-indexrangescan.jpg\" style=\"margin-left:1em;margin-right:1em;\"><img decoding=\"async\" border=\"0\" height=\"21\n5\" src=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/2fba2-indexrangescan.jpg?w=300\" width=\"320\" \/><\/a><\/div>\n<p>INDEX FULL SCAN &#8211; Usado quando usamos no predicado o IS NOT NULL para filtrar a coluna indexada. Geralmente a consulta cont\u00e9m mais de dois predicados, sendo um baseado na coluna com o \u00edndice e outra n\u00e3o.<\/p>\n<div style=\"clear:both;text-align:center;\"><a href=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/a753e-indexfullscan.jpg\" style=\"margin-left:1em;margin-right:1em;\"><img decoding=\"async\" border=\"0\" height=\"204\" src=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/a753e-indexfullscan.jpg?w=300\" width=\"320\" \/><\/a><\/div>\n<p>INDEX FAST FULL SCAN &#8211; Usado quando o otimizador ir\u00e1 buscar todos os dados da tabela, fazendo um full table scan isso desde que o predicado fa\u00e7a um filtro usando se a clausula IS NOT NULL em uma das colunas indexadas. \u00c9 uma alternativa ao full table scan visto que for\u00e7amos a busca dos valores no \u00edndice na tentativa de fazer o retorno mais rapido das linhas. Para &#8220;for\u00e7ar&#8221; o uso dessa t\u00e9cnica pode ser necess\u00e1rio adicionar o hint na consulta &#8211; <span style=\"color:black;font-family:&quot;font-size:12pt;font-weight:bold;\">INDEX_FFS<\/span><span style=\"color:black;font-family:Arial;font-size:12pt;font-weight:bold;\">. <\/span><\/p>\n<p>INDEX SKIP SCAN &#8211; \u00c9 a forma que o otimizador na leitura do indice, descarta aquele galho quando as informa\u00e7\u00f5es do galho n\u00e3o satisfazem o filtro do predicado da consulta. Geralmente presente em consultas do tipo BETWEEN ou onde se encontram predicados usando colunas indexadas com os simbolos &lt;, &gt;, &lt;=, &gt;=.<\/p>\n<p><\/p>\n<div style=\"clear:both;text-align:center;\"><a href=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/ebe5f-indexskipscan.jpg\" style=\"margin-left:1em;margin-right:1em;\"><img decoding=\"async\" border=\"0\" height=\"209\" src=\"http:\/\/168.138.141.47\/wp-content\/uploads\/2019\/02\/ebe5f-indexskipscan.jpg?w=300\" width=\"320\" \/><\/a><\/div>\n<p>INDEX JOIN SCAN &#8211; Faz um HASH JOIN, une v\u00e1rios indices (partes) para conseguir resolver a consulta, desde que estes indices apare\u00e7am nos predicados.<\/p>\n<p>AND-EQUAL &#8211; Ess\u00e1 opera\u00e7\u00e3o permite ao sistema fazer um merge entre indices combinando os diversos predicados que s\u00e3o usados. Em teoria poderia atingir at\u00e9 a cinco indices baseados em uma unica coluna e usar estes indices para fazer as buscas para os resultados. A ideia \u00e9 encontrar os ROWIDs. Para for\u00e7ar o uso dos v\u00e1rios indices, utilize o hint &#8211; AND_EQUAL.<\/p>\n<div style=\"text-align:center;\"><span style=\"font-size:large;\"><b>Outras considera\u00e7\u00f5es<\/b><\/span><\/div>\n<p><\/p>\n<ul>\n<li>O retorno de n\u00famero de registros \u00e9 facilitado quando a coluna a ser contabilizada \u00e9 NOT NULL.<\/li>\n<li>Indice IOT \u00e9 ideal quando em sistemas que necessitam buscar os valores do registro e fazem a busca pela chave prim\u00e1ria geralmente. A IOT armazena no indice as informacoes das colunas restantes. A diferen\u00e7a \u00e9 que em tabelas do tipo head as buscas precisam ir ao indices e depois no segmento da tabela. Na IOT isso \u00e9 feito diretamente no segmento do indice.<\/li>\n<li>Indices do tipo BITMAP s\u00e3o adequados para acelerar o retorno das fun\u00e7\u00f5es de agrega\u00e7\u00e3o. como soma, contar, max etc. O predicado IS NOT NULL pode ser beneficiado pelo indice bitmap, ja que este indice, diferente dos demais armazena valores nulos. Tamb\u00e9m indicados para colunas com grande n\u00famero de valores distintos: Cores, Sexo, Cidades, Estados, Pa\u00edses etc.<\/li>\n<li>Indices compostos &#8211; podem ter suas seletividades baixas quando sozinhos, mas combinados a seletividade aumenta, reduzindo o numero de registros lidos<\/li>\n<\/ul>\n<p><\/p>\n<div style=\"text-align:center;\"><span style=\"font-size:large;\"><b>Considera\u00e7\u00f5es ao analisar o plano de execu\u00e7\u00e3o &#8211; BITMAP operations<\/b><\/span><\/div>\n<p>As opera\u00e7\u00f5es que no plano retornam a resposta como BITMAP nao diz, necessariamente que o indice percorrido \u00e9 bitmap. O otimizador pode transformar em alguns casos o indice Btree em Bitmap.<\/p>\n<p><\/p>\n<div style=\"direction:ltr;margin-bottom:0;margin-left:.44in;margin-top:0;text-align:left;text-indent:-.19in;unicode-bidi:embed;vertical-align:baseline;\"><span style=\"font-size:12pt;\"><span style=\"font-family:&quot;font-size:70%;\">\u2022<\/span><\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">BITMAP CONVERSION FROM ROWID<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">:&nbsp; Indice B-tree convertido em Bitmap e depois convertido de novo em rowid ap\u00f3s o final da compara\u00e7\u00e3o.<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\"><\/span><\/div>\n<div style=\"direction:ltr;margin-bottom:0;margin-left:.44in;margin-top:0;text-align:left;text-indent:-.19in;unicode-bidi:embed;vertical-align:baseline;\"><span style=\"font-size:12pt;\"><span style=\"font-family:&quot;font-size:70%;\">\u2022<\/span><\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">BITMAP MERGE<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">: Pode ser feito o merge entre varios indices bitmaps para se fazer buscas em atributos de indices diferentes. <\/span><\/div>\n<div style=\"direction:ltr;margin-bottom:0;margin-left:.44in;margin-top:0;text-align:left;text-indent:-.19in;unicode-bidi:embed;vertical-align:baseline;\"><span style=\"font-size:12pt;\"><span style=\"font-family:&quot;font-size:70%;\">\u2022<\/span><\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">BITMAP MINUS<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">: \u00e8 uma opera\u00e7\u00e3o onde, se inverter as posi\u00e7\u00f5es em outro mapa de bits pode se beneficiar a busca. Geralemente esta presentes em opera\u00e7\u00f5es como <\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">: LAST_NAME<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">=&#8217;Andre&#8217; and LAST_NAME&lt;&gt;&#8217;LUIZ&#8217;<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">.<\/span><\/div>\n<div style=\"direction:ltr;margin-bottom:0;margin-left:.44in;margin-top:0;text-align:left;text-indent:-.19in;unicode-bidi:embed;vertical-align:baseline;\"><span style=\"font-size:12pt;\"><span style=\"font-family:&quot;font-size:70%;\">\u2022<\/span><\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">BITMAP KEY ITERATION<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">: Percorre a tabela encontrando as linhas e encontrando a correspondencia no bitmap a partir de um indice bitmap.Essa opera\u00e7\u00e3o \u00e9 feita para criar a opera\u00e7\u00e3o: <\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">BITMAP MERGE<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">.&nbsp;<\/span><\/div>\n<div style=\"direction:ltr;margin-bottom:0;margin-left:.44in;margin-top:0;text-align:left;text-indent:-.19in;unicode-bidi:embed;vertical-align:baseline;\"><span style=\"color:black;font-family:&quot;font-size:12pt;\">&nbsp;<\/span><span style=\"font-size:12pt;\"><span style=\"font-family:&quot;font-size:70%;\">\u2022<\/span><\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">BITMAP JOIN INDEX<\/span><span style=\"color:black;font-family:&quot;font-size:12pt;\">: Eficiente quando usado para facilitar as opera\u00e7\u00f5es de JOIN entre os predicados.Faz com que a quantidade de dados retornados seja menor. Monta o mapa de bits com a chave primaria e no mesmo bloco todas as FKs facilitando o retorno das opera\u00e7\u00f5es de JOIN.<\/span><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Performance de Consultas Otimizador &#8211; \u00c9 o programa que est\u00e1 preparado internamentamente pelo oracle para diagnosticar qual ser\u00e1 a melhor proposta para se recuperar a informa\u00e7\u00e3o. Seria ele o respons\u00e1vel por gerar o plano (caminho) para se buscar os dados &hellip; <a href=\"https:\/\/www.soudba.com.br\/?p=85\">Continue lendo <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40,53,120,194],"tags":[],"class_list":["post-85","post","type-post","status-publish","format-standard","hentry","category-bitmap-index","category-consulta-lenta","category-indices-eficientes","category-oracle-index"],"_links":{"self":[{"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=\/wp\/v2\/posts\/85","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=85"}],"version-history":[{"count":0,"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=\/wp\/v2\/posts\/85\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=85"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=85"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.soudba.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=85"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}