<?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>TecnoRetales &#187; SQL</title>
	<atom:link href="http://www.tecnoretales.com/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tecnoretales.com</link>
	<description>La experiencia no se olvida</description>
	<lastBuildDate>Wed, 07 Jul 2010 21:23:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<!-- google ad injected by adsense-optimizer http://www.adsenseoptimizer.de -->
			<div  style="padding:7px; float: right; padding-right: 0; margin: 3px;"><!-- Ad number: 1 --><script type="text/javascript"><!--
    	 
    	google_ad_client = "pub-7180773421652966"; google_alternate_color = "FFFFFF";
		google_ad_width = 468; google_ad_height = 60;
		google_ad_format = "468x60_as"; google_ad_type = "text";
		google_ad_channel =""; google_color_border = "FE8B00";
		google_color_link = "FE8B00"; google_color_bg = "FFFFFF";
		google_color_text = "000000"; google_color_url = "D9D9D9";
		google_ui_features = "rc:6"; //--></script>
		<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></div>	<item>
		<title>Consideraciones de velocidad con LIMIT</title>
		<link>http://www.tecnoretales.com/bases-de-datos/consideraciones-de-velocidad-con-limit/</link>
		<comments>http://www.tecnoretales.com/bases-de-datos/consideraciones-de-velocidad-con-limit/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 06:11:36 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Bases de datos]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=631</guid>
		<description><![CDATA[Un compañero de trabajo que es un crack en temas de optimización de bases de datos me ha pasado la siguiente información. Cuando hacemos una consulta con un LIMIT x, y sobre una tabla con millones de registros, a medida que x aumenta, la consulta se va haciendo cada vez más lenta. Veamos un ejemplo:
SELECT [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>Un compañero de trabajo que es un crack en temas de optimización de bases de datos me ha pasado la siguiente información. Cuando hacemos una consulta con un <em>LIMIT x, y</em> sobre una tabla con millones de registros, a medida que <em>x</em> aumenta, la consulta se va haciendo cada vez más lenta. Veamos un ejemplo:</p>
<p>SELECT version FROM car LIMIT 300,100; (100 results, <strong>0.01 sec</strong>)</p>
<p>SELECT version FROM car LIMIT 3000000,100; (100 results, <strong>2.5 sec</strong>)</p>
<p>Si además agregamos un par de JOINS a esta consulta, la complicamos un poco y le añadimos un ORDER BY, los problemas de rendimiento pueden llegar a causar un colapso en la base de datos.<span id="more-631"></span></p>
<p><strong>¿Por qué pasa esto?</strong></p>
<p>Para determinar el primer valor que tiene que seleccionar, MySQL debe recorrer desde el primer registro e ir contando hasta llegar al 300, a partir de ahí, cogerá 100. Obviamente, a medida que el valor de X va aumentando, la búsqueda del primer elemento es más lenta y como podemos ver en el ejemplo de arriba, llega a tardar 2,5 segundos en recorrer 3.000.000 de registros.</p>
<p><strong>¿Cómo lo podemos solucionar?</strong></p>
<p>Mi compañero propone hacer la búsqueda acotando a partir de primary key de la tabla, de este modo, al ser un campo indexado la búsqueda es realmente eficiente y nos evitamos cargar la máquina:</p>
<p><span style="font-family: Arial; font-size: x-small;"><span style="font-size: 10pt; font-family: Arial;" lang="EN-GB">SELECT version FROM car WHERE id_car BETWEEN 3000000 AND 3000100; (~100 results, <strong>0.01 sec</strong>)</span></span></p>
<p><span style="font-family: Arial; font-size: x-small;"><span style="font-size: 10pt; font-family: Arial;" lang="EN-GB">Esta solución no nos sería válida a la hora de construir un paginador, porque en el caso de tener vehículos desactivados u eliminados, unas páginas contendrían 100 vehículos, otras quizá 74&#8230; sin embargo, si por ejemplo construimos un script que se recorra toda la tabla <em>car</em> esta es una buena manera de realizar la búsqueda.</span></span></p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/bases-de-datos/consideraciones-de-velocidad-con-limit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Explain MySQL para optimizar tus consultas</title>
		<link>http://www.tecnoretales.com/bases-de-datos/explain-mysql-para-optimizar-tus-consultas/</link>
		<comments>http://www.tecnoretales.com/bases-de-datos/explain-mysql-para-optimizar-tus-consultas/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 17:25:01 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Bases de datos]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=563</guid>
		<description><![CDATA[Explain es una potente herramienta que MySQL pone a nuestra disposición para orientarnos sobre como está ejecutando una consulta el motor de la base de datos.
Esto nos es de mucha utilidad cuando creamos una consulta nueva, pues nos indica que índices va a utilizar, de que tipo son, como de efectiva será la respuesta al [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><strong><img class="alignleft size-full wp-image-565" src="http://www.tecnoretales.com/wp-content/uploads/2009/07/mysql_5_4_300x290.png" alt="MySQL Dolphin" width="150" height="145" />Explain</strong> es una potente herramienta que MySQL pone a nuestra disposición para orientarnos sobre como está ejecutando una consulta el motor de la base de datos.</p>
<p>Esto nos es de mucha utilidad cuando creamos una consulta nueva, pues nos indica que índices va a utilizar, de que tipo son, como de efectiva será la respuesta al usar esos índices&#8230; por lo tanto, podemos detectar rápidamente, por ejemplo, de que nuestra consulta no está bien formada o que nos falta un índice en algún campo concreto.</p>
<p>Si ejecutamos la siguiente consulta:</p>
<p><code>EXPLAIN SELECT *<br />
FROM user u<br />
INNER JOIN user_profile up ON u.id = up.user_id</code></p>
<p>Obtendremos una respuesta como esta:</p>
<table id="table_results" border="1">
<thead>
<tr>
<th>id</th>
<th>select_type</th>
<th>table</th>
<th>type</th>
<th>possible_keys</th>
<th>key</th>
<th>key_len</th>
<th>ref</th>
<th>rows</th>
<th>Extra</th>
</tr>
</thead>
<tbody>
<tr>
<td align="right">1</td>
<td>SIMPLE</td>
<td>up</td>
<td>ALL</td>
<td>user_id_idx</td>
<td><em>NULL</em></td>
<td><em>NULL</em></td>
<td><em>NULL</em></td>
<td align="right">13</td>
<td></td>
</tr>
<tr>
<td align="right">1</td>
<td>SIMPLE</td>
<td>u</td>
<td>eq_ref</td>
<td>PRIMARY</td>
<td>PRIMARY</td>
<td>4</td>
<td>futbol.up.user_id</td>
<td align="right">1</td>
<td></td>
</tr>
</tbody>
</table>
<p>Pero, ¿qué quieren decir estas columnas? ¿qué información nos dan?<span id="more-563"></span></p>
<ol>
<li><strong>Table: </strong>Nos informa de la tabla a la que nos estamos refiriendo.</li>
<li><strong>Type:</strong> El tipo de unión que se está usando. Desde la mejor hasta la peor, los tipos de uniones son system, const, eq_ref, ref, range, index, y ALL.
<ul>
<li><strong>System:</strong> Tabla con una única fila, por tanto, la respuesta es inmediata.</li>
<li><strong>Const:</strong> En la tabla coincide una única fila con los criterios indicados. Al sólo haber una fila, el optimizador toma este valor como constante, por este motivo este tipo de tablas son muy rápidas.</li>
<li><strong>Eq_ref:</strong> Una fila de la tabla 1 será leída por cada combinación de filas de la tabla 2. Este tipo es usado cuando todas las partes de un índice se usan en la consulta y el índice es UNIQUE o PRIMARY KEY.</li>
<li><strong>Ref:</strong> Todas las filas con valores en el índice que coincidan serán leídos desde esta tabla por cada combinación de filas de las tablas previas. Similar a <strong>eq_ref</strong>, pero usado cuando usa sólo un prefijo más a la izquierda de la clave o si la clave no es UNIQUE o PRIMARY KEY. Si la clave que es usada coincide sólo con pocas filas, esta union es buena.</li>
<li><strong>Range:</strong> Sólo serán recuperadas las filas que estén en un rango dado, usando un índice para seleccionar las filas. La columna <strong>key</strong> indica cual índice es usado, y el valor <strong>key_len</strong> contiene la parte más grande de la clave que fue usada. La columna ref será NULL para este tipo.</li>
<li><strong>Index:</strong> Escaneo completo de la tabla para cada combinación de filas de las tablas previas, revisando únicamente el índice.</li>
<li><strong>ALL:</strong> Escaneo completo de la tabla para cada combinación de filas. Es el peor caso ya que revisará todas las filas para cada combinación.</li>
</ul>
</li>
<li><strong>Possible_keys:</strong> Posibles indices que utilizará la consulta.</li>
<li><strong>Key:</strong> Índice utilizado para ejecutar la consulta. Si indica el valor NULL, no se ha escogido ningún índice.</li>
<li><strong>Key_len: </strong>Cuanto más pequeño sea este valor, más rápida será la consulta, pues nos indica la longitud del índice usado.</li>
<li><strong>Ref: </strong>Las columnas del índice que se está usando, o una constante si esta es posible.</li>
<li><strong>Rows: </strong>Número de filas que MySQL debe analizar para devolver los datos solicitados.</li>
<li><strong>Extra: </strong>Información complementaria sobre como MySQL ejecutará la consulta. Los posibles valores en este campo pueden ser:
<ul>
<li> <strong>Distinct</strong>: MySQL ha encontrado una fila coincidente con los filtros indicados y no necesita seguir analizando.</li>
<li><strong>Not exists:</strong> MySQL fue capaz de hacer una optimización LEFT JOIN sobre la consulta y no examinará más filas en la tabla para la combinación de filas previa después de que encuentre una fila que coincida con el criterio LEFT JOIN.</li>
<li><strong>Range checked for each record:</strong> No se encontró un índice válido. Para cada combinación de filas se hará un chequeo para determinar que indice utilizar y en caso de encontrar alguno válido, lo utilizará.</li>
<li><strong>Using filesort:</strong> Este valor indica que MySQL necesita hacer un paso extra para encontrar la forma de ordenar las filas. Este tipo de consultas <strong>debe ser optimizada</strong>.</li>
<li><strong>Using index:</strong> Recupera la información solicitada utilizando únicamente la información del índice. Esto sucede cuando todas las columnas requeridas forman parte del índice.</li>
<li><strong>Using temporary:</strong> Para resolver esta consulta, MySQL creará una tabla temporal. Uno de los casos típicos en los que devuelve este valor es cuando usamos un ORDER BY sobre un conjunto de columnas diferentes a las indicadas en la clausula GROUP BY. Este tipo de consultas <strong>debe ser optimizada</strong>.</li>
<li><strong>Where used:</strong> Se usará una clausula WHERE para determinar que filas serán comparadas con otra tabla. Si no deseamos regresar todas las filas desde la tabla, y el join es del tipo ALL o index, es muy probable que hayamos escrito algo mal en la consulta.</li>
</ul>
<p>Una respuesta en este campo del tipo &#8220;Using filesort&#8221; o &#8220;Using temporary&#8221; es susceptible de ser una consulta a optimizar.</li>
</ol>
<p>Si analizamos la consulta ejecutada anteriormente,vemos que para la tabla con alias &#8216;up&#8217; está utilizando el tipo de unión `ALL` debido a que no existe ningun filtro en la clausula WHERE (en este caso, es normal ya que queremos devolver todos los valores). Se podría utilizar el índice existente `user_id_idx` pero al no haber ningún filtro, no es necesario usarlo. Para devolver esta consulta MySQL analizará 13 filas.</p>
<p>La segunda fila hace referencia a la tabla con alias &#8216;u&#8217;. Utiliza un tipo de unión `eq_ref` ya que devolverá una fila para cada fila de la tabla `up` pudiendo usar y usando el índice primario de la tabla que tiene una longitud de 4 (muy pequeño). Se está utilizando la columna `user_id` del índice de la tabla `up` y de la base de datos `futbol` analizando una única fila para cada fila de la tabla contigua.</p>
<p>Todos los valores son correctos y podemos asegurar que esta consulta está optimizada!!</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/bases-de-datos/explain-mysql-para-optimizar-tus-consultas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como crear y modificar un campo autoincremental en Oracle</title>
		<link>http://www.tecnoretales.com/programacion/como-crear-y-modificar-un-campo-autoincremental-en-oracle/</link>
		<comments>http://www.tecnoretales.com/programacion/como-crear-y-modificar-un-campo-autoincremental-en-oracle/#comments</comments>
		<pubDate>Fri, 22 May 2009 22:30:19 +0000</pubDate>
		<dc:creator>Jordi Anta Ugarte</dc:creator>
				<category><![CDATA[Bases de datos]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=349</guid>
		<description><![CDATA[Muchas veces nos encontramos con la necesidad de crear un campo autoincremental en una tabla de nuestra base de datos. Típicamente suele usarse para generar una clave primaria para dicha tabla. Pues bien, la primera vez que nos enfrentamos con esta situación trabajando con Oracle, nos encontraremos con un grave problema que nos puede hacer [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>Muchas veces nos encontramos con la necesidad de crear un campo autoincremental en una tabla de nuestra base de datos. Típicamente suele usarse para generar una clave primaria para dicha tabla. Pues bien, la primera vez que nos enfrentamos con esta situación trabajando con Oracle, nos encontraremos con un grave problema que nos puede hacer perder mucho tiempo, puesto que, aunque parezca mentira, no existe ningún tipo de campo autoincremental en Oracle.</p>
<p>La solución es bastante sencilla (aunque no por ello deja de ser incómodo no disponer de un campo de este tipo directamente). Oracle dispone de un tipo de objeto denominado secuencia (SEQUENCE). Una secuencia tiene un valor inicial, un valor máximo y un valor de secuencia que incrementará cada vez que hagamos una llamada a la secuencia.<span id="more-349"></span></p>
<p>La estructura para crear una secuencia es la siguiente:</p>
<blockquote><p><strong>CREATE SEQUENCE sequence_name<br />
MINVALUE value<br />
MAXVALUE value<br />
START WITH value<br />
INCREMENT BY value<br />
CACHE value / NOCACHE;</strong></p></blockquote>
<p>Donde:</p>
<ul>
<li> MINVALUE es el valor mínimo que tendrá la secuencia (usualmente 0 o 1)</li>
<li>MAXVALUE es el valor máximo que tendrá la secuencia (se puede obviar y por defecto se le asignará 999999999999999999999999999)</li>
<li>START WITH es el valor con el que empezará la secuencia</li>
<li>INCREMENT BY es el valor con el que se incrementará la secuencia (usualmente 1, pero podríamos usar 2 para generar solo valores pares por ejemplo [siempre y cuando hubiesemos puesto el campo anterior a 0 o 2 <img src='http://www.tecnoretales.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  ] )</li>
<li>CACHE / NOCACHE el uso de CACHE permite indicar cuantos valores queremos que sean guardados en memoria para una acceso más rápido. El inconveniente que tiene es que en caso de una caida del sistema, los valores generados por la secuencia se pierden y quedarian &#8220;huecos&#8221;.</li>
</ul>
<p>Una vez creada la secuencia la usaremos llamando a <strong>sequence_name.nextval</strong>. Por ejemplo:</p>
<blockquote><p><strong>I</strong><strong>NSERT INTO mi_tabla (tabla_id, tabla_campo1) VALUES (mi_secuencia.nextval, &#8216;valor1&#8242;);</strong></p></blockquote>
<p>También podremos acceder al valor de la secuencia en una consulta haciendo la siguiente llamada (hay que tener en cuenta que esta llamada también nos incrementará el contador de la secuencia):</p>
<blockquote><p><strong>SELECT sequence_name.nextval FROM dual;</strong><strong><br />
</strong></p></blockquote>
<p>Por último veremos como podemos modificar el valor de la secuencia para asignarle uno arbitráriamente. Primero modificaremos la secuencia indicándole que a partir de este momento cada vez que sea llamada incremente su contador en tantas posiciones como la diferencia entre el valor que queremos asignarle (p.ej. si nuestra secuencia tiene valor 327 y queremos asignarle el 450, deberemos incrementar en 123).</p>
<blockquote class="sql_command"><p><strong>ALTER SEQUENCE seq_name INCREMENT BY 123;</strong></p></blockquote>
<p>Luego haremos una llamada a la secuencia para que se incremente con el nuevo valor:</p>
<blockquote class="sql_command"><p><strong>SELECT seq_name.nextval FROM dual;</strong></p></blockquote>
<p>Y por último volveremos a alterar la secuencia para que vuelva a incrementar igual que antes (en nuestro ejemplo de uno en uno)</p>
<blockquote class="sql_command"><p><strong>ALTER SEQUENCE seq_name INCREMENT BY 1;</strong></p></blockquote>
<p>También existe la posibilidad de generar campos autoincrementales creando un trigger que sea llamado antes de la inserción y se encargue de calcular el siguiente valor libre. O haciendo una consulta previa del primer valor libre del campo. Pero son técnicas más engorrosas y que pueden dar lugar a errores y problemas con más facilidad de la expuesta aquí.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/como-crear-y-modificar-un-campo-autoincremental-en-oracle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
