Problema de rendimiento en BBDD


#1

Me va demasiado lento hacer esto:

Contenido.all(:conditions => “tema = 11”, :order => “created_at”, :limit
=> 2)

La tabla “contenidos” tiene 200.000 registros, de los cuales unos 20.000
tienen tema=11; pero tengo definido un índice sobre los campos (tema +
created_at), de forma que la BBDD entiendo que debería acceder
directamente a los registros en cuestión…

Sin embargo, no va como debería, y un “explain SELECT * FROM contenidos
WHERE tema = 11 ORDER BY created_at LIMIT 2;” revela que, aun pasando
por el índice correcto, está recorriendo 13958 registros!! ¿Alguien sabe
cuál puede ser el problema?

s2


#2

Sería de gran utilidad que pegaras ese EXPLAIN (ejecutado con \G) y un
show index de esa tabla.

2008/12/1 Fernando C. removed_email_address@domain.invalid:


#3

Fernando B. wrote:

Sería de gran utilidad que pegaras ese EXPLAIN (ejecutado con \G) y un
show index de esa tabla.

2008/12/1 Fernando C. removed_email_address@domain.invalid:

Estoy alucinando… ahora el mismo explain dice que pasa por 491
registros, empleando el mismo índice!!

Respecto al explain, dice esto:
Possible keys: index_contenidos_on_tema_and_created_at,
index_contenidos_on_tema_and_ultima_respuesta_id,
index_contenidos_on_tema_and_veces_leido,
index_contenidos_on_tema_and_respuestas_count

Key: index_contenidos_on_tema_and_created_at

Key_len: 5

Ref: const

Rows: 491 (hoy)

Extra: Using where

Y la tabla:

CREATE TABLE contenidos (
id int(11) NOT NULL auto_increment,
parent_id int(11) default NULL,
inicial_id int(11) default NULL,
usuario_id int(11) NOT NULL,
subtipo_id int(11) NOT NULL,
publicado tinyint(1) default ‘1’,
tema int(11) default ‘0’,
titulo varchar(255) NOT NULL,
texto_completo text,
keywords varchar(255) default NULL,
descripcion varchar(400) default NULL,
permalink varchar(255) default NULL,
contenido_link varchar(255) default NULL,
usr_nick varchar(255) default NULL,
usr_nick_limpio varchar(255) default NULL,
veces_leido int(11) default ‘0’,
votos_count int(11) default ‘0’,
images_count int(11) default ‘0’,
respuestas_count int(11) default ‘0’,
ultima_respuesta_id int(11) default NULL,
contador int(11) default ‘0’,
producto_id int(11) default NULL,
lo_mejor varchar(255) default NULL,
lo_peor varchar(255) default NULL,
area1 int(11) default NULL,
area2 int(11) default NULL,
area3 int(11) default NULL,
puntuacion int(11) default NULL,
cliente varchar(255) default NULL,
fecha_cliente datetime default NULL,
cotizacion decimal(10,2) default NULL,
copyright varchar(255) default NULL,
fecha_titulares datetime default NULL,
created_ip varchar(255) default NULL,
updated_ip varchar(255) default NULL,
updated_usuario varchar(255) default NULL,
created_at datetime default NULL,
updated_at datetime default NULL,
leido_dia int(11) default ‘0’,
leido_semana int(11) default ‘0’,
PRIMARY KEY (id),
KEY ultima_respuesta_id (ultima_respuesta_id),
KEY index_contenidos_on_inicial_id_and_publicado_and_created_at
(inicial_id,publicado,created_at),
KEY index_contenidos_on_usuario_id_and_inicial_id
(usuario_id,inicial_id),
KEY index_contenidos_on_tema_and_created_at (tema,created_at),
KEY index_contenidos_on_subtipo_id_and_created_at
(subtipo_id,created_at),
KEY index_contenidos_on_created_at (created_at),
KEY index_contenidos_on_usuario_subtipo_publicado_created_at
(usuario_id,subtipo_id,publicado,created_at),
KEY index_contenidos_on_usuario_id_and_tema_and_created_at
(usuario_id,tema,created_at),
KEY index_contenidos_on_tema_and_ultima_respuesta_id
(tema,ultima_respuesta_id),
KEY index_contenidos_on_tema_and_veces_leido (tema,veces_leido),
KEY index_contenidos_on_tema_and_respuestas_count
(tema,respuestas_count),
KEY index_contenidos_on_producto_id_and_publicado_and_created_at
(producto_id,publicado,created_at),
KEY index_contenidos_on_parent_id_and_publicado_and_created_at
(parent_id,publicado,created_at),
KEY index_contenidos_on_fecha_titulares (fecha_titulares),
KEY index_contenidos_on_subtipo_id_and_publicado_and_created_at
(subtipo_id,publicado,created_at),
KEY index_contenidos_on_usuario_publicado_created_at
(usuario_id,publicado,created_at),
KEY index_contenidos_on_usuario_id_and_created_at
(usuario_id,created_at),
CONSTRAINT contenidos_ibfk_1 FOREIGN KEY (parent_id) REFERENCES
contenidos (id),
CONSTRAINT contenidos_ibfk_2 FOREIGN KEY (inicial_id) REFERENCES
contenidos (id),
CONSTRAINT contenidos_ibfk_3 FOREIGN KEY (usuario_id) REFERENCES
usuarios (id),
CONSTRAINT contenidos_ibfk_4 FOREIGN KEY (subtipo_id) REFERENCES
subtipos (id),
CONSTRAINT contenidos_ibfk_5 FOREIGN KEY (ultima_respuesta_id)
REFERENCES contenidos (id),
CONSTRAINT contenidos_ibfk_6 FOREIGN KEY (producto_id) REFERENCES
productos (id)
) ENGINE=InnoDB AUTO_INCREMENT=226129 DEFAULT CHARSET=utf8

