Re: Tratando de entender un plan de consulta con un INNER JOIN.

From: Igor <igor(at)negora(dot)com>
To: Jaime Casanova <jaime(at)2ndquadrant(dot)com>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Tratando de entender un plan de consulta con un INNER JOIN.
Date: 2012-08-09 10:46:09
Message-ID: 502394F1.60305@negora.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
On 08/08/12 18:47, Jaime Casanova wrote:<br>
<blockquote
cite="mid:CAJKUy5hnAjZCL2vTFUfHjgDrs9HRJgMKf30N_HTr_7e2y4qtgA(at)mail(dot)gmail(dot)com"
type="cite">
<pre wrap="">2012/8/8 Igor <a class="moz-txt-link-rfc2396E" href="mailto:igor(at)negora(dot)com">&lt;igor(at)negora(dot)com&gt;</a>:
</pre>
<blockquote type="cite">
<pre wrap="">
Analizando el plan de la consulta (anteponiendo "analyze" a &eacute;sta) aparece
esto:

Hash Join (cost=15.34..31.26 rows=166 width=8)
Hash Cond: (s.father_id = f.father_id)
-&gt; Seq Scan on sons s (cost=0.00..13.10 rows=310 width=8)
-&gt; Hash (cost=14.00..14.00 rows=107 width=4)
-&gt; Seq Scan on fathers f (cost=0.00..14.00 rows=107 width=4)
Filter: (father_id &lt; 10)

Supongo que se me est&aacute; escapando algo importante pero, &iquest;Por que en esa l&iacute;nea
marcada en negrita (la b&uacute;squeda secuencial en "sons") el planificador no
restringe la b&uacute;squeda tambi&eacute;n a aquellos hijos con c&oacute;digo de padre menor a
10, como hace al buscar los padres? &iquest;Significa este plan que pese a obtener
10 padres, luego recorre absolutamente todos los hijos y no s&oacute;lo los que
tienen c&oacute;digo de padre menor que 10 (pese a que hay un &iacute;ndice "btree" creado
en la columna "father_id" de la tabla "sons")?

He probado a llenar las tablas con 10 millones de registros y, tras ejecutar
"analyze", el resultado es el mismo.

</pre>
</blockquote>
<pre wrap="">
Que version de postgres esta? con solo 310 registros creo que es
normal que haga un seq scan pero con 10 millones deberia usar un
indice.

a mi me funciona asi (de hecho solo inserte 10000 en fathers y 30000
en sons) aun asi usa indices en ambas tablas (no necesita el filtro en
sons porque al usar el indice y chequear solo los resultados que
obtuvo de fathers el filtro esta implicito)

pero si, cuando hace un seq scan no hereda filtros aun cuando haya un
FK que relacione los dos campos.
ai quieres ver el filtro agregua una condicion "s.fathers_id &lt; 10"
adicional si quieres que use ese filtro

pero, un seq scan igual leera toda la tabla (filtro o no filtro)

</pre>
</blockquote>
<br>
Hola Jaime:<br>
<br>
Ante todo, gracias por tu respuesta. La versi&oacute;n que uso de
PostgreSQL es la 9.0.1, en un Linux de 64-bit (Kubuntu).<br>
<br>
Hoy he vuelto a probar a&ntilde;adiendo 10.000 y 30.000 registros, como en
tu caso, y el resultado es el que sigue:<br>
<ul>
<li><tt>WHERE f.id_father &lt;= 10:</tt> usa los &iacute;ndices de ambas
tablas, aplicando un "nested loop".<br>
</li>
<li><tt>WHERE f.id_father &lt;= 100:</tt> usa el &iacute;ndice de
"fathers" y una secuencia en "sons", aplicando un "hash join".<br>
</li>
<li><tt>WHERE f.id_father &lt;= 6000:</tt> usa secuencias en ambas
tablas, aplicando un "hash join".<br>
</li>
</ul>
<br>
As&iacute; que supongo que ayer, por trastear demasiado, los &iacute;ndices
pudieron haberse corrompido y por eso jam&aacute;s eran usados. En un
momento me qued&eacute; incluso sin espacio en disco, as&iacute; que es altamente
probable que esto tuviera que ver. Los 20.000.000 de registros que
introduje tienen la culpa muy probablemente, je je je.<br>
<br>
Volviendo a la pregunta original, y pensando en esos 3 casos que he
testado, veo muy l&oacute;gicos el primero (10) y el tercero (6000). El
primero, porque son poqu&iacute;simos registros. Y el tercero, porque al
devolver tantos, es m&aacute;s r&aacute;pido recorrer ambas tablas que usar
&iacute;ndices.<br>
<br>
El que me costaba entender es el segundo (100). Y creo que se debe a
que el resultado de "explain" es un poco ambiguo. Da a entender (al
menos a m&iacute;) que en el "hash join" por un lado se obtiene el "hash"
de 100 filas de "fathers", por otro se obtienen las 30.000 filas de
"sons" al completo (el planificador no aplica &iacute;ndice ni filtro en
este caso) y que luego se hace el producto cartesiano de eso.
Entiendo que la manera correcta de interpretarlo es que el producto
se hace <b>mientras</b> se recorren las 30.000 y <b>no despu&eacute;s</b>
de ello, como es l&oacute;gico. &iquest;Es as&iacute;, verdad?<b><br>
</b><br>
Aparte de eso, tambi&eacute;n me costaba entender como para 300 registros
(100 * 3; muy pocos) esa t&eacute;cnica era m&aacute;s r&aacute;pida que usar un "nested
loop". Pero pensando en c&oacute;mo funciona un &iacute;ndice de tipo "btree" y la
cantidad de b&uacute;squedas a realizar, la verdad es que me he dado cuenta
de que s&iacute;, que un barrido en secuencia puede ser mucho m&aacute;s r&aacute;pido en
ese caso. Es m&aacute;s, yo mismo uso esa misma t&eacute;cnica cuando programo en
Java productos cartesianos y ni siquiera me hab&iacute;a dado cuenta de que
es un caso semejante.<br>
<br>
Un saludo y gracias.<br>
</body>
</html>

Attachment Content-Type Size
unknown_filename text/html 5.1 KB

In response to

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Mariano Reingart 2012-08-10 18:18:19 [OT][Anuncio]: Jornada PostgreSQL Argentina 2012: Inscripción temprana y Llamado a propuestas extendido al 31-08-2012
Previous Message Edwin Quijada 2012-08-09 02:40:42 RE: Auto incrementar con Serial