Rendimiento MySQL

eXtreM3

Situación:

Tengo una tabla con 200.000 registros. La estructura es más o menos así:

  • ID: primary key auto_increment (del 1 al 200.000)
  • nombre
  • total
  • y otros diversos campos

Tenía un index en el cual ejecutaba varias consultas, para traer registros de esa tabla según unas condiciones (rangos de fecha, totales, etc.). Antes lo hacía bien, iba como un tiro.

Se han dado un par de factores que hacen que el rendimiento haya caído drásticamente:

1) Cambio de línea de internet. De 10mb con movistar a 6mb con orange.
2) Cambio de hosting. De uno bueno a uno algo inferior (esto no debería ser razón)
3) La más importante: a nivel de base de datos, y por necesidades urgentes, los IDs de la tabla han pasado de ser secuenciales (del 1 al 200k) a ser así:

El 1 pasa a ser 101.
El 150.000 pasa a ser 10150000

Es decir, se ha añadido un 10 al principio de todos los ids. ¿Es esta la razón de la caída de rendimiento? No quiere decir que haya 10 millones de tuplas, sigue habiendo 200k, el cambio es sólo a nivel de número.

Luz por favor! Gracias.

palotex

Yo creo que el tema está en el punto 2... comprueba la configuración de mysql... memoria consumida, si cacheas en temporales o accedes directamente... y por último intenta optimizar las consultas que igual rascas tiempo ahí.
Por descartar activa el Slow Query Log en la config de mysql para ver si hay consultas lentas que te frenan el rendimiento:

#Donde va el log
log-slow-queries=/var/log/mysql-slow-queries.log

#Tiempo de consulta en Segundos
long_query_time = 5

o si no desde consola tira un "show processlist" y ves el rendimiento de las consultas cuando se estén ejecutando.

También depende del motor que uses puedes mejorar el rendimiento en función de las consultas que realices...

2 respuestas
eXtreM3

#2 gracias. Me dices que la 3) no tiene absolutamente nada que ver? Era la que más me preocupaba :P

1 respuesta
palotex

#3 Si sólo ha cambiado eso y no el número de registros... y si así fuera tienes controlado el auto_increment para que mantenga esa regla, no debería haber problema. Al final la estructura es igual y el índice de la tabla sigue siendo el mismo campo.

2 respuestas
eXtreM3

#4 vale, pues tiene que ser del servidor seguro. Pero hay una cosa que me extraña, y es que antes de hacer el modificado de IDs, iba bien, pero ya no sé si es porque estaba cacheado en el servidor o qué.

En cuanto pueda haré un test con lo que me has dicho en #2 y comento, gracias.

eXtreM3

#4 te cito de nuevo, porque me he dejado una cosa sin poner. Cuando iba bien, el tipo de dato era INT(10) y ahora es BIGINT(20), es posible que sea por esto?

1 respuesta
palotex

#6 no debería, pero necesitas un campo de 20 digitos de longitud?

Josepanaero

Mi especialidad no son las bases de datos, pero que no te quepa la menor duda de que el punto 3 ha influido. No sé exactamente cuánto habrá influido, si mucho o poco (es posible que poco), pero estoy totalmente seguro de que con ese cambio el rendimiento va a ser peor.

Bueno, el punto 3 en sí no, sino el usar BIGINT en vez de INT. Al ser un tipo de dato más grande, los índices van a aumentar su tamaño, lo que va a hacer que usarlos sea más lento.

El hecho de haber cambiado los valores de las claves primarias a la vez que cambiar su tamaño también puede haber tenido un impacto negativo. Lo mismo ahora esta tabla está peor distribuida físicamente en el disco. No sé, es una suposición, como ya te digo, no soy ningún experto, pero quizá podrías intentar usar alguna de las órdenes de MySQL para optimizar la tabla (OPTIMIZE, creo que era).

De todas formas, ¿seguro que necesitas usar un BIGINT en vez de un INT? Date cuenta de que con un UNSIGNED INT puedes llegar a almacenar hasta 4.300 millones de valores distintos. Bueno, en tu caso, ya que añades un 10 al principio de cada número, 100 millones (los dos primeros dígitos siempre van a ser 1 y 0, por lo que el mayor ID en tu caso es 1.099.999.999).

¡Un saludo!

1 respuesta
eXtreM3

#8 volví a cambiar el tipo a INT y el rendimiento volvió a ser el de antes, sin duda ha sido por eso. No sabía que podía afetar tan negativamente al rendimiento usar un tipo de dato erróneo.

