pu
Buscar este blog
jueves, 23 de junio de 2016
El computador más potente del mundo es chino
El computador construido con materiales 100 % chinos superó a su predecesor: otro computador chino.
(CCM) — Si tras la segunda guerra mundial el planeta vivió lo que se denominó la Guerra Fría, que consistió —entre muchos otros factores— en la carrera armamentística que emprendieron Rusia y Estados Unidos por demostrar su supremacía, hoy en día la guerra es de bytes y se lleva a cabo entre China y Estados Unidos. Ambas naciones se disputan el "privilegio" de tener el computador más potente del mundo. Por segunda vez consecutiva, son los chinos quienes ostentan el récord mundial en este apartado, según la lista ofrecida por el sitio TOP500 (en inglés).
El supercomputador ha sido denominado Sunway TaihuLight y fue construido utilizando procesadores y otros periféricos de fabricación 100 % china. El dispositivo cuenta con la nada desdeñable cifra de más de 10 millones de núcleos al interior de 40.650 procesadores. Con dicha maquinaria es capaz de ofrecer una potencia de proceso de 93 pentaflops, cinco veces más potente que el modelo estadounidense más avanzado de la actualidad.
Otro dato interesante es que China, con 167, supera el número de supercomputadores disponibles en Estados Unidos, quien posee 165. Es de esperar que los estadounidenses no tarden mucho en contraatacar. La guerra de los bytes no ha hecho más que comenzar.
Fuente:http://es.ccm.net/news/20254-el-computador-mas-potente-del-mundo-es-chino?een=001f7195faf534d8d54a6fe56fa382ec&utm_source=greenarrow&utm_medium=mail&utm_campaign=ml147_elcomputadormas
Etiquetas:
chino,
computador mas potente,
server,
server chino mas potente,
titanhosting
El computador más potente del mundo es chino
El computador construido con materiales 100 % chinos superó a su predecesor: otro computador chino.
(CCM) — Si tras la segunda guerra mundial el planeta vivió lo que se denominó la Guerra Fría, que consistió —entre muchos otros factores— en la carrera armamentística que emprendieron Rusia y Estados Unidos por demostrar su supremacía, hoy en día la guerra es de bytes y se lleva a cabo entre China y Estados Unidos. Ambas naciones se disputan el "privilegio" de tener el computador más potente del mundo. Por segunda vez consecutiva, son los chinos quienes ostentan el récord mundial en este apartado, según la lista ofrecida por el sitio TOP500 (en inglés).
El supercomputador ha sido denominado Sunway TaihuLight y fue construido utilizando procesadores y otros periféricos de fabricación 100 % china. El dispositivo cuenta con la nada desdeñable cifra de más de 10 millones de núcleos al interior de 40.650 procesadores. Con dicha maquinaria es capaz de ofrecer una potencia de proceso de 93 pentaflops, cinco veces más potente que el modelo estadounidense más avanzado de la actualidad.
Otro dato interesante es que China, con 167, supera el número de supercomputadores disponibles en Estados Unidos, quien posee 165. Es de esperar que los estadounidenses no tarden mucho en contraatacar. La guerra de los bytes no ha hecho más que comenzar.
Fuente:http://es.ccm.net/news/20254-el-computador-mas-potente-del-mundo-es-chino?een=001f7195faf534d8d54a6fe56fa382ec&utm_source=greenarrow&utm_medium=mail&utm_campaign=ml147_elcomputadormas
Etiquetas:
chino,
computador mas potente,
server,
server chino mas potente,
titanhosting
miércoles, 17 de febrero de 2016
cuanto gana un analista programador en chile
El espacio de analistas cada vez es mas demandado, y el saber cobrar sobre un trabajo nuevo siempre es difícil de saber, toma las riendas de tu futuro y analiza esta siguiente lista donde los sueldos marcaran tu mejor opción.
El área informática en Chile, se encuentra en desarrollo y la necesidad de técnicos para el rubro es cada vez mayor. Un estudio realizado por la consultora Segacy-Kibernum sobre salarios en el área de TI, nos entrega los siguientes resultados en sueldos mínimos y máximos
- Gerente de informática, $2.550.000.- / $10.100.000.-
- Subgerente de informática, $900.000.- / $4.500.000.-
- Jefe de área, $800.000.- / $3.200.000.-
- Jefe de proyectos, $906.667.- / $2.640.000.-
- Arquitecto de software, $990.000.- / $2.700.000.-
- Analista programador senior, $1.025.000.- / $1.983.333.-
- Analista programador, $850.000.- / $1.528.000.-
- Analista programador junior, $625.417.- / $1.200.000.-
Etiquetas:
area ti,
Cuanto gana Analista Programador,
junior,
Programador,
Senior,
Sueldo Informático
martes, 1 de septiembre de 2015
LECTURA Y ESCRITURA DE ARCHIVOS DE TEXTO CON PHP
En esta ocasión veremos unos ejemplos prácticos de lectura y escritura de ficheros de texto usando PHP. El primer lugar, debemos crear un archivo de texto (con cualquier editor, notepad por ejemplo, aunque también puede valer el bloc de notas de Windows) con algunas líneas de texto.
LECTURA DE FICHEROS
Para leer un archivo de texto línea a línea en PHP vamos a utilizar la función fgets(). Por ejemplo si queremos leer línea por línea el archivo 'archivo.txt' que se encuentra ubicado en la misma carpeta que el archivo 'leer.php', tenemos que escribir en el archivo PHP:
<?php //Ejemplo
$file = fopen("archivo.txt", "r");
while(!feof($file)) {
echo fgets($file). "<br />";
}
fclose($file);
?>
|
Como podemos observar, lo primero que debemos hacer es abrir el fichero 'archivo.txt' y luego ir leyendo línea a línea hasta llegar al final. Recordemos que “r” es el modo de apertura que abre el archivo sólo para lectura. La lectura comienza al inicio del archivo. Después cerramos el fichero.
Con esto conseguiremos mostrar por pantalla el contenido del fichero 'archivo.txt' tal y como podemos ver en la siguiente imagen de ejemplo.
El contenido del fichero de texto “archivo.txt” se supone que era el siguiente:
Prueba de escritura
esto es una linea de texto
esto es una linea de texto
esto es una linea de texto
esto es una linea de texto
esto es una linea de texto
fin de la prueba
|
Lo que hemos hecho con nuestro pequeño programa es ir extrayendo líneas mientras no se detecta el final del fichero (feof). La condición while(!feof($file)) también podría haberse escrito de esta otra manera: while(feof($file)==false), con lo que obtendríamos el mismo resultado.
ESCRITURA DE FICHEROS
Para escribir un archivo de texto en PHP podemos utilizar la función fwrite(). Por ejemplo si queremos escribir línea por línea un archivo 'archivo.txt' que se encuentre ubicado en la misma carpeta que el archivo 'escribir.php', tenemos que escribir en el archivo PHP:
<?php //Ejemplo, archivo escribir.php
$file = fopen("archivo.txt", "w");
fwrite($file, "Esto es una nueva linea de texto" . PHP_EOL);
fwrite($file, "Otra más" . PHP_EOL);
fclose($file);
?>
|
Nota: PHP_EOL (end of line) introduce un salto de línea en PHP. Mediante la concatenación con un punto forzamos el salto de línea después del texto introducido.
Una vez escribimos en nuestro navegador la ruta del fichero escribir.php se ejecuta el código asociado. Después de la ejecución, podemos ver el fichero creado con un editor de texto cualquiera y observaremos el siguiente contenido:
Tener en cuenta que el modo de apertura de archivo que hemos usado es w. Si recordamos el significado de este modo:
w: Abre el archivo sólo para escritura. La escritura comienza al inicio del archivo, y elimina el contenido previo del archivo. Si el archivo no existe, intenta crearlo.
AÑADIR CONTENIDO A UN FICHERO DE TEXTO
A veces no queremos reemplazar el contenido que exista en un fichero de texto, sino añadir un contenido adicional al final de lo que ya exista en el mismo. Vamos a ver cómo podemos hacerlo.
A modo de ejemplo añadiremos unas líneas de texto al final del fichero anteriormente escrito:
<?php //Ejemplo
$file = fopen("archivo.txt", "a");
fwrite($file, "Añadimos línea 1" . PHP_EOL);
fwrite($file, "Añadimos línea 2" . PHP_EOL);
fclose($file);
?>
|
Tener en cuenta que el modo de apertura de archivo que hemos usado es a. Si recordamos el significado de este modo:
a: Abre el archivo para sólo escritura. La escritura comenzará al final del archivo sin eliminar el contenido previo existente. Si el fichero no existe se intenta crear.
Ahora podemos ver el fichero creado con un editor de texto cualquiera y observaremos el siguiente contenido (no se ha reemplazado el contenido existente, sino que se ha ampliado):
Observamos que hemos añadido las dos nuevas líneas al final del archivo.
Etiquetas:
crea archivo con php,
escritura archivo,
lectura archivo,
PHP,
txt,
txt con php
lunes, 31 de agosto de 2015
APPNANA - Descarga Aplicaciones y gana puntos
AppNana
Recompensas tarjeta regalo gratuita!
La app de recompensas más popular para móviles iOS ¡ahora disponible para Android! ¡Prueba apps gratuitas y canjea tarjetas regalo gratis! Los miembros ganan más de 5 millones. de $ en juegos y créditos Clan of Clash
MY ID o Código de Invitación AppNana: t11894075
rp lol, xbox live, gta shark,fifa 15,ps card, League of Legends, dinero en paypal, bitcoin, steam.
Asi de facil solo descargando aplicaciones.
yo por lo general la instalo la dejo un día y después la elimino.
Recompensas tarjeta regalo gratuita!
La app de recompensas más popular para móviles iOS ¡ahora disponible para Android! ¡Prueba apps gratuitas y canjea tarjetas regalo gratis! Los miembros ganan más de 5 millones. de $ en juegos y créditos Clan of Clash
MY ID o Código de Invitación AppNana: t11894075
rp lol, xbox live, gta shark,fifa 15,ps card, League of Legends, dinero en paypal, bitcoin, steam.
Asi de facil solo descargando aplicaciones.
yo por lo general la instalo la dejo un día y después la elimino.
Etiquetas:
appnana,
chile,
codigo invitacion,
lol,
rp,
steam y mas
jueves, 23 de julio de 2015
TAREA SQL - SAKILA :P
1.-¿cúal es la cantidad de dinero que se recaudo en
arriendo de películas el mes de junio y julio del año
2005 para la tienda 2?
r:
select s.store_id,SUM(p.amount) from payment as p inner join staff as s on (s.staff_id= p.staff_id) where s.store_id = 2 and DATEPART(YEAR,p.payment_date) = 2005 and DATEPART(MONTH,p.payment_date) in (6,7) group by s.store_id --ahi esta listo el 1
2.- ¿Cúal es la cantidad de unidades de películas de categoría children que fueron arrendadas en la tienda 2 para el mes de julio y agosto del año 2005?
r:
select count(*) as cantidad_arriendos from rental where DATEPART(YEAR,rental_date) = 2005 and DATEPART(MONTH,rental_date) in (7,8) and inventory_id in(select inventory_id from inventory where film_id in (select film_id from film_category where category_id = 3))
3.- ¿cúal es la cantidad de unidades de peliculas de categoria "children" que fueron arrendadas el mes de mayo del año 2005?, en la cual participo el actor "helen voight"?
r:
select count(*) as cantidad_arriendos_que_participo_helen_voight from rental where DATEPART(YEAR,rental_date) = 2005 and DATEPART(MONTH,rental_date) in (5) and --mayo 2005 inventory_id in(select inventory_id from inventory where film_id in (select film_id from film_category where category_id = 3) And film_id in (select film_id from film_actor as fa inner join actor as a on (fa.actor_id = a.actor_id) where a.actor_id = 17) )
4.- cual es la cantidad de unidades de peliculas que fueron arendadas por tienda para el mes de febrero del año 2005?
r:
select * from rental where DATEPART(YEAR,rental_date) = 2005 and DATEPART(MONTH,rental_date) in (2) --esta es la 4 esta lista
select st.store_id,count(*) as cantidad_arriendos_por_tienda from rental as r inner join staff as s on (s.staff_id = r.staff_id) inner join store as st on (st.store_id = s.store_id) where DATEPART(YEAR,r.rental_date) = 2005 and DATEPART(MONTH,r.rental_date) in (2) GROUP by st.store_id
5.- ¿Cúal fue el cliente que más arrendo películas el mes de mayo del 2005?
r:
select top 1 c.first_name,c.last_name,count(r.rental_id) as cantidad_de_arriendo_mes_mayo2005 from customer as c inner join rental as r on (c.customer_id = r.customer_id) where DATEPART(YEAR,r.rental_date) = 2005 and DATEPART(MONTH,r.rental_date) in (5) group by c.first_name,c.last_name order by count(r.rental_id) desc
Cúal es la primera película arrendada?, donde participo el actor identificado como nº65
select * from actor where actor_id = 65 'ANGELA HUDSON'
select * from film
select * from film
select MIN(rental_date) from rental
select * from inventory
--ahora tenemos que saber cual es la primera peli arrendada, eso lo sacamos con la tabla de rental y un min ? si
SELECT top 1 dbo.film.film_id AS FID,dbo.film.title,MIN(dbo.rental.rental_date) as primera_fecha_arriendo FROM dbo.category LEFT OUTER JOIN dbo.film_category ON dbo.category.category_id = dbo.film_category.category_id LEFT OUTER JOIN dbo.film ON dbo.film_category.film_id = dbo.film.film_id INNER JOIN dbo.film_actor ON dbo.film.film_id = dbo.film_actor.film_id INNER JOIN dbo.actor ON dbo.film_actor.actor_id = dbo.actor.actor_id inner join dbo.inventory on dbo.inventory.film_id = dbo.film.film_id inner join dbo.rental on dbo.rental.inventory_id = dbo.inventory.inventory_id where actor.actor_id = 65 group by dbo.film.film_id ,dbo.film.title order by MIN(dbo.rental.rental_date) asc
7.- ¿Cúal es la cantidad de unidades de películas que fueron arrendadas con valores mayores a 11usd durante el mes de julio para la tienda 2?
r:
SELECT s.store_id as tienda, count(p.rental_id) AS Conteo_arriendos FROM dbo.payment AS p INNER JOIN dbo.rental AS r ON p.rental_id = r.rental_id INNER JOIN dbo.inventory AS i ON r.inventory_id = i.inventory_id INNER JOIN dbo.store AS s ON i.store_id = s.store_id INNER JOIN dbo.address AS a ON s.address_id = a.address_id INNER JOIN dbo.city AS c ON a.city_id = c.city_id INNER JOIN dbo.country AS cy ON c.country_id = cy.country_id INNER JOIN dbo.staff AS m ON s.manager_staff_id = m.staff_id where DATEPART(month,r.rental_date)=7 and p.amount > 10 and s.store_id = 2 GROUP BY s.store_id
r:
select s.store_id,SUM(p.amount) from payment as p inner join staff as s on (s.staff_id= p.staff_id) where s.store_id = 2 and DATEPART(YEAR,p.payment_date) = 2005 and DATEPART(MONTH,p.payment_date) in (6,7) group by s.store_id --ahi esta listo el 1
2.- ¿Cúal es la cantidad de unidades de películas de categoría children que fueron arrendadas en la tienda 2 para el mes de julio y agosto del año 2005?
r:
select count(*) as cantidad_arriendos from rental where DATEPART(YEAR,rental_date) = 2005 and DATEPART(MONTH,rental_date) in (7,8) and inventory_id in(select inventory_id from inventory where film_id in (select film_id from film_category where category_id = 3))
3.- ¿cúal es la cantidad de unidades de peliculas de categoria "children" que fueron arrendadas el mes de mayo del año 2005?, en la cual participo el actor "helen voight"?
r:
select count(*) as cantidad_arriendos_que_participo_helen_voight from rental where DATEPART(YEAR,rental_date) = 2005 and DATEPART(MONTH,rental_date) in (5) and --mayo 2005 inventory_id in(select inventory_id from inventory where film_id in (select film_id from film_category where category_id = 3) And film_id in (select film_id from film_actor as fa inner join actor as a on (fa.actor_id = a.actor_id) where a.actor_id = 17) )
4.- cual es la cantidad de unidades de peliculas que fueron arendadas por tienda para el mes de febrero del año 2005?
r:
select * from rental where DATEPART(YEAR,rental_date) = 2005 and DATEPART(MONTH,rental_date) in (2) --esta es la 4 esta lista
select st.store_id,count(*) as cantidad_arriendos_por_tienda from rental as r inner join staff as s on (s.staff_id = r.staff_id) inner join store as st on (st.store_id = s.store_id) where DATEPART(YEAR,r.rental_date) = 2005 and DATEPART(MONTH,r.rental_date) in (2) GROUP by st.store_id
5.- ¿Cúal fue el cliente que más arrendo películas el mes de mayo del 2005?
r:
select top 1 c.first_name,c.last_name,count(r.rental_id) as cantidad_de_arriendo_mes_mayo2005 from customer as c inner join rental as r on (c.customer_id = r.customer_id) where DATEPART(YEAR,r.rental_date) = 2005 and DATEPART(MONTH,r.rental_date) in (5) group by c.first_name,c.last_name order by count(r.rental_id) desc
Cúal es la primera película arrendada?, donde participo el actor identificado como nº65
select * from actor where actor_id = 65 'ANGELA HUDSON'
select * from film
select * from film
select MIN(rental_date) from rental
select * from inventory
--ahora tenemos que saber cual es la primera peli arrendada, eso lo sacamos con la tabla de rental y un min ? si
SELECT top 1 dbo.film.film_id AS FID,dbo.film.title,MIN(dbo.rental.rental_date) as primera_fecha_arriendo FROM dbo.category LEFT OUTER JOIN dbo.film_category ON dbo.category.category_id = dbo.film_category.category_id LEFT OUTER JOIN dbo.film ON dbo.film_category.film_id = dbo.film.film_id INNER JOIN dbo.film_actor ON dbo.film.film_id = dbo.film_actor.film_id INNER JOIN dbo.actor ON dbo.film_actor.actor_id = dbo.actor.actor_id inner join dbo.inventory on dbo.inventory.film_id = dbo.film.film_id inner join dbo.rental on dbo.rental.inventory_id = dbo.inventory.inventory_id where actor.actor_id = 65 group by dbo.film.film_id ,dbo.film.title order by MIN(dbo.rental.rental_date) asc
7.- ¿Cúal es la cantidad de unidades de películas que fueron arrendadas con valores mayores a 11usd durante el mes de julio para la tienda 2?
r:
SELECT s.store_id as tienda, count(p.rental_id) AS Conteo_arriendos FROM dbo.payment AS p INNER JOIN dbo.rental AS r ON p.rental_id = r.rental_id INNER JOIN dbo.inventory AS i ON r.inventory_id = i.inventory_id INNER JOIN dbo.store AS s ON i.store_id = s.store_id INNER JOIN dbo.address AS a ON s.address_id = a.address_id INNER JOIN dbo.city AS c ON a.city_id = c.city_id INNER JOIN dbo.country AS cy ON c.country_id = cy.country_id INNER JOIN dbo.staff AS m ON s.manager_staff_id = m.staff_id where DATEPART(month,r.rental_date)=7 and p.amount > 10 and s.store_id = 2 GROUP BY s.store_id
Etiquetas:
base de datos,
Inacap,
sakila,
SQL,
tarea
lunes, 13 de julio de 2015
COMO SABER SI EXISTE UN OBJETO (TABLA, STORE PROCEDURE) EN SQL
Con este simple script podemos verificar si existe un objeto como una tabla o store procedure en nuestra base de datosSQL utilizando la función EXISTS.
Codigo
USE NombreBaseDeDatos
GO
GO
IF EXISTS (SELECT * FROM sysobjects WHERE name=’sp_Procedimiento‘)
BEGIN
print ‘Existe’
END
print ‘Existe’
END
ELSE BEGIN
print ‘No existe‘
END
print ‘No existe‘
END
Usando la función EXISTS de SQL y haciendo un SELECT a la tabla SYSOBJECTS, podemos saber si existe el objeto que estamos buscando. El resultado de la funcion EXISTS nos devolvera un valor boleano, para este ejemplo utilizamos un IF, el cual, dependiendo del valor devuelto imprimira un mensaje indicandonos si econtro o no el objeto buscado(sp_Procedimiento).
Etiquetas:
exists table,
MSSQL2012,
script,
SQL
martes, 30 de junio de 2015
SQL Server 2008 R2 Express en español no entiende el Windows en español
Cuando el SQL Server 2008 R2 Express en español no entiende el Windows en español
y también
[Solucion] SQL server setup media does not support the language en Windows 7 SQL Server Express
Al intentar instalar Windows Server 2012 Express o 2008 r2, salía siempre una pop up window con el error
Esto es por tener un lenguaje especifico de una zona particular, en mi caso, el sistema esta configurado con Español (Chile). Debemos dejarlo más general, con Español (España).
Entonces, solo es:
Inicio->Panel de Control-> Reloj, idioma y region-> Configuracion regional y de idioma
Sale una pantalla pop up y se elige el formato Espanol (Espana).
Aplicar, Aceptar.
Ahora intentar instalar SQL Server nuevamente!
SQL server setup media does not support the language of the OS or does not have ENU localized files. Use the matching language-specific SQL Server media or change the OS local through Control Panel
Esto es por tener un lenguaje especifico de una zona particular, en mi caso, el sistema esta configurado con Español (Chile). Debemos dejarlo más general, con Español (España).
Entonces, solo es:
Inicio->Panel de Control-> Reloj, idioma y region-> Configuracion regional y de idioma
Sale una pantalla pop up y se elige el formato Espanol (Espana).
Aplicar, Aceptar.
Ahora intentar instalar SQL Server nuevamente!
Etiquetas:
ENU localized files. Use the matching language-specific SQL Server media or change the OS local through Control Panel,
SQL,
sql2008
jueves, 18 de junio de 2015
Validando en JavaScript las Url
Esta función la puedes utilizar dentro de los tag de "<Script>" en las paginas html que devolvera un true o false dependiendo si es valida o no.
function isValidUrl(url,obligatorio,ftp)
{
// Si no se especifica el paramatro "obligatorio", interpretamos
// que no es obligatorio
if(obligatorio==undefined)
obligatorio=0;
// Si no se especifica el parametro "ftp", interpretamos que la
// direccion no puede ser una direccion a un servidor ftp
if(ftp==undefined)
ftp=0;
if(url=="" && obligatorio==0)
return true;
if(ftp)
var pattern = /^(http|https|ftp)\:\/\/[a-z0-9\.-]+\.[a-z]{2,4}/gi;
else
var pattern = /^(http|https)\:\/\/[a-z0-9\.-]+\.[a-z]{2,4}/gi;
if(url.match(pattern))
return true;
else
return false;
}
si te funciona no olvides de compartir o dejar un comentario.
vamos sigueme @tmaoner
Etiquetas:
javascript,
script,
url,
validando
viernes, 22 de mayo de 2015
UN POCO DE MEJORAMIENTO QUERYS SQL!
He pensado que convendría tener en cuenta que hoy en día existen aún mejoras que podemos aportar a la hora de mejorar el rendimiento de las Queries que se lanzan desde nuestras aplicaciones, así que a continuación se desglosan una serie de mejores prácticas que creo que son de utilidad para la comunidad.
Uso de sintaxis UNION
Debemos tener en cuenta que por defecto un UNION equivale a realizar un SELECT DISTINCT sobre el resultado final de una query. En otras palabras, UNION toma los resultados de dos recordsets, los combina y realiza un SELECT DISTINCT de cara a eliminar las filas duplicadas. Este proceso ocurre incluso si no hay registros duplicados en el recordset final. Si sabemos que hay registros duplicados, y esto representa un problema para la aplicación, entonces haremos uso de UNION para eliminar estas filas duplicadas.
Por otro lado si sabemos que nunca habrá duplicado de filas o si las hay pero no representa un problema para la aplicación entonces deberemos usar UNION ALL en lugar de UNION. La ventaja de UNION ALL es que no realiza el SELECT DISTINCT, lo cual evita uns gran cantidad de trabajo y recursos al servidor SQL.
Otro caso bastante común es el que se explica en el siguiente ejemplo, imaginemos que queremos realizar una query para mezclar dos conjuntos de datos:
SELECT column_name1, column_name2
FROM table_name1
WHERE column_name1 = some_value
UNION
SELECT column_name1, column_name2
FROM table_name1
WHERE column_name2 = some_value
FROM table_name1
WHERE column_name1 = some_value
UNION
SELECT column_name1, column_name2
FROM table_name1
WHERE column_name2 = some_value
La misma query puede ser reescrita como se explica a continuación para mejorar el rendimiento de la misma:
SELECT DISTINCT column_name1, column_name2
FROM table_name1
WHERE column_name1 = some_value OR column_name2 = some_value
FROM table_name1
WHERE column_name1 = some_value OR column_name2 = some_value
Y puede mejorarse aún más si sabemos que la mezcla de estos dos grupos de datos a paesar de contener duplicados no afectan al funcionamiento de la aplicación eliminando el DISTINCT.
Un aspecto relativo al rendimiento es la evaluación del uso de la sentencia DISTINCT. Muchos desarrolladores aplican esta sentencia por defecto aunque no se necesite, Sólo debe usarse si sabemos que la query puede devolver duplicados, y además esto puede provocar un mal funcionamiento de la aplicación que hace uso de los datos.
La sentencia DISTINCT genera una gran cantidad de trabajo extra a SQL Server debido a que consume muchos recursos que son necesarios para otras queries que sean lanzadas dentro de la base de datos. Sólo se debe usar si es necesario.
Un aspecto que siempre se menciona en todos los libros de SQL es que debemos devolver nada más que los datos que se necesitan, y esto sobre todo referido a las columnas de datos. Debemos evitar el uso de SELECT * ya que esto además de devolver más datos de los que seguramente necesitemos, impide el uso de índices, añadiendo mayor degradación al rendimiento del sistema.
Si nuestra aplicación permite a los usuarios ejecutar queries, pero es difícil evitar en la aplicación de forma sencila el retorno de cientos de registros o incluso miles es posible usar el operador TOP con una sentencia SELECT. De este modo se puede limitar cuantas filas son devueltas incluso si el usuario no introduce ningún criterio que ayude a reducir el número de filas a devolver al cliente. Por ejemplo:
SELECT TOP 100 fname, lname FROM customers
WHERE state = 'mo'
WHERE state = 'mo'
Esta query limita los resultados a las 100 primeras filas, incluso si el criterio del WHERE de devuelve 10000 registros. Cuando el número especificado se alcanza, todos los procesos de la query se paran salvaguardando así recursos del SQL.
El operador TOP también permite seleccionar porcentajes, tal y como indica el siguiente ejemplo:
SELECT TOP 10 PERCENT fname, lname FROM customers
WHERE state = 'mo'
WHERE state = 'mo'
El resultado de SET ROWCOUNT es el mismo que TOP, pero en algunos casos puede tener peor rendimiento cuando se trata con listas no ordenadas, por ello es preferible el uso de TOP.
Otro aspecto importante de cara a mejorar el rendimiento de las queries, es tener en consideración que operadores dentro de la clausula WHERE tienen mejor rendimiento, a continuación se detalla una lista ordenada de mejor a peor rendimiento:
¾ =
¾ >, >=, <, <=
¾ LIKE
¾ <>
Además de esto, existen otros criterios que son también importantes a la hora de elaborar la condición de cualquier Query. Estas consideraciones son relativas a que ciertos operadores pueden prestarse a tener mejor rendimiento según se usen, a continuación detallamos estos casos, ordenados de mayor a peor rendimiento:
¾ Un literal único en lugar de varios usado al lado de un operador
¾ Un nombre de columna o de parámetro al lado de un operador
¾ Una expresión multi-operando al lado de un operador
¾ Un número único exacto al lado de un operador
¾ Un número único no exacto al lado de un operador (date, time)
¾ Datos de caracteres, Null
En el caso de haber varias expresiones dentro del WHERE, no se agiliza el rendimiento por ordenarlos, excepto en algunos casos.
Como norma hay que evitar las clausulas WHERE NON-SARGABLE, (esta palabra provienen de SARG que significa Search Argument y se refiere a una clausula WHERE que compara una columna con una constante).
En estos casos cuando una clausula es SARGABLE puede aprovecharse la funcionalidad de los INDICES (asumiendo que al menos hay uno) para acelerar la ejecución de la Query. En aquellos casos que la clausula WHERE sea NON-SARGABLE, significará que dicha clausula WHERE (o parte de ella) no puede aprovecharse de los INDICES, dando como consecuencia un table/scan y degradando el rendimiento de la Query.
Los argumentos de búsqueda en la cláusula WHERE, tales como “IS NULL”, “<>”, “!=”, “!>”,”!<”, “NOT”, “NOT EXIST”, “NOT IN”, “NOT LIKE” y “LIKE ‘%500’” generalemte previenen (pero no siempre) la utilización de un INDICE para realizar la búsqueda.
Adicionalmente las expresiones que incluyen una función sobre una columna, expresiones que tienen la misma columna en ambos lados de un operador o comparaciones contra una columna (y no una cosntante) son NO-SARGABLE.
Pero no todas cláusulas WHERE que tienen una expresión NON-SARGABLE provocan un TABLE/INDEX SCAN. Si la cláusula WHERE incluye cláusulas NON-SARGABLE y SARGABLE, entonces las cláusualas SARGABLE pueden usar un INDICE (si existe uno) para ayudar a acceder a los datos rápidamente.
En muchos casos si hay un COVERED INDEX en la tabla, que incluye todas las columnas en la SELECT, JOIN y WHERE entonces dicho INDICE puede ser utilizado en lugar de un TABLE/INDEX SCAN para devolver los datos, incluso si tiene un NON-SARGABLE en la cláusula WHERE.
Pero se debe tener en cuenta que los COVERED INDEX tienen sus propias desventajas, tales como producir INDICES muy extensos que pueden incrementar los I/O cuando son leídos. En algunos casos, es posible reescribir una cláusula WHERE NON-SARGABLE, por ejemplo:
WHERE substring(firstname,1,1) = ‘m’
Por
WHERE firstname LIKE ’m%’
Ambas cláusulas WHERE producen el mismo resultado, pero la primera es NON-SARGABLE (usa una función) y se ejecutará más lenta, mientras que la segunda es SARGABLE e irá más rápida.
Las cláusulas WHERE que realizan alguna función sobre una columna son NON-SARGABLE. Por otro lado si se puede reescribir la cláusula WHERE dando como resultado que la columna y la función estén separadas, entonces la QUERY puede usar un INDICE que esté disponible, aumentando así el rendimiento por ejemplo:
La función actúa directamente sobre la columna y el INDICE no puede usarse:
SELECT member_number, first_name, last_name
FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
La función ha sido separada de la columna y puede usar un INDICE:
SELECT member_number, first_name, last_name
FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
Cada una de las QUERIES anteriores produce el mismo resultado, pero la segunda QUERY usará un INDICE porque la función no se realiza directamente sobre la columna, como si ocurre en el primer ejemplo. El mensaje de esta historia es que se debe intentar reescribir las cláusulas WHERE que tengan funciones que actúen sobre columnas por cláusulas que no lo hagan.
Las cláusulas WHERE que usen el operador NOT son todas NON-SARGABLE, pero pueden ser reescritas para eliminar dicho operador, por ejemplo:
WHERE NOT column_name > 5
A
WHERE column_name <= 5
Es fácil identificar si una cláusula es NON-SARGABLE, se ejecuta en el Query Analizer mostrando el plan de ejecución para ver si se realiza un INDEX LOOKUP o un TABLE/INDEX SCAN.
Cuando nos encontramos con cláusulas WHERE NON-SARGABLE que contienen una función en el lado derecho de un signo igual, y no es posible reescribir dicha cláusula para que sea SARGABLE, existe la opción de crear un INDICE en una COLUMNA COMPUTADA. De este modo se evitará el WHERE NON-SARGABLE usando los resultados de la función el dicha cláusula.
Debido a la sobrecarga que requiere para los INDICES en COLUMNAS COMPUTADAS, sólo realizaremos esto si la QUERY la ejecutaremos una y otra vez desde la aplicación.
En el caso que tengamos que hacer uso del comando NOT IN tendremos que tener especial cuidado en su uso ya que posee un mal rendimiento ya que obliga al SQL Server Optmizer a realizar un SCAN, en su lugar mejor utilizaremos la siguientes opciones ordenadas de mejor a peor rendimiento:
¾ Usar EXISTS o NOT EXISTS
¾ Usar IN
¾ Realizar un LEFT OUTER JOIN y chequear por una condición NULL
Cuando exista la posibilidad de elegir entre IN o EXISTS utilizaremos siempre EXISTS, ya que tiene mejor rendimiento.
Es posible que podamos encontrarnos TABLE SCAN en las queries que lanzemos, a pesar de existir INDICES que mejorarían el rendimiento. En estos casos la mejor opción para forzar el uso de un INDICE es realizar los siguiente, como muestra el ejemplo:
SELECT * FROM tblTaskProcesses WHERE nextprocess = 1 AND processid IN (8,32,45)
Esto tarda 3 segundos y al siguiente QUERY tarda menos de un segundo:
SELECT * FROM tblTaskProcesses (INDEX = IX_ProcessID) WHERE nextprocess = 1 AND processid IN (8,32,45)
En el caso del comando LIKE es necesario entender que hay maneras más optimas en el uso de dicho comando. En el caso que nos trata del comando LIKE debemos en la medida de los posible usar una “leading character” esto es un carácter diferente de un “wildcard” (%,*, etc…).
Por ejemplo la query LIKE ‘%m’ tiene peor rendimiento que LIKE ‘m%’ ya que en el segundo caso (más optimo rendimiento) esta claúsula puede usar en el caso que exisitiera un INDICE para agilizar la búsqueda por el carácter. En el caso de que el “leading character” fuera un “wildcard” SQL tendría que realizar un SCAN previo.
A veces nuestras aplicaciones necesitan calcular sumarios de datos, con el consecuente coste de renmiento. Estos cálculos al vuelo par mantener un sumario son muy costosos, y en muchos casos la mejor opción es utilizar un trigger que una vez ejecutada la transacción haga el sumario de datos en una tabla auxiliar que se pueda consultar en cualquier momento.
A veces el coste de este trigger puede tener mejor rendimiento que calcular el sumario junto con la transacción lanzada.
Inserción de datos binarios de gran tamaño
Si nuestra aplicación necesita inserta insertar datos binarios de gran tamaño en una columna de datos, se debe realizar en primer lugar a través de un Store Procedure y no usar nunca una sentencia INSERT dentro de nuestra aplicación.
LA razón es ue la aplicación debe primero convertir los datos binarios en una cadena de caracteres (lo que hace doblar su tamaño incrementando el tráfico de red y llevando más tiempo) antes de que pueda ser enviada al servidor. Y cuando el servidor recibe la cadena de caracteres, tiene que convertirla de nuevo a datos binarios (llevandose aún más tiempo que en la primera conversión).
El uso de Store Procedures evita todo esto ya que la actividad ocurre en el servidor SQL Server y los datos transmitidos a través de la red son menores.
En el caso que nuestras QUERIES tenga que hacer uso de los comandos IN o BETWEEN haremos siempre uso de BETWEEN siempre que se pueda (existen casos que no es posible). Para entender porque veamos el siguiente ejemplo:
SELECT customer_number, customer_name
FROM customer
WHERE customer_number in (1000, 1001, 1002, 1003, 1004)
FROM customer
WHERE customer_number in (1000, 1001, 1002, 1003, 1004)
Es menos eficiente que la siguiente QUERY:
SELECT customer_number, customer_name
FROM customer
WHERE customer_number BETWEEN 1000 and 1004
FROM customer
WHERE customer_number BETWEEN 1000 and 1004
Asumiendo que existe un INDICE en customer_number el Query Optimizer de SQL Server puede localizar un rango de números más rápidamente mediante el uso de BETWEEN que con el uso de IN.
Si es posible debemos evitar el uso de la función SUBSTRING en las cláusulas WHERE. Dependiendo de cómo se construya la función SUBSTRING puede forzar un SCAN de TABLA en lugar de permitir al optimizador de SQL a usar un INDICE (asumiendo que exista uno). Si la subcadena que estamos buscando no incluye el primer carácter de la columna por la cual buscamos entonces se realiza un SCAN. Veamos un ejemplo:
WHERE SUBSTRING(column_name,1,1) = 'b'
Intentaremos usar en su lugar lo siguiente:
WHERE column_name LIKE 'b%'
Si nos decidimos a usar esta opción debemos considerar usar una condición para el LIKE que sea SARGABLE , esto significa que no podemos por un “wirldcard” en primer lugar.
Si existe una cláusula WHERE que incluye expresiones conectadas por dos o más operadores AND, SQL Server evaluará desde la izquierda hacia la derecha en el orden que hayan sido escritas. Esto asume que no se hayan usado paréntesis para cambiar el orden de la ejecución. Por esta razón se debe considerar lo siguiente cuando usemos el operador AND:
¾ Localizaremos la expresión menos probable de suceder y la pondremos en primer lugar de la expresión AND. De este modo si una expresión AND es falsa la cláusula finalizará inmediatamente ahorrando tiempo
¾ Si ambas partes de una expresión AND son iguales o tienen igual peso, y son falsas, pondremos la menos compleja primero. De este modo si es falsa la expresión se realizará menos trabajo para evaluar la expresión.
Si lo que queremos es mejorar el rendimiento de las QUERIES que contienen operadores AND en la cláusula WHERE debemos considerar lo siguiente:
¾ En las condiciones que se establezcan en la cláusula WHERE al menos una de ellas debería basarse en una columna lo más selectiva posible y que sea parte de un INDICE.
¾ Si al menos uno de los criterios de búsqueda en la cláusula WHERE no es altamente selectivo, consideraremos añadir INDICES para todas las columnas referenciadas en la cláusula WHERE.
Si ninguna de las columnas en la cláusula WHERE son suficientemente selectivas para usar su propio INDICE, consideraremos crear un “Covering Index” para esta QUERY.
Es posible que las QUERIES que lancemos nos encontremos que existen operadores OR que muchas veces pueden reescribirse mediante la sentencia UNION ALL, de cara a mejorar el rendimiento de la QUERY. Por ejemplo echemos un vistazo a la siguiente QUERY:
SELECT employeeID, firstname, lastname
FROM names
WHERE dept = 'prod' or city = 'Orlando' or division = 'food'
FROM names
WHERE dept = 'prod' or city = 'Orlando' or division = 'food'
Esta QUERY tiene tres condiciones en la cláusula WHERE separadas. De cara a que esta QUERY use un INDICE, debemos tener un INDICE sobre todas las columnas que están en dicha cláusula.
Este ejemplo puede ser reescrito usando un UNION ALL en lugar de un OR, tal y como muestra el ejemplo:
SELECT employeeID, firstname, lastname FROM names WHERE dept = 'prod'
UNION ALL
SELECT employeeID, firstname, lastname FROM names WHERE city = 'Orlando'
UNION ALL
SELECT employeeID, firstname, lastname FROM names WHERE division = 'food'
UNION ALL
SELECT employeeID, firstname, lastname FROM names WHERE city = 'Orlando'
UNION ALL
SELECT employeeID, firstname, lastname FROM names WHERE division = 'food'
Cada una de estas QUERIES producirá el mismo resultado. Si hay sólo un INDICE pero ninguna otra columna está en la cláusula WHERE entonces la primera versión no usará ningún INDICE y se realizará un TABLE SCAN.
Pero en la segunda versión de la QUERY usaremos el INDICE para parte de la QUERY pero no para toda la QUERY.
Admitimos que esto es un ejemplo muy sencillo, pero muestra cómo podemos mejorar la QUERY reescribiéndola, aunque la diferencia de rendimiento sería casi inapreciable, sin embargo con QUERIES más complejas las diferencias de rendimiento se hacen más notorias.
Debemos tener en cuenta que estamos usando UNION ALL en lugar de UNION. La razón es que el uso de UNION previene de realizar ordenaciones y evitar repeticiones, lo cual mejora el rendimiento. Naturalmente existe la posibilidad de duplicados, por lo que en esos casos si usaremos UNION siempre y cuando no haya otra opción tal y como explicamos en el puntoMejorar el rendimiento de UNION.
Usaremos ORDER BY en las QUERIES que lancemos sólo si es absolutamente indispensable, es decir, que si es posible realizar la ordenación en el lado del cliente siempre será mejor que realizarla desde el lado del servidor SQL Server.
En el caso que sea absolutamente necesario realizar la ordenación en el lado del servidor SQL Server, deberemos atender a las siguientes recomendaciones:
¾ Mantener el número de filas a ordenar al mínimo, haciendo esto mediante la devolución de aquellas filas que son absolutamente necesarias.
¾ Mantener el número de columnas a ordenar al mínimo. En otras palabras, no ordenar columnas no requeridas.
¾ Mantener el ancho (tamaño físico) de las columnas a ordenar al mínimo
¾ Ordenar columnas con tipos de datos numéricos en lugar de tipos de datos carácter
Cuando usemos cualquier mecanismo de ordenación en Transact –SQL, debemos tener en mente todas estas recomendaciones para la mejora del rendimiento.
Si se ha de ordenar por una columna a menudo, debemos considerar el realizar un “Clustered Index” sobre esa columna para la mejora del rendimiento.
Es posible que nos podamos encontrar el operador IN en cláusulas WHERE (y que este sea imposible sustituirlo por otro operador). En estos casos lo mejor que podemos hacer es lo siguiente; si hemos de contrastar una condición contra unos valores en un IN, debemos poner en la parte izquierda de dichos valores los que sean más frecuentes de encontrar, y al final de la lista los menos frecuentes.
Cuando nos encontremos con la necesidad de utilizar SELECT INTO debemos tener en cuenta que este tipo de sentencias pueden provocar un bloqueo en las tablas de sistema, impidiendo a otros usuarios el acceso a los datos que necesiten. Si se necesita usar SELECT INTO, deberemos intentar programar su uso cuando el usuario esté menos ocupado, y teniendo en cuenta que la cantidad de datos insertados sea la mínima posible.
Si la sentencia SELECT continene una cláusula HAVING, debemos escribir la QUERY de forma que la cláusula WHERE realice la mayor parte del trabajo (eliminando filas no deseadas) en lugar de hacer que la cláusula HAVING haga el trabajo de eliminar dichas filas. Usando la cláusula WHERE apropiadamente podemos eliminar filas innecesarias antes de lanzar el GROUP BY y el HAVING evitando así trabajo extra y mejorando así el rendimiento.
Por ejemplo en una SELECT con cláusulas WHERE, GROUP BY y HAVING ocurre lo siguiente:
En primer lugar la cláusula WHERE es usada para seleccionar las filas apropiadas que necesitan ser agrupadas. Lo próximo es agrupar mediante GROUP BY que divide las filas en grupos y agrega sus valores. Por último la cláusula HAVING elimina los grupos no deseados.
Si la cláusula WHERE es utilizada para eliminar el mayor número posible de filas no deseadas implicará que la sentencia GROUP BY y HAVING tendrán menos trabajo que hacer y mejorará el rendimiento.
La cláusula GROUP BY puede usarse con o sin una función de agregación. Pero si queremos obtener un mejor rendimiento, no usaremos la cláusula GROUP BY sin una función de agregación. Esto es porque produce el mismo resultado usar DISTINCT y es más rápido.Veamos un ejemplo:
USE Northwind
SELECT OrderID
FROM [Order Details]
WHERE UnitPrice > 10
GROUP BY OrderID
SELECT OrderID
FROM [Order Details]
WHERE UnitPrice > 10
GROUP BY OrderID
O
USE Northwind
SELECT DISTINCT OrderID
FROM [Order Details]
WHERE UnitPrice > 10
SELECT DISTINCT OrderID
FROM [Order Details]
WHERE UnitPrice > 10
Ambas QUERIES dan el mismo resultado, pero la segunda obtendrá mejor rendimiento, ya que usa menos recursos.
Para acelerar el uso de la cláusula GROUP BY debemos seguir las siguientes recomendaciones:
¾ Mantener el número de fílas a devolver por la QUERY tan pequeño como sea posible
¾ Mantener el número de agrupaciones tan limitado como sea posible
¾ No agrupar columnas redundantes
¾ Si hay un JOIN en la misma SELECT que tiene un GROUP BY, intentar reescribir la QUERY usado una SUBQUERY en lugar de usar un JOIN. Si es posible hacer esto, el rendimiento sera major. Si se tiene que usar un JOIN, intentaremos hacer el GROUP BY por columna desde la misma tabla que la columna o columnas sobre la cual la se usa la función.
Consideraremos el añadir un ORDER BY a la SELECT que ordena por la misma columna que el GROUP BY. Eso puede producir que el GROUP BY tenga mejor rendimiento.
A veces la percepción que tenemos del rendimiento de las QUERIES es sólo eso, una percepción, ya que en muchas ocasiones los resultados a devolver son tan extensos, que las QUERIES llevan su tiempo. Es en estos casos cuando podemos aprovechar las funcionalidades que brinda SQL Server para cambiar la percepción sobre el rendimiento, para ello podemos hacer uso de FAST, de la siguiente forma:
OPTION(FAST number_of_rows)
Donde number_of_rows es el número de filas a devolver mientras la QUERY sigue ejecutándose en background hasta devolver todos los demás registros.
En lugar de usar tablas temporales, usaremos tablas derivadas para mejorar el rendimiento de nuestra QUERY. Esto funciona de la siguiente forma:
SELECT num_Customer, dt_Date FROM (SELECT num_Customer, dt_Date, nom_Customer FROM Customers)
Con este tipo de tablas mejoramos el rendimiento de nuestra QUERY ya que se producen menos operaciones de I/O sobre el servidor.
Es bastante común realizar comparaciones entre tablas padre y tablas hijas, existen tres formas de realizar dichas comparaciones que a continuación explicamos en ejemplos y que sirven para encontrar si hay registros padre que no tienen su igual en la tabla hija:
Usando NOT EXISTS
SELECT a.hdr_key
FROM hdr_tbl a
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)
FROM hdr_tbl a
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)
Usando LEFT JOIN
SELECT a.hdr_key
FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key
WHERE b.hdr_key IS NULL
FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key
WHERE b.hdr_key IS NULL
Usando NOT IN
SELECT hdr_key
FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)
FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)
En cada caso las QUERIES anteriores devuelven el mismo resultado. Pero ¿cuál de ellas tiene mejor rendimiento?. Asumiendo que todo lo demás es igual, la versión que tiene mejor rendimiento es la primera y la última es la que peor rendimiento tiene (están ordenadas de mejor a peor rendimiento). En otras palabras la variación NOT EXISTS es la QUERY más eficiente.
Esto es generalmente, quiero decir que a pesar de esto y dependiendo de los INDICES y el número de filas en cada tabla puede variar el resultado.
Si necesitamos verificar si un registro existe en una tabla no usaremos nunca SELECT COUNT (*) para identificarla ya que es muy ineficiente y utiliza recursos de servidor de forma masiva.
En su lugar la sentencia Transact-SQL IF EXISTS para determinar si el registro en cuestión existe que es mucho más eficiente. Por ejemplo:
Usando SELECT COUNT (*):
IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx')
Usando IF EXISTS (mucho más rápido):
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
La razón por la cual IF EXISTS es más rápido que SELECT COUNT (*) es porque en el momento que dicha QUERY encuentra el registro finaliza inmediatamente, mientras que COUNT(*) debe contar todas las filas.
Etiquetas:
ayuda sql,
consultas sql,
MEJORAMIENTO,
MSSQL2000,
MSSQL2005,
MSSQL2008,
MSSQL2012,
MSSQL2015,
primeras consultas sql,
QUERYS,
SQL
Suscribirse a:
Entradas (Atom)