136 votes

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 un 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 ?

179voto

jigfox Points 11788

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

Ce serait mieux, car cela accélère la recherche en triant dans cette colonne. Et les clés étrangères sont quelque chose que l'on recherche beaucoup.

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

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

Non, cela est déjà fait par les rails

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

Non, même chose que ci-dessus

Si j'ajoute un 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'indice est alors un indice combiné des deux colonnes. Cela n'a aucun sens, à moins que vous ne vouliez que toutes les entrées pour une category_id ET un state_id (Il devrait être category_id no category ) en même temps.

Un tel index permettrait d'accélérer 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, parce que si vous faites cela, un seul utilisateur peut être dans une catégorie, mais la signification de la catégorie est que vous pouvez mettre plus de beaucoup de dans une seule catégorie. Dans votre User vous avez quelque chose comme ceci belongs_to :category et dans votre modèle de catégorie quelque chose comme has_many :users . Si vous avez un has_many relation le foreign_key Le champ ne doit pas être unique !

Pour des informations plus détaillées à ce sujet, vous pouvez consulter le site suivant tadman de la grande réponse .

3 votes

Bonne réponse. Question supplémentaire. Je dois ajouter "index avec unique" pour xxx_id, n'est-ce pas ?

0 votes

Question : indexeriez-vous une clé étrangère si ce champ est très rarement recherché de manière explicite ?

0 votes

@Cyle Je ne peux pas répondre définitivement à cette question, cela dépend de votre machine, de la taille de la base de données, et de la nature de votre requête. Si la requête provient du web, je dirais probablement OUI, car il est toujours préférable d'obtenir des réponses rapides. Si c'est pour un travail en arrière-plan et que vous devez économiser de l'espace disque, vous n'avez pas besoin de le définir, mais si l'espace disque n'est pas un problème, j'ajouterais quand même un index.

114voto

tadman Points 70178

L'indexation peut être une chose délicate et subtile, mais il existe des règles générales qui s'appliquent et qui peuvent faciliter le choix de la méthode à utiliser.

La première chose à retenir est que les index peuvent fonctionner de plusieurs façons. 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 ordonnez correctement. L'annuaire téléphonique est indexé sur Nom, Prénom, ce qui vous permet de rechercher facilement des personnes par leur nom de famille ou une combinaison de leur nom et de leur prénom. En revanche, vous ne pouvez pas les rechercher directement par leur prénom. Il vous faut un index séparé pour cela. Il en va de même pour le numéro de téléphone, qui doit également être indexé.

En gardant cela à l'esprit, il y a beaucoup de choses qui vont dicter la façon dont vous créez les index :

  • Si vous avez un belongs_to - has_many vous devez disposer d'un index sur la clé étrangère utilisée.
  • Si vous ordonnez vos documents, 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 vous avez 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é composite.
  • Si vous récupérez un enregistrement directement en utilisant un identifiant unique tel que le nom d'utilisateur ou l'adresse électronique, il devrait s'agir d'un index unique.
  • Si vous récupérez des ensembles d'enregistrements à partir d'un fichier has_many à l'aide d'une portée, assurez-vous qu'il y a un index qui inclut la relation has_many la clé étrangère et la colonne scope dans cet ordre.

L'objectif des index est d'éliminer les redoutables opérations de "balayage de table" ou de "tri de fichier" 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 le champ WHERE o HAVING conditions et ORDER BY sont représentées dans cet ordre.

1 votes

Je suis curieux de savoir pourquoi Rails n'implique pas les index si vous voulez toujours les utiliser pour chaque clé étrangère. Y a-t-il une situation où ce n'est pas une bonne idée de l'indexer ?

1 votes

@trip C'est assez facile à ajouter. index: true à votre définition de colonne pour les cas simples, mais parfois vous voudrez avoir plus de contrôle sur celle-ci. Avoir des index par défaut sur les clés étrangères n'est pas un défaut terrible à avoir, mais cela pourrait prendre les gens par surprise.

14voto

Will Taylor Points 1588
  • Toujours indexer les clés étrangères
  • Indexez toujours les colonnes que vous allez classer par
  • 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] o find where( a and b ) alors vous avez besoin d'un double index :

Exemple concret :

Si vous avez :

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

Vous devriez ajouter :

add_index :photos, [:created_at, :version]

Note : Un index occupe de l'espace supplémentaire sur le disque et rend la création et la mise à jour de chaque enregistrement plus lente, car il faut reconstruire chaque index.

Crédit :

https://tomafro.net/2009/08/using-indexes-in-rails-choosing-additional-indexes , rails - created_at quand l'utilisateur pour la commande, Faut-il ajouter un index à la table ? et les réponses ci-dessus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X