s2


#4

Emili Parreño wrote:

Has probado a poner una logintud de indice más larga, 10 por ejemplo??,
de
todas maneras reducir de 20.000 a 500 no esta mal, deberia ejecutarte la
query bastante rapido.

El 2 de diciembre de 2008 10:22, Fernando C. <
removed_email_address@domain.invalid> escribió:

¿La longitud de la clave se puede modificar? Creía que Mysql le ponía la
que necesita para abarcar estos campos (en este caso, un entero y una
fecha).

De todos modos, con 491 filas claro que va bien, el tema es que ayer me
daba 13958 filas…


#5

Has probado a poner una logintud de indice más larga, 10 por ejemplo??,
de
todas maneras reducir de 20.000 a 500 no esta mal, deberia ejecutarte la
query bastante rapido.

El 2 de diciembre de 2008 10:22, Fernando C. <
removed_email_address@domain.invalid> escribió:


#6

Emili Parreño wrote:

Puedes especificar la longitud del indice por ejemplo así

def self.up
execute “CREATE INDEX users_full_name ON users (name(10),
surname(10))”
end

El 2 de diciembre de 2008 14:03, Fernando C. <
removed_email_address@domain.invalid> escribió:

En los campos de texto sí, pero ¿en los int y datetime? ¿No los coge
enteros?

s2 y gracias!!


#7

Puedes especificar la longitud del indice por ejemplo así

def self.up
execute “CREATE INDEX users_full_name ON users (name(10),
surname(10))”
end

El 2 de diciembre de 2008 14:03, Fernando C. <
removed_email_address@domain.invalid> escribió:


#8

El indice lo crea por defecto con una longitud igual al tamaño máximo
del
campo en cuestión, si es un varchar le pone una longitud de 255
carácteres,
a no ser que tú lo hayas limitado. En tu caso tienes un datetime (12
bytes)
y un entero (4 bytes), es este caso deberia crear un indice de longitud
16,
cosa que por lo que dices no hace, fuerzalo y ponle longitud 16 a ver
que
pasa.

El 2 de diciembre de 2008 17:13, Fernando C. <
removed_email_address@domain.invalid> escribió:


#9

Yo creo que está bien… y el explain no se está quejando… no?

Hay una movida con los índices y los order by DESC/ASC que por defecto
se crean con un órden y si los invocas con el otro es como si el
índice no existiera.

Te suena que ayer lanzases la query con un order by diferente al de hoy?

f.