Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Consulta Lenta

Estas en el tema de Consulta Lenta en el foro de Mysql en Foros del Web. Hola!! mi problem es el siguiente, estoy realizando un sistema que se encarga de buscar información almacenada en una base de datos. Los campos que ...
  #1 (permalink)  
Antiguo 03/11/2008, 13:34
 
Fecha de Ingreso: junio-2006
Mensajes: 330
Antigüedad: 17 años, 10 meses
Puntos: 4
Consulta Lenta

Hola!! mi problem es el siguiente, estoy realizando un sistema que se encarga de buscar información almacenada en una base de datos. Los campos que manejo en este buscador son: fecha(desde, hasta) y categoría. Mi base de datos consta de dos tablas idénticas, por ejemplo, tabla1 y tabla2, donde en tabla1 se almacena la información de dias anteriores al de hoy (una especie de histórico) y tabla2, donde me almacena la información del día.

El problema viene cuando busco información, ya que se tarda demasiado, la consulta que realizo es la siguiente:

Código PHP:
SELECT FROM tabla1 WHERE categoria '761' AND fecha BETWEEN '2008-09-10' AND '2008-09-11' 
Son aproximadamente 150 categorias, las cuales se encuentran almacenadas en un array, el mismo lo recorro con un foreach y voy buscando una por una en la tabla1, y luego la busco en la tabla2, para almacernarno en un array y luego recorrer este otro array.

Sé que lo lento puede ser esta recorredera de tantas cosas, pero necesito obtener los datos de ambas tablas (la historica y la diaria), y tambien los id de categorias.

En la tabla historica tengo aproximadamente 300 mil registros y ambas estan en myisam
¿Alguna sugerencia para optimizar estas consultas?
  #2 (permalink)  
Antiguo 04/11/2008, 03:11
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Consulta Lenta

Sobre la consulta que mandas no se puede hacer nada és muy simple.

Puedes trabajar sobre el squema de bbdd, crear indices sobre las fechas, dividir la tabla1 (historico) en distintas tablas (por fechas o por categorias)...

tabla1_enero
tabla1_febrero

....

y consultar la que toque en funcion de las fechas que busques...

Quim
  #3 (permalink)  
Antiguo 04/11/2008, 07:40
 
Fecha de Ingreso: junio-2006
Mensajes: 330
Antigüedad: 17 años, 10 meses
Puntos: 4
Respuesta: Consulta Lenta

Hola, gracias por responder, bueno ya he creado indices en esas tablas, un índice categoria y otro fecha, pero igual es lento, en la historica. La separé en dos ya que diariamente se ingresa información, y una vez ingresada ésta, la consultan, entonces cuando estaba en una sola se hacía muy lenta la consulta porque supongo que tenia muchos registros (para aquel entonces 150 mil), y claro al separarla la información del día al consultarla fue mucho mas rápida ya que diariamente se limpia y se dejan solo los datos día.

Pero ahora me han pedido un buscador entre fechas y es allí donde me enrollo toda, es lentisima la consulta, y si la separo como me dices igual se tardaría no crees? buscando los datos de tabla en tabla. Yo siempre he tenido esta curiosidad, existen sistemas en empresas que deben tener más de 500 mil registros, como hacen esas grandes empresas para menejar tanta data??? la separan así como me mencionas? qué métodos utilizan para el tratamiento de tanta información?

Muchisímas gracias por responder, espero alguna acotación con respecto a las preguntas planteadas.
  #4 (permalink)  
Antiguo 04/11/2008, 08:01
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Consulta Lenta

De entrada hay motores mas rapidos que otros... luego por ejemplo en oracle en la consulta se le puede indicar que indice usar, con lo que se mejora el rendimeinto, tambien hay formas de optimizar la forma en que se guardan fisicamente los registros en disco para mejorar la eficiencia de las busquedas...

Yo te planteaba dividir la tabla historico no en dos sino en varias y luego lanzar la consulta sobre la que corresponda via programación si las fechas son de enero solo consultamos la tabla que contiene los registros de enero si son de dos meses consecutivos una consulta con un UNION ALL podria funcionar, la question es evitar una busqueda sobre todo el historico... Todo de penderar del tipo de consultas que se van a hacer ... por ejemplo si solo se consulta lo de 12 meses antes muy esporadicamente se podria admitir que sea lenta y guardar todos los registros en una sola tabla y los de meses mas cercanos en tablas para cada mes....


Busca informacion de como optimizar la bbdd en tu motor MySql supongo...

Quim
  #5 (permalink)  
Antiguo 04/11/2008, 11:41
Avatar de Carxl
Colaborador
 
Fecha de Ingreso: agosto-2006
Ubicación: Bogotá
Mensajes: 2.993
Antigüedad: 17 años, 8 meses
Puntos: 70
Respuesta: Consulta Lenta

