Kapan menambahkan indeks apa dalam tabel di Rails

131

Saya punya pertanyaan tentang database Rails.

  • Haruskah saya menambahkan "indeks" ke semua kunci asing seperti "xxx_id"?
  • Haruskah saya menambahkan "indeks" ke kolom "id" yang dibuat secara otomatis?
  • Haruskah saya menambahkan "indeks (unik)" ke kolom "id" yang dibuat secara otomatis?

  • Jika saya menambahkan indeks ke dua kunci asing sekaligus ( add_index (:users, [:category, :state_id]), apa yang terjadi? Apa bedanya dengan menambahkan indeks untuk setiap kunci?

    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
    

Jawaban yang bagus sejauh ini. Pertanyaan tambahan.

  • Saya harus menambahkan "indeks dengan unik" untuk xxx_id, kan?
TK.
sumber

Jawaban:

175

Haruskah saya menambahkan "indeks" ke semua kunci asing seperti "xxx_id"?

Akan lebih baik, karena mempercepat pencarian dalam menyortir di kolom ini. Dan kunci Asing adalah sesuatu yang banyak dicari.

Karena Versi 5 dari rel indeks akan dibuat secara otomatis, untuk informasi lebih lanjut lihat di sini .

Haruskah saya menambahkan "indeks" ke kolom "id" yang dibuat secara otomatis?

Tidak, ini sudah dilakukan dengan rel

Haruskah saya menambahkan "indeks (unik)" ke kolom "id" yang dibuat secara otomatis?

Tidak, sama seperti di atas

Jika saya menambahkan indeks ke dua kunci asing sekaligus ( add_index (:users, [:category_id, :state_id]), apa yang terjadi? Apa bedanya dengan menambahkan indeks untuk setiap kunci?

Kemudian indeks adalah indeks gabungan dari dua kolom. Itu tidak masuk akal, kecuali jika Anda ingin semua entri untuk satu category_id DAN satu state_id(Seharusnya category_idtidak category) pada saat yang sama.

Indeks seperti ini akan mempercepat permintaan berikut:

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

Dimana

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

akan mempercepat permintaan ini:

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

Saya harus menambahkan "indeks dengan unik" untuk xxx_id, kan?

Tidak, karena jika Anda melakukan ini, hanya satu pengguna yang dapat berada dalam satu kategori, tetapi arti dari kategori ini adalah Anda dapat menempatkan lebih banyak pengguna dalam satu kategori. Dalam Usermodel Anda, Anda memiliki sesuatu seperti ini belongs_to :categorydan dalam kategori Anda, sesuatu seperti has_many :users. Jika Anda memiliki has_manyhubungan, foreign_keybidangnya tidak boleh unik!

Untuk informasi lebih rinci tentang ini, Anda harus melihat jawaban yang bagus dari tadman .

jigfox
sumber
3
Jawaban yang bagus Pertanyaan tambahan. Saya harus menambahkan "indeks dengan unik" untuk xxx_id, kan?
TK.
Pertanyaan, apakah Anda akan mengindeks kunci asing jika bidang itu sangat jarang dicari secara eksplisit?
Noz
@Cyle Saya tidak bisa menjawab ini pasti, itu tergantung pada mesin Anda, ukuran database, dan sifat permintaan Anda. Jika kueri berasal dari web, saya mungkin akan mengatakan YA, karena selalu lebih baik untuk mendapatkan respons cepat, jika itu untuk pekerjaan latar belakang dan Anda perlu menghemat ruang disk Anda tidak perlu mengaturnya, tetapi jika ruang disk bukan masalah saya akan tetap menambahkan indeks.
jigfox
111

Pengindeksan bisa menjadi hal yang rumit dan sulit, tetapi ada aturan umum yang berlaku yang dapat membuat menentukan mana yang akan digunakan lebih mudah.

Hal pertama yang harus diingat adalah bahwa indeks dapat bekerja dalam lebih dari satu cara. Indeks pada A, B, C juga berfungsi untuk A, B dan hanya A, sehingga Anda dapat merancang indeks Anda menjadi lebih fleksibel jika Anda memesannya dengan benar. Buku telepon diindeks pada Nama Belakang, Nama Depan, sehingga Anda dapat mencari orang dengan mudah dengan nama belakang mereka, atau kombinasi dari nama belakang dan nama depan. Namun, Anda tidak dapat mencarinya langsung dengan nama depan. Anda perlu indeks terpisah untuk itu. Hal yang sama berlaku untuk nomor telepon, yang harus Anda indeks juga.

Dengan mengingat hal itu, ada banyak hal yang akan menentukan bagaimana Anda membuat indeks:

  • Jika Anda memiliki belongs_to- has_manyhubungan pasangan, Anda harus memiliki indeks pada kunci asing yang digunakan.
  • Jika Anda memesan catatan Anda, dan ada sejumlah besar dari mereka yang akan dibuat paginasi, Anda harus menambahkan kolom pesanan itu ke akhir indeks.
  • Jika Anda memiliki has_many :throughhubungan, tabel gabungan Anda harus memiliki indeks unik pada kedua properti yang terlibat dalam gabungan sebagai kunci gabungan.
  • Jika Anda mengambil catatan secara langsung menggunakan pengidentifikasi unik seperti nama pengguna atau email, itu harus menjadi indeks unik.
  • Jika Anda mengambil kumpulan rekaman dari suatu has_manyhubungan menggunakan cakupan, pastikan ada indeks yang menyertakan has_manykunci asing dan kolom lingkup dalam urutan itu.

Tujuan dengan indeks adalah untuk mengeliminasi operasi "pemindaian tabel" atau "pengurutan file" yang terjadi ketika data Anda tidak diindeks dengan benar.

Dalam istilah sederhana, lihat kueri yang dihasilkan oleh aplikasi Anda dan pastikan bahwa kolom yang dirujuk dalam WHEREatau HAVINGkondisi dan ORDER BYklausa disajikan dalam urutan itu.

anak laki-laki
sumber
1
Saya ingin tahu mengapa Rails tidak menyiratkan indeks jika Anda selalu ingin menggunakannya untuk setiap kunci asing. Apakah ada situasi di mana itu bukan ide yang baik untuk mengindeksnya?
Perjalanan
1
@trip Cukup mudah untuk menambahkan index: truedefinisi kolom Anda untuk kasus-kasus sederhana, tetapi kadang-kadang Anda mungkin ingin lebih banyak kontrol atasnya. Memiliki indeks secara default pada kunci asing bukanlah standar yang buruk untuk dimiliki, tetapi mungkin mengejutkan banyak orang.
tadman
13
  • Selalu mengindeks kunci asing
  • Selalu indeks kolom yang akan Anda pesan
  • Semua bidang yang unik (untuk memastikan keunikan pada tingkat database Contoh migrasi:. add_index :users, :email, unique: true)
  • Jika Anda memesan dengan dua hal, atau mencari dengan dua hal, misalnya: order by [a, b]atau find where( a and b ), maka Anda memerlukan indeks ganda:

Contoh nyata:

Jika Anda memiliki:

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

Anda harus menambahkan:

add_index :photos, [:created_at, :version]

Catatan: Indeks membutuhkan ruang ekstra pada disk dan membuatnya lebih lambat untuk membuat dan memperbarui setiap catatan, karena harus membangun kembali setiap indeks.

Kredit:

https://tomafro.net/2009/08/using-indexes-in-rails-choosing-additional-indexes , rails - Created_at saat pengguna memesan, Haruskah Anda menambahkan Indeks ke tabel? , dan jawaban di atas.

Will Taylor
sumber