2011-06-06 11 views
5

Tengo dos tablas: A - 301 columnas (primera llamada a1 int (11) Clave principal, 2da a 301ª - doble (15,11)) & B - 33 columnas (1st one - b1 int (11) Clave única, 2nd One - b2 varchar (100) Clave principal, ..., 33.a - b33 int (11) MUL).Selección de Mysql en la desaceleración de la columna indexada en tablas grandes

Ambos A & B tienen ~ 13,500,000 registros.

Mi consulta MySQL: Para cada valor de punto de venta, con el POS en el conjunto (1, 1000, 2000, ..., 13500000) en múltiplos de 1000:

seleccione A. *, B2, B5 , b7, b8, b10, b13, b33 de A unión B en a1 = b1 donde b33> = pos y b33 < pos + 1000;

La consulta tarda 1-5 segundos para los valores de b33 < = 600,000. Después de eso, la consulta comienza a tomar de 20 a 30 segundos. Cuando b33> = 8,000,000 la consulta comienza a tomar 60-70s. No puedo entender por qué está ocurriendo la desaceleración. b33 está indexado y la unión tiene lugar en la clave que se define como primaria en una tabla y única en la otra. ¿Hay una solución para esto? Esto realmente está obstaculizando la velocidad del código y tendré que dividir las tablas A & B en varias más pequeñas si nada funciona. ¡Realmente espero no tener que hacer eso! ¡Por favor ayuda!

EDIT: Aquí está la O/P de EXPLIQUE -

** * ** * ** * ** * * 1. fila * ** * ** * ** * ** *
id: 1
SELECT_TYPE: SIMPLE
tabla: B
tipo: gama
possible_keys: B1, B33
clave: b33
key_len: 4
ref: NULL
filas: 981
Extra: Usando donde
* ** * ** * ** * ** * 2.fila * ** * ** * ** * ** *
id: 1
SELECT_TYPE: SIMPLE
tabla: A
tipo: eq_ref
possible_keys: PRIMARIO
clave: PRIMARIO
key_len: 4
ref: DBName.B.b1
filas: 1
adicionales:
2 rows in set (0.00 sec)

+0

¿Tiene un valor particular> 600,000 para el cual el rendimiento cae repentinamente de ~ 5s a ~ 20s? –

+0

No. Tengo más como un rango. Publicar 650,000 es una pesadilla. – ayesha129

+0

Esa es la salida de la explicación de la lenta, supongo. Y el rápido? Tiene la misma salida? – Samuel

Respuesta

0

yo no soy MySQL (o cualquier cosa) guru pero algunas cosas que me gustaría tener en cuenta. Primero, ¿b33 está distribuido uniformemente? ¿Puede ser más lento porque está recuperando efectivamente más filas? En segundo lugar, ¿ha considerado hacer todo el trabajo en una sola consulta en lugar de 13500? Algo así como:

select A.*, b2, b5, b7, b8, b10, b13, b33, (b33 - 1 DIV 1000) the_group 
from A join B on a1=b1 

En tercer lugar, una suposición, si su versión de MySQL tiene, usar una vista inlinew para hacer el filtrado de primera:

select A.*, b2, b5, b7, b8, b10, b13, b33 
from A join (select b1,b2, b5, b7, b8, b10, b13, b33 
      from B b33 >= pos and b33 < pos+1000) B_NEW 
    on a1=b1 ; 

Cuarto (debería ser en primer lugar), hacer una explique el plan y trate de averiguar por qué la consulta es lenta comparando las consultas rápidas con las lentas.

Buena suerte !!

+0

Sí. b33 está distribuido uniformemente. Aquí está el resultado de la explicación: – ayesha129

+0

'*************************** 1. row *********** **************** id: 1 SELECT_TYPE: SIMPLE tabla: b tipo: gama possible_keys: i1, Identificación del clave: id key_len: 4 ref: NULL filas: 981 Extra: utilizando donde *************************** 2.fila *************************** id: 1 SELECT_TYPE: SIMPLE tabla: un tipo : eq_ref possible_keys: PRIMARIA clave : PRIMARIO key_len: 4 ref: ja_StepUp.b.resid filas: 1 Extra: 2 filas en el conjunto (0.00 seg) ' – ayesha129

