web-dev-qa-db-fra.com

Quand ajouter quels index dans une table dans Rails

J'ai une question sur la base de données Rails.

  • Dois-je ajouter "index" à toutes les clés étrangères comme "xxx_id"?
  • Dois-je ajouter "index" à la colonne "id" créée automatiquement?
  • Dois-je ajouter "index (unique)" à la colonne "id" créée automatiquement?

  • Si j'ajoute l'index à deux clés étrangères à la fois (add_index (:users, [:category, :state_id]), que se passe-t-il? En quoi est-ce différent de l'ajout de l'index pour chaque clé?

    class CreateUsers < ActiveRecord::Migration
      def self.up
        create_table :users do |t|
          t.string :name
          t.integer :category_id 
          t.integer :state_id
          t.string :email
          t.boolean :activated
          t.timestamps
        end
      # Do I need this? Is it meaningless to add the index to the primary key?
      # If so, do I need :unique => true ?
      add_index :users, :id 
      # I don't think I need ":unique => true here", right?
      add_index :users, :category_id # Should I need this?
      add_index :users, :state_id # Should I need this?
      # Are the above the same as the following?
      add_index (:users, [:category, :state_id])
      end
    end
    

Excellente réponse jusqu'à présent. Question supplémentaire.

  • Je devrais ajouter "index avec unique" pour xxx_id, non?
129
TK.

Dois-je ajouter "index" à toutes les clés étrangères comme "xxx_id"?

Ce serait mieux, car cela accélère la recherche dans le tri dans cette colonne. Et les clés étrangères sont quelque chose de très recherché.

Depuis la version 5 de Rails l'index sera créé automatiquement, pour plus d'informations, voir ici .

Dois-je ajouter "index" à la colonne "id" créée automatiquement?

Non, c'est déjà fait par Rails

Dois-je ajouter "index (unique)" à la colonne "id" créée automatiquement?

Non, comme ci-dessus

Si j'ajoute l'index à deux clés étrangères à la fois (add_index (:users, [:category_id, :state_id]), que se passe-t-il? En quoi est-ce différent de l'ajout de l'index pour chaque clé?

L'index est alors un index combiné des deux colonnes. Cela n'a aucun sens, sauf si vous voulez toutes les entrées pour un category_id [~ # ~] et [~ # ~] un state_id (CA devrait etre category_id pas category) en même temps.

Un index comme celui-ci accélérerait la demande suivante:

# Rails 2
User.find(:all, :conditions => { :state_id => some_id, :category_id => some_other_id })

# Rails 3
User.where(:state_id => some_id, :category_id => some_other_id)

add_index :users, :category_id
add_index :users, :state_id

accélérera ces demandes:

# Rails 2+3
User.find_by_category_id(some_id)
User.find_by_state_id(some_other_id)

# or
# Rails 2
User.find(:all, :conditions => {:category_id => some_id})
User.find(:all, :conditions => {:state_id => some_other_id})

# Rails 3
User.where(:category_id => some_id)
User.where(:state_id => some_other_id)

Je devrais ajouter "index avec unique" pour xxx_id, non?

Non, car si vous faites cela, un seul utilisateur peut être dans une catégorie, mais le sens de la catégorie est que vous pouvez mettre plus plusieurs utilisateurs en un Catégorie. Dans votre modèle User, vous avez quelque chose comme ça belongs_to :category et dans votre modèle de catégorie quelque chose comme has_many :users. Si tu as un has_many relation la foreign_key le champ ne doit pas être unique!

Pour des informations plus détaillées à ce sujet, vous devriez jeter un œil à tadman 's great answer .

173
jigfox

L'indexation peut être une chose délicate et subtile, mais il existe des règles générales qui peuvent faciliter la détermination de l'utilisation.

La première chose à retenir est que les index peuvent fonctionner de plusieurs manières. Un index sur A, B, C fonctionne également pour A, B et simplement A, vous pouvez donc concevoir vos index pour qu'ils soient plus polyvalents si vous les commandez correctement. L'annuaire est indexé sur Nom, Prénom, de sorte que vous pouvez rechercher facilement des personnes par leur nom de famille ou une combinaison de nom et prénom. Vous ne pouvez cependant pas les rechercher directement par leur prénom. Vous auriez besoin d'un index distinct pour cela. Il en va de même pour le numéro de téléphone, que vous devrez également indexer.

Dans cet esprit, il existe de nombreuses choses qui dicteront la façon dont vous créez des index:

  • Si tu as un belongs_to-has_many appariement des relations, vous devez avoir un index sur la clé étrangère utilisée.
  • Si vous commandez vos enregistrements et qu'il y en a un grand nombre qui seront paginés, vous devez ajouter cette colonne d'ordre à la fin de l'index.
  • Si tu as un has_many :through, votre table de jointure doit avoir un index unique sur les deux propriétés impliquées dans la jointure en tant que clé composée.
  • Si vous récupérez un enregistrement directement en utilisant un identifiant unique tel qu'un nom d'utilisateur ou un e-mail, cela devrait être un index unique.
  • Si vous récupérez des ensembles d'enregistrements à partir d'un has_many relation utilisant une étendue, assurez-vous qu'il existe un index qui inclut le has_many clé étrangère et la colonne d'étendue dans cet ordre.

Le but des index est d'éliminer les redoutables "analyses de table" ou "tri de fichiers" qui se produisent lorsque vos données ne sont pas indexées correctement.

En termes simples, examinez les requêtes générées par votre application et assurez-vous que les colonnes référencées dans les conditions WHERE ou HAVING et ORDER BY les clauses sont représentées dans cet ordre.

110
tadman
  • Toujours indexer les clés étrangères
  • Toujours indexer les colonnes par lesquelles vous commanderez
  • Tous les champs uniques (pour garantir l'unicité au niveau de la base de données. Exemple de migration: add_index :users, :email, unique: true)
  • Si vous commandez par deux choses, ou recherchez par deux choses, par exemple: order by [a, b] Ou find where( a and b ), alors vous avez besoin d'un double index:

Exemple concret:

Si tu as:

default_scope :order => 'photos.created_at DESC, photos.version DESC'

Vous devez ajouter:

add_index :photos, [:created_at, :version]

Remarque: Un index prend de l'espace supplémentaire sur le disque et ralentit la création et la mise à jour de chaque enregistrement, car il doit reconstruire chaque index.

Crédit:

https://tomafro.net/2009/08/using-indexes-in-Rails-choosing-additional-indexes , Rails - created_at lors de la commande de l'utilisateur, si vous ajoutez un index au tableau? , et les réponses ci-dessus.

10
Will Taylor