Когда добавлять индексы в таблицу в Rails

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

  • Должен ли я добавить "индекс" ко всем внешним ключам типа "xxx_id"?
  • Должен ли я добавить "индекс" в автоматически созданный столбец "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
    

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

  • Я должен добавить "index with unique" для xxx_id, правильно?

Ответ 1

Должен ли я добавить "индекс" ко всем внешним ключам типа "xxx_id"?

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

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

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

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

Нет, так же, как указано выше

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

Затем индекс является комбинированным индексом двух столбцов. Это не имеет никакого смысла, если вам не нужны все записи для одного category_id И один state_id (он должен быть category_id not 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)

Я должен добавить "index with unique" для xxx_id, правильно?

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

  • Всегда индексировать внешние ключи
  • Всегда индексировать столбцы, которые вы заказываете
  • Все уникальные поля (для обеспечения уникальности на уровне базы данных. Пример миграции: 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 - created_at, когда пользователь заказывает, Если вы добавите индекс к таблице? и ответы выше.