Ruby Forum Rails-ES > query-reviewer y optimización con índ ices en tablas

Posted by Jaime Iniesta (Guest)
on 05.08.2008 20:07
(Received via mailing list)
¿Habéis probado el plugin query-reviewer? [1]

Lo he estado usando para encontrar cuellos de botella en mis
aplicaciones, principalmente falta de índices en algunas tablas, y me
ha venido muy bien... pero hay algún warning que no he conseguido
saber cómo solucionar...

En concreto, me avisa de "long key length" en el método show de mi
controlador de plantas en floragavarres.net, donde localizo las
plantas a través de su slug (con sluggable_finder), por ejemplo:

http://floragavarres.net/carthamus-lanatus-l-subsp-lanatus

Puse un índice para la columna "slug" en la tabla "plants" para poder
buscar por ese campo rápidamente... ahora las encuentra rápido pero
dice que la clave es demasiado larga...

Table plants:  Long key length (768)
The key used for the index was rather long, potentially affecting
indices in memory

¿Se os ocurre por dónde mirar para solucionar este warning?

[1] http://code.google.com/p/query-reviewer/

--
Jaime Iniesta
http://jaimeiniesta.com - http://pagerankalert.com - 
http://floragavarres.net
Posted by Silvio Quadri (Guest)
on 05.08.2008 20:23
(Received via mailing list)
El día 5 de agosto de 2008 15:07, Jaime Iniesta
<jaimeiniesta@gmail.com> 
escribió:>
> http://floragavarres.net/carthamus-lanatus-l-subsp-lanatus
>
> Puse un índice para la columna "slug" en la tabla "plants" para poder
> buscar por ese campo rápidamente... ahora las encuentra rápido pero
> dice que la clave es demasiado larga...
>
> Table plants:  Long key length (768)
> The key used for the index was rather long, potentially affecting
> indices in memory

¿Cuál es la base de datos?
¿Podés poner la definición de la tabla (tal como quedó en la base)?
¿Los valores en el campo se repiten mucho?

Silvio
Posted by Fernando Blat (ferblape)
on 05.08.2008 20:25
(Received via mailing list)
Completamente de acuerdo en que ese plugin es una gran ayuda para
encontrar slow querys y demás.

El warning que te reporta se debe a que el índice es sobre un string y
si no le dices nada a Mysql el índice lo aplica sobre la longitud del
campo varchar.

Según tengo entendido, se ve que cuando hay muchísimas filas un índice
tan grande consume mucha memoria, y es recomendable hacer un índice de
parte de la longitud del campo, intentando llegar a un compromiso
entre eficiencia del índice y uso de memoria:

- cuanto más pequeña sea la longitud del índice menos memoria consumirá
- sin embargo cuanto más pequeño menos eficiente es, porque el índice
se aplica a una subcadena y no sobre la cadena entera.

Es muy sencillo:

si tienes un campo string con con valores:

juanitowadus
juanitomenglanito
pepitojuanito
pepitosotanito
pepitomenglanito
pepitopedrito

y tu índice es de 6 caracteres, cuando busques "pepitomenglanito" el
índice te devolverá las 4 entradas que empiecen por "pepito" porque
hará matching rápidamente y el resto de la búsqueda terminará sin
índice.

Lo suyo es encontrar una longitud de caractéres óptima que ayude a
discriminar rápidamente. Quizá con 2 o 3 sea suficiente y ya
discrimina entre las tres primeras letras.

Eso sí, no sé si el add_index de rails de las migraciones permite
indicar longitud del índice :) Supongo que sí.


2008/8/5 Jaime Iniesta <jaimeiniesta@gmail.com>:
Posted by Emili Parreño (Guest)
on 06.08.2008 00:23
(Received via mailing list)
En la documentación sobre migraciones [1] no lo especifica, y en la del
método add_index tampoco. En MySQL se hace así:
ALTER TABLE plantas ADD INDEX ( slug(4) )

Otra cosa a tener en cuenta es si el índice debe ser único o no, en el 
caso
de slugs o permalinks sí deberá serlo. En tablas InnoDB un índice único 
es
prácticamente lo mismo que una clave primaria, así que las búsquedas son 
muy
rápidas. Se puede añadir un índice único en una migración así:

add_index(:plantas,:slug, :unique => true)
Tienes otra opción que yo he aplicado a veces, utilizar el slug solo 
para
decorar la url, pero buscando por id, por ejemplo con urls del tipo

http://floragavarres.net/34/centaurea-cyanus-l

o

http://floragavarres.net/centaurea-cyanus-l/34

y mapear una ruta p.e.

map.ver_panta "/:id/:slug", :controller => "plantas", :action => "show"

así la url queda bonita pero las búsquedas son por id ya que puedes 
hacer un
Planta.find(params[:id])



[1] http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

El 5 de agosto de 2008 20:25, Fernando Blat<ferblape@gmail.com>escribió:
Posted by Jaime Iniesta (Guest)
on 06.08.2008 09:43
(Received via mailing list)
El día 5 de agosto de 2008 20:25, Fernando Blat <ferblape@gmail.com> 
escribió:> Completamente de acuerdo en que ese plugin es una gran ayuda para
> encontrar slow querys y demás.

