<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Stiod Blog &#187; PostgreSQL</title>
	<atom:link href="http://blog.stiod.com/category/postgresql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.stiod.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Mon, 22 Feb 2010 14:20:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Indíces em PostgreSQL</title>
		<link>http://blog.stiod.com/2008/08/09/indices-em-postgresql/</link>
		<comments>http://blog.stiod.com/2008/08/09/indices-em-postgresql/#comments</comments>
		<pubDate>Sat, 09 Aug 2008 03:49:53 +0000</pubDate>
		<dc:creator>Rafael Sierra</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://blog.beta.stiod.com/?p=71</guid>
		<description><![CDATA[Um dos grandes problemas de performances em bancos de dados são os indíces, ou mais precisamente, a falta deles.
Antes de mais nada, o que raios é um índice?
Um índice nada mais é do que um conjunto de tuplas ordenadas, vamos pegar como exemplo a seguinte tabela:

CREATE TABLE usuarios (
id INTEGER,
login VARCHAR(20),
senha VARCHAR(40)
);

Nessa tabela, nenhum índice [...]]]></description>
			<content:encoded><![CDATA[<p>Um dos grandes problemas de performances em bancos de dados são os <a href="http://www.postgresql.org/docs/8.3/interactive/indexes-intro.html">indíces</a>, ou mais precisamente, a falta deles.</p>
<p>Antes de mais nada, <strong>o que raios é um índice?</strong></p>
<p>Um índice nada mais é do que um conjunto de tuplas ordenadas, vamos pegar como exemplo a seguinte tabela:<br />
<code><br />
CREATE TABLE usuarios (<br />
id INTEGER,<br />
login VARCHAR(20),<br />
senha VARCHAR(40)<br />
);<br />
</code></p>
<p>Nessa tabela, nenhum índice foi criado, então, vamos inserir alguns registros:<br />
<code><br />
INSERT INTO usuarios (id, login, senha) VALUES (1, 'usuario1', 'senha1');<br />
INSERT INTO usuarios (id, login, senha) VALUES (2, 'usuario2', 'senha2');<br />
INSERT INTO usuarios (id, login, senha) VALUES (3, 'usuario3', 'senha3');<br />
...<br />
INSERT INTO usuarios (id, login, senha) VALUES (300000, 'usuario300000', 'senha300000');<br />
</code></p>
<p>Agora temos 300,000 usuários no nosso banco de dados, uma quantidade pequena, mas já serve ao nosso proposito, vamos fazer um select que nos retorne um usuário qualquer:<br />
<code><br />
=# SELECT login FROM usuarios WHERE login='usuario2';<br />
login<br />
----------<br />
usuario2<br />
(1 row)</code></p>
<p>Time: 179.047 ms</p>
<p>Se saiu bem....179ms pra encontrar um resultado, agora vamos fazer outro:<br />
<code><br />
=# SELECT login FROM usuarios WHERE login='usuario223432';<br />
login<br />
---------------<br />
usuario223432<br />
(1 row)</code></p>
<p>Time: 191.386 ms</p>
<p>Hmmm....subiu pra 191, o que aconteceria se eu precisasse pegar o registro número mais alto, tipo 9999999? Teriamos um sério problema certo? Mas porque isso acontece?? Vamos entrar no cerne do PostgreSQL, vou mudar meu SQL:<br />
<code><br />
=# EXPLAIN SELECT login FROM usuarios WHERE login='usuario223432';<br />
QUERY PLAN<br />
------------------------------------------------------------<br />
Seq Scan on usuarios  (cost=0.00..5910.00 rows=1 width=13)<br />
Filter: ((login)::text = 'usuario223432'::text)<br />
(2 rows)</code></p>
<p>Time: 0.792 ms</p>
<p>Repare na primeira linha do resultado, ele está fazendo uma <a href="http://pt.wikipedia.org/wiki/Busca_linear">busca sequencial</a> até encontrar o resultado desejado. De forma resumida, isso significa que ele vai comparar cada linha que tiver na tabela até encontrar o que você, desde o primeiro até o último (ou até encontrar), se o seu resultado estiver nos primeiros registros legal, mas se for um dos ultimos bilhões....</p>
<p>Pra resolver esse problema, basta criar um índice na tabela:<br />
<code><br />
=# CREATE INDEX idx_usuarios_login ON usuarios(login);<br />
CREATE INDEX<br />
Time: 4020.891 ms<br />
</code></p>
<p>Agora vamos repetir o mesmo SQL:<br />
<code><br />
=# SELECT login FROM usuarios WHERE login='usuario223432';<br />
login<br />
---------------<br />
usuario223432<br />
(1 row)</code></p>
<p>Time: 1.528 ms</p>
<p>OMFG!!!! Caiu de 190 pra 1!!!! UM!!!! Preciso falar mais alguma coisa?</p>
<p><strong>"Puxa vida Rafael, você resolveu todos os problemas da minha vida, vou criar indíces em todas os campos de todas as minhas tabelas e em todas as combinações possiveis!!"</strong><br />
Você ta loco??? Se você fizer isso sua performance em modificações (INSERT, UPDATE, DELETE) vai sofrer <strong>muito</strong>. Isso porque se sempre que você modificar os valores, o PostgreSQL vai precisar reorganizar os indíces pra garantir que a performance no SELECT seja alta.</p>
<p><strong>"Carai, como infernos eu vou saber em que campos criar um índice então?"</strong><br />
Fácil, crie apenas em campos que você use WHERE e ORDER BY, dessa forma você vai manter o equilibrio na performance.</p>
<p><strong>"Pow cara, mas e as chaves primárias e estrangeiras?"</strong><br />
Bom, uma chave primaria naturalmente já é um indíce, porém, uma chave estrangeira não, então, se você tiver um campo que seja uma chave estrangeira para um campo em outra tabela, crie um índice nele também.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stiod.com/2008/08/09/indices-em-postgresql/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
