Когда добавлять какие индексы в таблицу в Rails - PullRequest
128 голосов
/ 07 сентября 2010

У меня вопрос по базе данных Rails.

  • Должен ли я добавить «index» ко всем внешним ключам, таким как «xxx_id»?
  • Должен ли я добавить «index» в автоматически созданный столбец «id»?
  • Должен ли я добавить "индекс (уникальный)" в автоматически созданный столбец "id"?

  • Если я добавлю индекс к двум внешним ключам одновременно (add_index (:users, [:category, :state_id]), что произойдет? Чем это отличается от добавления индекса для каждого ключа?

    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
    

Отличный ответ. Дополнительный вопрос

  • Я должен добавить «индекс с уникальным» для xxx_id, верно?

Ответы [ 3 ]

171 голосов
/ 07 сентября 2010

Должен ли я добавить «index» ко всем внешним ключам, таким как «xxx_id»?

Было бы лучше, потому что это ускоряет поиск при сортировке в этом столбце. И внешние ключи - это то, что ищут много.

Начиная с версии 5 рельсов, индекс будет создан автоматически, для получения дополнительной информации см. здесь .

Должен ли я добавить «index» в автоматически созданный столбец «id»?

Нет, это уже сделано рельсами

Должен ли я добавить «index (unique)» в автоматически созданный столбец «id»?

Нет, как и выше

Если я добавлю индекс к двум внешним ключам одновременно (add_index (:users, [:category_id, :state_id]), что произойдет? Чем это отличается от добавления индекса для каждого ключа?

Тогда индекс представляет собой объединенный индекс двух столбцов. Это не имеет никакого смысла, если только вы не хотите, чтобы все записи для одного category_id И одного state_id (это должно быть category_id не category) одновременно.

Такой индекс ускорит выполнение следующего запроса:

# 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

ускорит эти запросы:

# 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)

Я должен добавить «индекс с уникальным» для xxx_id, верно?

Нет, потому что если вы сделаете это, только один пользователь может быть в одной категории, но значение категории состоит в том, что вы можете поместить больше много пользователей в одну категорию. В вашей модели User у вас есть что-то вроде belongs_to :category, а в модели вашей категории что-то вроде has_many :users. Если у вас есть отношение has_many, поле foreign_key не должно быть уникальным!

Для получения более подробной информации об этом вы должны взглянуть на tadman 's great answer .

109 голосов
/ 07 сентября 2010

Индексирование может быть хитрым, тонким делом, но есть общие правила, которые могут сделать определение, которое использовать намного проще.

Первое, что нужно помнить, это то, что индексы могут работать более чем в одномпуть.Индекс на A, B, C также работает для A, B и просто для A, поэтому вы можете сделать свои индексы более универсальными, если вы упорядочите их правильно.Телефонная книга индексируется по фамилии, имени, поэтому вы можете легко искать людей по их фамилии или по комбинации фамилии и имени.Однако вы не можете искать их по имени.Вам понадобится отдельный индекс для этого.То же самое относится и к номеру телефона, который вы также должны индексировать.

Имея это в виду, есть много вещей, которые будут определять порядок создания индексов:

  • Если выиметь пару отношений belongs_to - has_many, вам нужно иметь индекс для используемого внешнего ключа.
  • Если вы заказываете свои записи, и существует большое количество их, которые будут разбиты на страницы, выследует добавить этот столбец порядка в конец индекса.
  • Если у вас есть отношение has_many :through, ваша таблица соединения должна иметь уникальный индекс для обоих свойств, участвующих в объединении в качестве составного ключа.
  • Если вы выбираете запись напрямую, используя уникальный идентификатор, такой как имя пользователя или адрес электронной почты, это должен быть уникальный индекс.
  • Если вы выбираете наборы записей из отношения has_many, используя область действия, убедитесь, чтоесть индекс, который включает внешний ключ has_many и столбец области в указанном порядке.

Целью индексов является устранение страшного «сканирования таблицы» или «сортировки файлов» oЭто происходит, когда ваши данные не проиндексированы должным образом.

Проще говоря, посмотрите на запросы, сгенерированные вашим приложением, и убедитесь, что столбцы, на которые ссылаются условия WHERE или HAVING и условия ORDER BY,представлены в таком порядке.

10 голосов
/ 07 мая 2015
  • Всегда индексировать внешние ключи
  • Всегда индексировать столбцы, которые вы будете упорядочивать по
  • Все уникальные поля (для обеспечения уникальности на уровне базы данных. Пример миграции: add_index :users, :email, unique: true)
  • Если вы заказываете по двум вещам или выполняете поиск по двум вещам, например: order by [a, b] или find where( a and b ), то вам нужен двойной индекс:

Конкретный пример:

Если у вас есть:

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

Вы должны добавить:

add_index :photos, [:created_at, :version]

Примечание. Индекс занимает дополнительное место на диске и замедляет создание и обновление каждой записи., потому что он должен перестраивать каждый индекс.

Кредит:

https://tomafro.net/2009/08/using-indexes-in-rails-choosing-additional-indexes, rails - made_at при заказе для пользователя. Следует ли добавить индекс в таблицу? , а ответы выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...