Rails'te bir tabloya hangi dizinler ne zaman eklenir?


131

Rails veritabanı hakkında bir sorum var.

  • "Xxx_id" gibi tüm yabancı anahtarlara "dizin" eklemeli miyim?
  • Otomatik olarak oluşturulan "id" sütununa "indeks" eklemeli miyim?
  • Otomatik olarak oluşturulan "kimlik" sütununa "dizin (benzersiz)" eklemeli miyim?

  • Aynı anda iki yabancı anahtara dizin eklersem ( add_index (:users, [:category, :state_id])ne olur? Bunun her anahtar için dizini eklemekten farkı nedir?

    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

Şimdiye kadar harika cevap. Ek soru.

  • Xxx_id için "benzersiz dizin" eklemeliyim, değil mi?

Yanıtlar:


175

"Xxx_id" gibi tüm yabancı anahtarlara "dizin" eklemeli miyim?

Daha iyi olur, çünkü bu sütundaki sıralamada aramayı hızlandırır. Ve Yabancı anahtarlar çok aranan bir şeydir.

Rayların Sürüm 5'inden bu yana, dizin otomatik olarak oluşturulacaktır, daha fazla bilgi için buraya bakın .

Otomatik olarak oluşturulan "id" sütununa "indeks" eklemeli miyim?

Hayır, bu zaten raylarla yapılıyor

Otomatik olarak oluşturulan "kimlik" sütununa "dizin (benzersiz)" eklemeli miyim?

Hayır, yukarıdakiyle aynı

Aynı anda iki yabancı anahtara dizin eklersem ( add_index (:users, [:category_id, :state_id])ne olur? Bunun her anahtar için dizini eklemekten farkı nedir?

Daha sonra dizin, iki sütunun birleşik bir dizinidir. Aynı anda bir category_id VE bir için tüm girişleri state_id(olmamalı ) istemediğiniz sürece bu hiç mantıklı category_iddeğil category.

Bunun gibi bir Dizin aşağıdaki isteği hızlandıracaktır:

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

Nerede

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

bu istekleri hızlandıracak:

# 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 için "benzersiz dizin" eklemeliyim, değil mi?

Eğer bunu yaparsanız Hayır, çünkü yalnızca bir kullanıcı bir kategori içinde yer alabilir, ancak kategorinin anlamı daha koyabilirsiniz olmasıdır birçok tek kategoride kullanıcıyı. Senin içinde Usermodelde böyle bir şey var belongs_to :categoryve sevdiği Kategori modeli şey has_many :users. Bir has_manyilişkiniz varsa, foreign_keyalan benzersiz olmamalıdır!

Bununla ilgili daha ayrıntılı bilgi için tadman'ın harika cevabına bir göz atmalısınız .


3
Mükemmel cevap. Ek soru. Xxx_id için "benzersiz dizin" eklemeliyim, değil mi?
TK.

Soru, bu alan çok nadiren açıkça aranıyorsa bir yabancı anahtarı dizine ekler miydiniz?
Noz

@Cyle Buna kesinlikle cevap veremem, makinenize, veritabanının boyutuna ve sorgunuzun niteliğine bağlı. Sorgu web'den geliyorsa muhtemelen EVET derim, çünkü hızlı yanıt almak her zaman daha iyidir, eğer bir arka plan işi içinse ve disk alanından tasarruf etmeniz gerekiyorsa, ayarlamanız gerekmez, ancak disk alanı varsa bir sorun değil yine de bir dizin ekleyeceğim.
jigfox

111

İndeksleme zor ve incelikli bir şey olabilir, ancak hangisinin kullanılacağını çok daha kolay belirleyebilecek geçerli genel kurallar vardır.

Unutulmaması gereken ilk şey, dizinlerin birden fazla şekilde çalışabileceğidir. A, B, C üzerindeki bir indeks aynı zamanda A, B ve basitçe A için de işe yarar, böylece indekslerinizi doğru sıralarsanız daha çok yönlü olacak şekilde tasarlayabilirsiniz. Telefon rehberi Soyadı, Adına göre dizine eklenmiştir, böylece insanları soyadlarına veya soyad ve ad kombinasyonuna göre kolayca arayabilirsiniz. Bununla birlikte, onlara doğrudan adlarıyla bakamazsınız. Bunun için ayrı bir dizine ihtiyacınız olacak. Aynı şey, dizine eklemeniz gereken telefon numarası için de geçerlidir.

Bunu akılda tutarak, indeksleri nasıl oluşturacağınızı belirleyecek birçok şey var:

  • Bir belongs_to- has_manyilişki eşleştirmeniz varsa, kullanılan yabancı anahtarda bir dizine sahip olmanız gerekir.
  • Kayıtlarınızı sıralarsanız ve çok sayıda sayfalandırılacaksa, bu sıra sütununu dizinin sonuna eklemelisiniz.
  • Bir has_many :throughilişkiniz varsa, birleştirme tablonuzun birleşik anahtar olarak birleştirmeye dahil olan her iki özellik için benzersiz bir dizini olmalıdır.
  • Bir kaydı, kullanıcı adı veya e-posta gibi benzersiz bir tanımlayıcı kullanarak doğrudan getirirseniz, bu benzersiz bir dizin olmalıdır.
  • has_manyKapsam kullanarak bir ilişkiden kayıt kümelerini getirirseniz , has_manyyabancı anahtarı ve kapsam sütununu bu sırada içeren bir dizin bulunduğundan emin olun .

Dizinlerle amaç, verileriniz düzgün bir şekilde dizine eklenmediğinde ortaya çıkan korkunç "tablo taraması" veya "dosya sıralama" işlemlerini ortadan kaldırmaktır.

Basit bir ifadeyle, uygulamanız tarafından oluşturulan sorgulara bakın ve içinde başvurulan sütunların WHEREveya HAVINGkoşulların ve ORDER BYcümlelerin bu sırayla temsil edildiğinden emin olun.


1
Her yabancı anahtar için her zaman kullanmak istiyorsanız, Rails'in neden indeksler anlamına gelmediğini merak ediyorum. Dizine eklemenin iyi bir fikir olmadığı bir durum var mı?
gezi

1
@trip index: trueBasit durumlar için sütun tanımınıza eklemek oldukça kolaydır , ancak bazen onun üzerinde daha fazla kontrol isteyebilirsiniz. Yabancı anahtarlarda varsayılan olarak dizinlere sahip olmak korkunç bir varsayılan değildir, ancak insanları şaşırtabilir.
tadman

13
  • Yabancı anahtarları her zaman endeksle
  • Sıralayacağınız sütunları her zaman dizine ekleyin
  • Tüm benzersiz alanlar (bir veritabanı seviyesinde benzersizliği sağlamak için Örnek göç:. add_index :users, :email, unique: true)
  • İki şeye göre sipariş verirseniz veya iki şeye göre arama yaparsanız, örneğin: order by [a, b]veya find where( a and b ), çift dizine ihtiyacınız vardır:

Somut örnek:

Eğer varsa:

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

Eklemelisiniz:

add_index :photos, [:created_at, :version]

Not: Bir dizin, diskte fazladan yer kaplar ve her bir dizini yeniden oluşturması gerektiğinden, her kaydın oluşturulmasını ve güncellenmesini yavaşlatır.

Kredi:

https://tomafro.net/2009/08/using-indexes-in-rails-choosing-additional-indexes , raylar - kullanıcı sipariş verirken oluşturulmuş_at, Tabloya bir Dizin eklemeli misiniz? ve yukarıdaki cevaplar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.