Індекс на декількох стовпцях у Ruby on Rails


97

Я впроваджую функціональність для відстеження статей, які користувач прочитав.

  create_table "article", :force => true do |t|
    t.string   "title"
    t.text     "content"
  end

Це моя міграція на даний момент:

create_table :user_views do |t|
  t.integer :user_id
  t.integer :article_id
end

Таблиця user_views завжди буде запитуватися на пошук обох стовпців, ніколи лише одного. Моє питання полягає в тому, як повинен виглядати мій індекс. Чи є різниця в порядку цих таблиць, чи має бути ще кілька варіантів до нього чи ще. Моя цільова БД - Postgres.

add_index(:user_views, [:article_id, :user_id])

Дякую.

ОНОВЛЕННЯ:
Оскільки може існувати лише один рядок, що містить однакові значення в обох стовпцях (оскільки, знаючи, чи user_id ЧИТАТИ article_id), чи варто розглядати варіант: unique? Якщо я не помиляюсь, це означає, що мені не потрібно самостійно перевіряти, а просто робити вставку кожного разу, коли користувач відвідує статтю.


"Таблиця user_views завжди буде запитуватися для пошуку обох стовпців, ніколи не лише однієї." - ніколи не буде запиту "знайти всі статті, які переглянув цей користувач", або "знайти всіх користувачів, які переглянули цю статтю"? Я дивуюся.
Девід Олдрідж

Відповіді:


213

Порядок має значення при індексації.

  1. Поставте перше найбільш селективне поле, тобто поле, яке швидше звужує кількість рядків.
  2. Індекс буде використовуватися лише в тому випадку, якщо ви використовуєте його стовпці в послідовності, починаючи з початку . тобто якщо ви індексуєте [:user_id, :article_id], ви можете виконувати швидкий запит на user_idабо user_id AND article_id, але НЕ на article_id.

Ваша add_indexлінія міграції повинна виглядати приблизно так:

add_index :user_views, [:user_id, :article_id]

Питання щодо "унікальної" опції

Найпростіший спосіб зробити це в Rails - це використовувати validatesу вашій моделі з розмальованим uniquenessнаступним чином ( документація ):

validates :user, uniqueness: { scope: :article }

7
Порядок має величезне значення в індексації. Розташуйте пункти де ліворуч та заповніть покажчик стовпцями упорядкування праворуч. stackoverflow.com/questions/6098616/dos-and-donts-for-indexes
Дені де Бернарді

1
Зауважте, що validates_uniqueness_of(та її двоюрідний брат validates uniqueness:) схильні до умов перегонів
Бен Обен

1
Як згадано у коментарях вище та stackoverflow.com/a/1449466/5157706 та stackoverflow.com/a/22816105/5157706 , розгляньте можливість додавання унікального індексу в базу даних.
Акаш Агарвал

25

Просто попередження про перевірку унікальності під час перевірки порівняно з індексом: останнє робиться базою даних, а праймер - моделлю. Оскільки може бути декілька паралельних екземплярів моделі, що працює одночасно, перевірка підлягає гоночним умовам, а це означає, що в деяких випадках вона може не виявити дублікатів (наприклад, подати двічі одну і ту ж форму в той самий час).


То який з них краще? Сторона бази даних або перевіряє унікальність_?
WM

9
І те й інше. validates_uniqueness_of може використовуватися для витонченого відображення повідомлення про помилку в програмі, наприклад, коли форма зберігається. Обмеження бази даних гарантувало б, що ви не отримаєте записи dup, навіть знаючи, що у вас була перевірка, вказана в моделі. Крім того, ви можете врятувати виняток ActiveRecord, а також показати приємне повідомлення користувачеві.
Uģis Ozols

5
@WM Якщо вам потрібно вибрати один, перейдіть із обмеженням бази даних. Це буде працювати навіть у тому випадку, якщо різні додатки, що не належать до RoR, взаємодіють з вашими даними та забезпечують послідовність на тривалий термін.
пришвартовано
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.