No obstante, a largo plazo tendré un "problema", porque sí que necesito almacenar esa cantidad, pero se me ocurrirá alguna manera de optimizarlo cuando llegue el momento.

2 respuestas
RaymaN

#9 el valor máximo de INT (unsigned) es 4294967295. ¿Realmente necesitas almacenar más de cuatro mil millones de registros?

1 respuesta
eXtreM3

#10 no, pero surgió la necesidad de cambiar el índice. Lo que hemos hecho ha sido una burrada, comentado por mi parte, que soy el que se encarga de la base de datos. Pero como digo, no quedaba otra opción.

El índice era secuencial, como digo en #1, pero ha tenido que pasar a ser:

ID (de otro campo de otra tabla) + 0 (un separador único) + antiguo ID

de manera que, por ejemplo, si en la otra tabla tengo un ID 250, y el id de mi tabla va por el 599.999, el nuevo id de esa tupla será: 2500599999

Así que sí, como ves, se me va a quedar corto el máximo valor del INT unsigned.

1 respuesta
RaymaN

#11 es que antes de pensar en el espacio que necesitarás en un futuro debéis arreglar la chapuza que habéis hecho. No hay por donde cogerlo xD

1 respuesta
eXtreM3

#12 si es que no me escucharon :(

La solución buena me lleva unos 7 días de implementación, ya que aparte de cambiar cosillas en la base de datos, hay que cambiar un mogollón de código de la aplicación. Y teníamos que aplicar la solución como máximo tardando 1 día, así que hubo que hacer ese parche sobre la marcha y tirar palante.

Spacelord

#9 Mierda, veo esto tarde. Sí, era por lo del BIGINT, y la explicación es muy sencilla: espacio de memoria. Cuanto más espacio uses para guardar datos más tardarás en encontrar esos datos porque el programa tendrá que buscar en más sitios.

Por si quieres un texto más técnico (junto con un experimento): http://planet.mysql.com/entry/?id=13825

1
7 días después
eXtreM3

Aprovecho el hilo para preguntar otra cosa distinta.

¿Establecer relaciones con claves foráneas aumenta la velocidad de las consultas? O las foráneas solamente sirven para establecer una solidez relacional?

1 respuesta
Dostoievski

#15 con mis comienzos limitados de bbdd, imagino que si no creas un índice no mejará nada. En principio sólo sirve para mantener la integridad relacional, tendrías que crear un índice.

1 respuesta
palotex

MYISAM o INNODB? Si usas la primera las relaciones las haces tu cuando trabajas con la bd en la aplicación, por lo tanto en cuanto a consultas es o debe ser más rápida que INNODB.

INNODB relaciona FK de forma nativa peeeeeeeeeero si no recuerdo mal eso es lo que le penaliza en rendimiento.

conclusión post-edit: Si tu aplicación tira más de SELECT que de INSERT / UPDATE usando myisam te da lo mismo porque las establecerás por la aplicación si no mediante innodb te restará rendimiento.

JuAn4k4

No creo que tenga que ver el BIGINT vs INT, yo tengo tablas con 7kk de registros en mysql con bigint de identificador, consultas mas o menos normalillas con 1 group by, average, etc.. y va como un tiro.

Cómo tienes estos parametros ?

innodb_buffer_pool_size
join_buffer_size
sort_buffer_size
read_rnd_buffer_size

Haz un:
explain select ....... ;

de tu consulta.

#16 Yo diria que se crean solos para las FK

1 respuesta
Dostoievski

#18 Tienes razon, le acabo de echar un vistazo a la docu y me lié con las referencias y las FG. Al añadir la restricción de la FK se crea un índice (que es lo lógico vaya) aunque con una referencia nada más nop, habría que añadirla después.

3 meses después
eXtreM3

Aprovecho este hilo para preguntar algo, a ver si alguien me da una explicación. Tengo dos tablas, t1 con unos 170.000 registros y t2 con unos 250.000, y la siguiente consulta

UPDATE t1,t2 SET t2.newId = t1.newId WHERE t1.oldId = t2.oldId

Todos los campos son INT, y la consulta no termina de ejecutarse. He puesto en el where otra cláusula para que lo haga sólo para los 13.000 primeros, ha tardado unos 50-60 segundos en ejecutarse. Todo esto en local. Por qué tarda tantísimo?

1 respuesta
RaymaN

#20 falta de índices?

1 respuesta
eXtreM3

#21

t1.oldId es PK de t1
t2.oldId es FK a t1.oldId

Usuarios habituales

  • eXtreM3
  • RaymaN
  • Dostoievski
  • JuAn4k4
  • palotex
  • Spacelord
  • Josepanaero