sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo crear un índice en LOWER (users.username) en Rails (usando postgres)

Sí, esa validación haría ese tipo de consulta y ese tipo de consulta hará un escaneo de tabla.

De hecho, tienes un par de problemas aquí:

  • La validación está sujeta a condiciones de carrera porque la lógica no está en la base de datos a la que pertenece. La base de datos debe ser responsable de todos los problemas de integridad de datos, independientemente de la ideología habitual de Rails.
  • Su validación desencadena escaneos de tablas y a nadie le gustan los escaneos de tablas.

Puede resolver ambos problemas con un índice. El primer problema se resuelve utilizando un índice único dentro de la base de datos. El segundo problema se resuelve indexando el resultado de lower(username) en lugar de username .

AFAIK Rails todavía no entiende los índices de las expresiones, por lo que tendrá que hacer dos cosas:

  1. Cambiar de schema.rb a structure.sql para evitar que Rails se olvide de su índice. En tu config/application.rb querrás configurar:

    config.active_record.schema_format = :sql
    

    También tendrás que empezar a usar db:structure:* rake tareas en lugar de db:schema:* Tareas. Una vez que haya cambiado a structure.sql , puede eliminar db/schema.rb ya que no se actualizará ni usará más; también querrá comenzar a rastrear db/structure.sql en el control de revisión.

  2. Cree el índice a mano escribiendo un poco de SQL en una migración. Esto es fácil:

    def up
      connection.execute(%q{
        create index idx_users_lower_username on users(lower(username))
      })
    end
    
    def down
      connection.execute(%q{
        drop index idx_users_lower_username
      })
    end
    

Por supuesto, esto lo dejará con cosas específicas de PostgreSQL, pero eso no es motivo de preocupación, ya que ActiveRecord no le brinda ninguna portabilidad útil de todos modos.