{"id":737,"date":"2014-02-13T21:42:50","date_gmt":"2014-02-13T20:42:50","guid":{"rendered":"http:\/\/clemente.pamplona.name\/dba\/?p=737"},"modified":"2014-02-20T13:57:24","modified_gmt":"2014-02-20T12:57:24","slug":"cuando-se-usan-los-indices-en-una-consulta-con-like","status":"publish","type":"post","link":"http:\/\/clemente.pamplona.name\/dba\/cuando-se-usan-los-indices-en-una-consulta-con-like\/","title":{"rendered":"Cuando se usan los indices en una consulta con LIKE"},"content":{"rendered":"<p>Hoy vamos ha hacer una peque\u00f1a entrada de tunning.<\/p>\n<p>Muchas veces vemos a la hora de hacer ajustes de rendimiento como las consultas que se ejecutan la base de datos tienen la clausula LIKE, pero su comportamiento es distinto segun como se ejecuta.<br \/>\n\u00bfCuando se hace un INDEX RANGE y cuando un FULL SCAN? , esto es principalmente lo que veremos hoy <\/p>\n<p>Lo primero,\u00bf que es lo que hace la cla\u00fasula <b>LIKE<\/b> ?<br \/>\nLa clausula LIKE mira si una cadena determinada coincide con un determinado patr\u00f3n. Mediante el car\u00e1cter <b>%<\/b> podemos hacer b\u00fasquedas gen\u00e9ricas con esa cadena .<br \/>\nHemos de destacar que, LIKE contempla la b\u00fasqueda de longitud cero, es decir ,que la b\u00fasqueda de LIKE  &#8216;PEPE% &#8216; incluye tanto PEPESI como PEPE.<\/p>\n<p>Una vez tenemos claro que hace la clausula LIKE, veamos de que manera podemos utilizarlo:<\/p>\n<ul>\n<li> CADENA%\n<li> %CADENA\n<li> %CADENA%\n<li> CADENA1%CADENA2\n<\/ul>\n<p>Vamos a ver el comportamiento en cada una de las consultas. Tenemos una tabla llamada Imagen con un campo varchar <i>NOMBRE<\/i> <\/p>\n<pre>\r\nSQL> desc imagen\r\n Name                 Null?    Type\r\n ------------------ -------- ---------------\r\n ID                  NOT NULL NUMBER\r\n NOMBRE                       VARCHAR2(256)\r\n RUTA                         VARCHAR2(256)\r\n<\/pre>\n<p>Sobre este campo NOMBRE hemos creado un y un UNIQUE INDEX  llamado <b>IMAGEN_NOMBRE_UNI<\/b>, vamos ha hacer los 4 tipos de b\u00fasqueda y comparar los planes:<\/p>\n<h2>  CADENA%<\/h2>\n<p>Si ejecutamos una b\u00fasqueda en la que miramos el final de la cadena, la base de datos intentar\u00e1 utilizar primero el \u00edndice <\/p>\n<pre>\r\nset autotrace traceonly;\r\nSQL> select * from  imagen where nombre like 'D80%';\r\n|Id | Operation                  | Name           |Rows |Bytes| \r\n------------------------------------------------------------------\r\n| 0 | SELECT STATEMENT            |                  | 1 |143|3(0)|\r\n| 1 |  TABLE ACCESS BY INDEX ROWID| IMAGEN           | 1 |143|3(0)|\r\n|*2 |   INDEX RANGE SCAN          | IMAGEN_NOMBRE_UNI| 1 |   |2(0)|\r\n-------------------------------------------------------------------\r\n<\/pre>\n<p>El optimizador conoce como comienza la cadena, con lo que llevar\u00e1 a cabo un <b>INDEX RANGE SCAN<\/b> para llevar a cabo la consulta con el menor coste posible.<\/p>\n<h2>  %CADENA<\/h2>\n<p>EN este caso estamos buscando el final de la cadena entre el contenido de nuestra columna NOMBRE, si miramos el resultado del plan de ejecuci\u00f3n<\/p>\n<pre>\r\nset autotrace traceonly;\r\nSQL> select * from  imagen where nombre like '%009';\r\n----------------------------------------------------\r\n| Id  | Operation    | Name   | Rows  | Bytes |\r\n-------------------------------------------------\r\n| 0| SELECT STATEMENT  |       |778 |108K| 93 (2)\r\n|*1|  TABLE ACCESS FULL| IMAGEN|778 |108K| 93 (2)\r\n-------------------------------------------------\r\n\r\n<\/pre>\n<p>El optimizador desconoce como comienza la cadena, con lo que llevar\u00e1 a cabo un <b> TABLE ACCESS FULL<\/b> de toda la tabla.En este caso<b> no usa el \u00edndice<\/b> ya que no le sirve de nada el indice si debe de comparar la parte final de la cadena <\/p>\n<h2>  %CADENA%<\/h2>\n<p>Que ocurrir\u00e1 si buscamos la parte central de una cadena?<\/p>\n<pre>\r\nset autotrace traceonly;\r\nSQL> select * from  imagen where nombre like '%009%';\r\n----------------------------------------------------\r\n| Id  | Operation    | Name   | Rows  | Bytes |\r\n-------------------------------------------------\r\n| 0| SELECT STATEMENT  |       |778 |108K| 93 (2)\r\n|*1|  TABLE ACCESS FULL| IMAGEN|778 |108K| 93 (2)\r\n-------------------------------------------------\r\n<\/pre>\n<p>El optimizador desconoce como comienza la cadena, con lo que llevar\u00e1 a cabo un <b> TABLE ACCESS FULL<\/b> de toda la tabla.<br \/>\nEn este caso<b> no usa el \u00edndice<\/b> ya que no le sirve de nada el indice si debe de comparar la parte final de la cadena , es el mismo comportamiento que cuando lanzamos la consulta con %CADENA<\/p>\n<h2>  CADENA1%CADENA2<\/h2>\n<p>Que ocurrir\u00e1 si buscamos la parte central de una cadena?<\/p>\n<pre>\r\nset autotrace traceonly;\r\nSQL>  select * from imagen where nombre like 'D80_10%G';\r\n\r\n|Id | Operation                  | Name           |Rows |Bytes| \r\n------------------------------------------------------------------\r\n| 0 | SELECT STATEMENT            |                  | 1 |143|3(0)|\r\n| 1 |  TABLE ACCESS BY INDEX ROWID| IMAGEN           | 1 |143|3(0)|\r\n|*2 |   INDEX RANGE SCAN          | IMAGEN_NOMBRE_UNI| 1 |   |2(0)|\r\n-------------------------------------------------------------------\r\n<\/pre>\n<p>Este caso es muy similar al de CADENA%, el optimizador si que conoce el comienzo de la cadena, con lo que llevar\u00e1 a cabo un <b>INDEX RANGE SCAN<\/b> para llevar a cabo la consulta en el menor.<br \/>\nHay que tener en cuenta que, contra mas restrictiva sea la b\u00fasqueda mas r\u00e1pido ser\u00e1 y tendr\u00e1 menos coste para la base de datos. es decir que, aunque en los dos casos use el \u00edndice,   el coste de buscar CAD%CADENA2 ser\u00e1 mayor que el de buscar CADENA1%CADENA2 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hoy vamos ha hacer una peque\u00f1a entrada de tunning. Muchas veces vemos a la hora de hacer ajustes de rendimiento como las consultas que se ejecutan la base de datos tienen la clausula LIKE, pero su comportamiento es distinto segun &hellip; <a href=\"http:\/\/clemente.pamplona.name\/dba\/cuando-se-usan-los-indices-en-una-consulta-con-like\/\">Sigue leyendo <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[114,3],"tags":[145,256],"class_list":["post-737","post","type-post","status-publish","format-standard","hentry","category-plsql","category-tunning","tag-like","tag-plsql"],"_links":{"self":[{"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/posts\/737","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/comments?post=737"}],"version-history":[{"count":8,"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/posts\/737\/revisions"}],"predecessor-version":[{"id":897,"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/posts\/737\/revisions\/897"}],"wp:attachment":[{"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/media?parent=737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/categories?post=737"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/clemente.pamplona.name\/dba\/wp-json\/wp\/v2\/tags?post=737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}