0

Sólo un tiro en la oscuridad ...

select A.*, b2, b5, b7, b8, b10, b13, b33 
    from A join B 
    on a1=b1 
    where b33 BETWEEN pos AND pos+999; 
0

nos muestras los índices que haya configurado en la B? (Interesados ​​en cómo se define el índice de B33, y si se define en una sola columna, o en varias columnas):

SHOW INDEXES FROM B; 

¿Ves la misma disminución de velocidad cuando sólo se selecciona a partir de B?

es decir

select b2, b5, b7, b8, b10, b13, b33 from B where b33 >= pos and b33 < pos+1000; 

¿Nos puede la parte de la SHOW CREATE TABLE que implica b33 campo (interesado en NULL permitido)

¿Está usando MyISAM o InnoDB como motor de base de mostrar? (Puede ver esto en el resultado de SHOW CREATE TABLE).

0

explicar el plan y los índices parecen estar bien.

me sugieren que usted pueda comparar los perfiles y ver donde el tiempo realmente va:

SET profiling=1; 

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B on a1=b1 where b33 >= 0 and b33 < 1000; 
SHOW PROFILE; 

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B on a1=b1 where b33 >= 1000000 and b33 < 1001000; 
SHOW PROFILE; 


SET profiling=0; 

pero creo que tal vez lento debido a índice de post 600k no cabe en la memoria más y más búsquedas en disco están hechos

0

¡NECESITA REFACTAR ESTA CONSULTA!

Aquí es su consulta antigua:

select A.*, b2, b5, b7, b8, b10, b13, b33 
from A join B on a1=b1 where b33 >= pos and b33 < pos+1000; 

Aquí es el nuevo:

SELECT 
    AAA.*,b2,b5,b7,b8,b10,b13,b33 
FROM 
    A AAA INNER JOIN 
    (
     select 
      A.a1,b2,b5,b7,b8,b10,b13,b33 
     from 
      A INNER JOIN 
      (
       SELECT 
        b1,b2,b5,b7,b8,b10,b13,b33 
       FROM B 
       WHERE 
        b33 >= pos and 
        b33 < pos+1000 
      ) BB 
      ON A.a1=B.b1 
    ) BBB 
    USING (a1) 
; 

Claves clínicas

El objetivo de esta consulta refactorizado es hacer que las tablas temporales dentro de la consulta plan lo más pequeño posible. De hecho, subconsulta BBB nunca debe tener más de 1000 filas en un momento dado.

¡Pruébalo!

0

ayesha129p,

trate de mover las limitaciones B33 en la cláusula de combinación. Parece que el optimizador solo está aplicando una de las restricciones b33 pre-join-set-creation.

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B 
    on a1=b1 and b33 >= pos and b33 < pos+1000; 

De esta forma, el optimizador debe usar el índice b33 y reducir la fila B establecida en 1000 antes de intentar la unión.

1

Dado que su base de datos tiene varios millones de registros, ¿está haciendo algo para mantener su BD en buen estado de salud?

Ejecutar el siguiente comando noche podría ayudar con la reactividad general si los datos cambian con frecuencia (un montón de plantillas, tal vez?):

mysqlcheck --check --analyze --auto-repair --all-databases --silent

Aunque yo sugeriría reading up a bit on mysqlcheck antes de ejecutar el comando, para que lo saber lo que está haciendo

También debe consultar optimizing your InnoDB configuration, especialmente innodb_buffer_pool_size (cuanta más memoria pueda darle, mejor). Estaba experimentando una lentitud similar en un campo basado en la fecha (que, por supuesto, indexamos inmediatamente) en una tabla de tamaño similar, y aumentar el tamaño del grupo de búferes de los 8 megabytes por defecto a varios gigabytes hizo una diferencia muy notable.

Si está eliminando muchas filas de cualquier tabla involucrada en la unión, también puede considerar ejecutar OPTIMIZE TABLE.

Cuestiones relacionadas