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' }