Ruby on Rails: definir el tamaño de un Ãndice MySQL en las migraciones
Revisando el log de tus queries te puedes encontrar que si estás buscando registros por un campo VARCHAR te salte un warning de “long key length“.
Esto es porque el Ãndice que has puesto en este campo VARCHAR es muy grande, aunque MySQL soporta Ãndices de hasta 1000 bytes si son muy grandes pueden ralentizar las búsquedas.
La solución está en limitar el tamaño del Ãndice a un número bastante pequeño.
En MySQL esto se indica asÃ:
ALTER TABLE mi_tabla ADD INDEX ( campo_del_indice(4) )
ó también:
CREATEÂ INDEX `nombre_del_indice` ON mi_tabla (`campo_del_indice`(4))
El problema es que si estamos usando ‘migrations‘ de Rails y queremos ser puristas nos encontramos con que la sintaxis estándar de las migraciones de Rails no soporta el campo ‘longitud’.
Como bien dice Jaime Iniesta existe un parche que da soporte a las migraciones para admitir el campo ‘length’.
Yo sin embargo he preferido no tocar el código de mis gemas y meter este fichero (rails_migraions_hack.rb) en el ‘/lib‘ de mi aplicación:
module ActiveRecord module ConnectionAdapters # :nodoc: module SchemaStatements def add_index(table_name, column_name, options = {}) column_names = Array(column_name) index_name = index_name(table_name, :column => column_names) if Hash === options # legacy support, since this param was a string index_type = options[:unique] ? "UNIQUE" : "" index_name = options[:name] || index_name index_length = options[:length] ? "(#{options[:length]})" : nil # only mysql else index_type = options end quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ") # execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})" sql = "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{table_name} (#{quoted_column_names}#{index_length})" p "SQL: #{sql}" execute sql end end end end
Y cargarlo con un:
require 'rails_migrations_hack'
En mi environment.rb.
Funciona perfectamente y vemos como saca por pantalla las querys de las creaciones de Ãndices con cosas como esta:
"SQL: CREATEÂ INDEX `idx_forums_forums_nicetitle` ON forums_forums (`nicetitle`(4))"
Es interesante consultar toda la discusión en la lista de ror-es.
Actualizado (2008-08-13):
Al parecer no estan cubiertas todas las posibilidades.
En el caso de estar creando un Ãndice compuesto el atributo length se lo asigna al último campo y esto puede no ser lo adecuado:
add_index :tabla, [:campo1, :campo2], :name => 'idx_tabla1', :length => '10'
lo que intenta es hacer:
CREATEÂ INDEX `idx_tabla1` ON tabla (`campo1`, `campo2`(10))
Si el campo varchar que queremos limitar es el primero la hemos cagado..
HabrÃa que intentar modificar la sintaxis del length para que coja algo como esto:
add_index :tabla, [:campo1, :campo2], :name => 'idx_tabla1', :length => { :campo1 => '10' }