Sip, está guay. Pero como con todos los plugins, ¡cuidado! Ayer me
daban errores en la aplicación que no comprendía, concretamente al
borrar fotos, me dice que nosequé de nil.table... y si quito el
plugin, no falla. Así que mola usarlo, viene muy bien, pero si la app
os hace cosas raras, desconfiad!

> Lo suyo es encontrar una longitud de caractéres óptima que ayude a
> discriminar rápidamente. Quizá con 2 o 3 sea suficiente y ya
> discrimina entre las tres primeras letras.

Genial, he probado con una longitud de 25 caracteres para el índice
del campo slug y query-reviewer ya dice que SQL OK.

Lo que no entiendo es que el index diga que tiene 768 caracteres
cuando se trata de un varchar(255).

> Eso sí, no sé si el add_index de rails de las migraciones permite
> indicar longitud del índice :) Supongo que sí.

Pues me parece que no... hay un parche propuesto [1] pero he probado
con :length y no hace caso.

[1] http://dev.rubyonrails.org/ticket/9254

Gracias!
Posted by Jaime Iniesta (Guest)
on 06.08.2008 09:45
(Received via mailing list)
El día 6 de agosto de 2008 0:19, Emili Parreño <emili@abecedata.com> 
escribió:> En la documentación sobre migraciones [1] no lo especifica, y en la del
> método add_index tampoco. En MySQL se hace así:
> ALTER TABLE plantas ADD INDEX ( slug(4) )

Es una pena que no lo hayan incluido en la sintaxis de las migraciones 
todavía.

> Otra cosa a tener en cuenta es si el índice debe ser único o no, en el caso
> de slugs o permalinks sí deberá serlo. En tablas InnoDB un índice único es
> prácticamente lo mismo que una clave primaria, así que las búsquedas son muy
> rápidas. Se puede añadir un índice único en una migración así:
> add_index(:plantas,:slug, :unique => true)

Sip.

> Tienes otra opción que yo he aplicado a veces, utilizar el slug solo para
> decorar la url, pero buscando por id, por ejemplo con urls del tipo
> http://floragavarres.net/34/centaurea-cyanus-l
> o
> http://floragavarres.net/centaurea-cyanus-l/34
> y mapear una ruta p.e.
> map.ver_panta "/:id/:slug", :controller => "plantas", :action => "show"
> así la url queda bonita pero las búsquedas son por id ya que puedes hacer un
> Planta.find(params[:id])

Buena idea también, aunque es una pena que no queden tan bonitas las
URLs... Mejor las dejo como las tengo.
Posted by Francesc Esplugas (fesplugas)
on 07.08.2008 18:53
(Received via mailing list)
Para mirar las slow queries no creis que es mejor activar las slow
queries de MySQL?
Posted by Fernando Blat (ferblape)
on 10.08.2008 22:24
(Received via mailing list)
Hombre,

una cosa no quita a la otra: en producción está claro que es mejor
tenerlo activado para estar continuamente atendiendo a posibles
problemas, pero en desarrollo el query reviewer te ahorra el tener que
ir a buscar el log y luego pensar a qué petición correspondía tal
query.

Vamos, que es muy cómodo. Pero claro, en producción no se puede
utilizar bajo ningún concepto.

2008/8/7 Francesc Esplugas <francesc.esplugas@gmail.com>:
Posted by Fernando Guillen (Guest)
on 11.08.2008 16:17
(Received via mailing list)
El día 6 de agosto de 2008 9:45, Jaime Iniesta
<jaimeiniesta@gmail.com> 
escribió:> El día 6 de agosto de 2008 0:19, Emili Parreño <emili@abecedata.com> escribió:
>> En la documentación sobre migraciones [1] no lo especifica, y en la del
>> método add_index tampoco. En MySQL se hace así:
>> ALTER TABLE plantas ADD INDEX ( slug(4) )
>
> Es una pena que no lo hayan incluido en la sintaxis de las migraciones todavía.

El parche a mí me ha funcionado perfectamente.. si bien lo que he
hecho es 'abrir' el código y modificarlo directamente en mi 
aplicaciónasí no toco el código original de la gema:

http://www.fernandoguillen.info/es/blog/2008/08/11/ruby-on-rails-definir-el-tamano-de-un-indice-mysql-en-las-migraciones/

>
>> Otra cosa a tener en cuenta es si el índice debe ser único o no, en el caso
>> de slugs o permalinks sí deberá serlo. En tablas InnoDB un índice único es
>> prácticamente lo mismo que una clave primaria, así que las búsquedas son muy
>> rápidas. Se puede añadir un índice único en una migración así:
>> add_index(:plantas,:slug, :unique => true)
>
> Sip.

Cuidado si se está limitando el tamaño de este índice pues si le has
puesto un tamaño 10, por ejemplo, marcará que tendrá que ser único
usando sólo los 10 primeros caracteres.

Saludos
f.