PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So erstellen Sie einen Index für LOWER (users.username) in Rails (mit postgres)

Ja, diese Validierung würde diese Art von Abfrage durchführen, und diese Art von Abfrage wird einen Tabellenscan durchführen.

Sie haben hier tatsächlich ein paar Probleme:

  • Die Validierung unterliegt Race Conditions, da die Logik nicht in der Datenbank ist, wo sie hingehört. Die Datenbank sollte unabhängig von der üblichen Rails-Ideologie für alle Fragen der Datenintegrität verantwortlich sein.
  • Ihre Validierung löst Tabellenscans aus und niemand mag Tabellenscans.

Sie können diese beiden Probleme mit einem Index lösen. Das erste Problem wird gelöst, indem ein eindeutiger Index innerhalb der Datenbank verwendet wird. Das zweite Problem wird gelöst, indem das Ergebnis von lower(username) indiziert wird statt username .

AFAIK Rails versteht immer noch keine Indizes für Ausdrücke, also müssen Sie zwei Dinge tun:

  1. Wechseln Sie von schema.rb zu structure.sql damit Rails Ihren Index nicht vergisst. In Ihrer config/application.rb Sie möchten Folgendes festlegen:

    config.active_record.schema_format = :sql
    

    Sie müssen auch damit beginnen, db:structure:* zu verwenden Rechenaufgaben anstelle von db:schema:* Aufgaben. Sobald Sie zu structure.sql gewechselt sind , können Sie db/schema.rb löschen da es nicht mehr aktualisiert oder verwendet wird; Sie sollten auch mit dem Tracking von db/structure.sql beginnen in der Revisionskontrolle.

  2. Erstellen Sie den Index von Hand, indem Sie in einer Migration ein wenig SQL schreiben. Das ist ganz einfach:

    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
    

Natürlich werden Sie dadurch mit PostgreSQL-spezifischen Dingen zurückbleiben, aber das ist kein Grund zur Sorge, da ActiveRecord Ihnen sowieso keine nützliche Portabilität bietet.