Hola greisy, cómo vas??

Pues antes que nada no uses en tus consultas el comodín "*"(asterisco), consume mas recursos del motor.

Luego, si ya usas índices, ejecuta explain

http://www.mysql-hispano.org/page.php?id=29&pag=8

Un link para optimizar consultas, no sé que tan "oficial" sea, pero me parece acertado:

http://aurea.es/2007/08/30/optimizar...ltas-en-mysql/

Y otro mas para lo mismo:
http://www.programacion.com/php/tutorial/mysql_indices/

Saludos, espero te sirva
__________________
Hay 10 tipos de personas, los que entienden binario y los que no. (Anónimo)
www.programandoweb.com
  #6 (permalink)  
Antiguo 04/11/2008, 16:22
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Consulta Lenta

Una parte de tu enrollo es que estás combinando bases de datos y programación para ahcer una tarea que la base de datos está capacitada para hacer mejor por sí sola...
Me explico:
Si lo que quieres es listar todo el contenido de tabla1, donde la fecha esté en un rango y los datos comprendidos en una lista de categorías, tienes dos formas:
1. Si quieres seguir usando el array, te recomiendo que los pases directamente como parámetro de consulta, de modo de poder usar la cláusula IN:
Código sql:
Ver original
  1. SELECT *  
  2. FROM tabla1
  3. WHERE fecha BETWEEN '2008-09-10' AND '2008-09-11'
  4. AND categoria IN(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

donde "1, 2, 3, 4, 5, 6, 7, 8, 9, 10" representaría el contenido del parámetro pasado al string y construido sobre la base del array. En este sentido, la idea es que pases TODOS LOS VALORES separados por comas como parte del string y ubicados dentro del paréntesis del IN().
Es muy eficiente y rápido.
Si además quisieras agrupar u ordenar el resultado, puedes hacer algo como esto:

Código sql:
Ver original
  1. SELECT *  
  2. FROM tabla1
  3. WHERE fecha BETWEEN '2008-09-10' AND '2008-09-11'
  4. AND categoria IN(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
  5. ORDER BY fecha, categoria;
Esto te devolvería el resultado ordenado por fecha y categoría, simplemente.

2. La otra opción es si deseas usar la totalidad de las categorías. Allí te conviene tener una tabla CATEGORIA y realizar la consulta directamente cruzando los resultados:

Código sql:
Ver original
  1. SELECT *  
  2. FROM tabla1
  3. WHERE fecha BETWEEN '2008-09-10' AND '2008-09-11'
  4. AND categoria IN(SELECT categoria_id FROM categorias)
  5. GROUP BY fecha, catedoria;
El resultado es en esencia idéntico, pero la diferencia (que mejora la cosa) es que si aumentas el numero de categorías de la tabla, no es necesario modificar el script de la consulta, porque los valores nuevos se incluyen dinámicamente.
Cualquiera de estos dos casos será más rápido que lo que actualmente estás haciendo, en esencia porque el método que estás usando realiza demasiadas consultas a la base... y precisamente lo que debes siempre tratar de evitar es que el motor de base de datos realice lecturas a disco. Mientras menos veces acceda al disco, mejor erá la performance.

Como agregado, un consejo que te dieron más arriba es cierto: Trata de evitar traer todos los campos a menos que sea estrictamente necesario. El SELECT * ... es la forma más ineficiente y de peor performance en una consulta. Además: ¿para que traer 54 campos (supongamos) si en realidad voy a manipular y usar 7? No tiene sentido.

Tip final: Si quieres saber cómo se hace para calcular el costo en tiempo de una consulta, recuerda:
a) Los motores de bases de datos leen los registros por bloques (agrupan los registros en bloques de tamaño fijjo).
b) Los bloques son habitualmente de 64 kb.
c) Cada bloque es un acceso al disco (overhead de hardware) y cada acceso a disco es tiempo de microprocesador.
d) La longitud en bytes de un registro se debe usar para calcular cuántos regisrtos entran en un bloque. Ese resultado lo usas para dividir la cantidad de registros devueltos por una consulta, y que en MySQL lo puedes obtener usando el EXPLAIN. Una de las columnas expresa cuantos registros afecta cada parte de la consulta.
e) Ese cálculo te dirá cuántos accesos a disco usa una consulta.
Recuerda: Mientras menos accesos a d sico uses, más eficiente es la consulta.

Para reducirlos, hay muchas técnicas:
- Aumentar la selectividad de la consulta (escribirla de modo que devuelva la cantidad mas específica de registros).
- Crear índices no agrupados que cubran la selectividad del WHERE.
- Forzar el uso de diferentes índices para adecuar la consulta. Si los campos del SELECT están en el índice, entonces MySQL no lee la tabla (!).
- No poner demasiadas validaciones en el WHERE, no es optimizable.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:35.