Khi nào cần thêm chỉ mục nào vào bảng trong Rails


131

Tôi có một câu hỏi về cơ sở dữ liệu Rails.

  • Tôi có nên thêm "chỉ mục" cho tất cả các khóa ngoại như "xxx_id" không?
  • Tôi có nên thêm "chỉ mục" vào cột "id" được tạo tự động không?
  • Tôi có nên thêm "index (duy nhất)" vào cột "id" được tạo tự động không?

  • Nếu tôi thêm chỉ mục vào hai khóa ngoại cùng một lúc ( add_index (:users, [:category, :state_id])điều gì xảy ra? Điều này khác với việc thêm chỉ mục cho mỗi khóa như thế nào?

    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
    

Câu trả lời tuyệt vời cho đến nay. Câu hỏi bổ sung.

  • Tôi nên thêm "chỉ mục duy nhất" cho xxx_id, phải không?

Câu trả lời:


175

Tôi có nên thêm "chỉ mục" cho tất cả các khóa ngoại như "xxx_id" không?

Nó sẽ tốt hơn, bởi vì nó tăng tốc tìm kiếm trong việc sắp xếp trong cột này. Và khóa ngoại là một cái gì đó được tìm kiếm rất nhiều.

Vì Phiên bản 5 của đường ray, chỉ mục sẽ được tạo tự động, để biết thêm thông tin xem tại đây .

Tôi có nên thêm "chỉ mục" vào cột "id" được tạo tự động không?

Không, điều này đã được thực hiện bởi đường ray

Tôi có nên thêm "index (duy nhất)" vào cột "id" được tạo tự động không?

Không, giống như trên

Nếu tôi thêm chỉ mục vào hai khóa ngoại cùng một lúc ( add_index (:users, [:category_id, :state_id])điều gì xảy ra? Điều này khác với việc thêm chỉ mục cho mỗi khóa như thế nào?

Sau đó, chỉ mục là một chỉ mục kết hợp của hai cột. Điều đó không có ý nghĩa gì, trừ khi bạn muốn tất cả các mục cho một category_id một state_id(Nó phải là category_idkhông category) cùng một lúc.

Một chỉ mục như thế này sẽ tăng tốc yêu cầu sau:

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

Ở đâu

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

sẽ tăng tốc các yêu cầu này:

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

Tôi nên thêm "chỉ mục duy nhất" cho xxx_id, phải không?

Không, bởi vì nếu bạn làm điều này, chỉ một người dùng có thể thuộc một danh mục, nhưng ý nghĩa của danh mục là bạn có thể đưa nhiều người dùng hơn vào một danh mục. Trong Usermô hình của bạn, bạn có một cái gì đó như thế này belongs_to :categoryvà trong mô hình Danh mục của bạn một cái gì đó như thế has_many :users. Nếu bạn có một has_manymối quan hệ, foreign_keylĩnh vực không phải là duy nhất!

Để biết thêm thông tin chi tiết về vấn đề này, bạn nên xem câu trả lời tuyệt vời của tadman .


3
Câu trả lời chính xác. Câu hỏi bổ sung. Tôi nên thêm "chỉ mục duy nhất" cho xxx_id, phải không?
TK.

Câu hỏi, bạn có lập chỉ mục một khóa ngoại nếu trường đó rất hiếm khi được tìm kiếm rõ ràng không?
Noz

@Cyle Tôi không thể trả lời điều này chắc chắn, nó phụ thuộc vào máy của bạn, kích thước của cơ sở dữ liệu và bản chất của truy vấn của bạn. Nếu truy vấn đến từ web, tôi có thể nói CÓ, bởi vì luôn luôn tốt hơn để nhận được phản hồi nhanh, nếu đó là cho công việc nền và bạn cần tiết kiệm dung lượng ổ đĩa, bạn không cần phải đặt nó, nhưng nếu không gian đĩa không phải là một vấn đề tôi sẽ thêm một chỉ mục nào.
jigfox

111

Lập chỉ mục có thể là một điều khó khăn, tinh tế, nhưng có những quy tắc chung áp dụng có thể giúp xác định sử dụng cái nào dễ dàng hơn nhiều.

Điều đầu tiên cần nhớ là các chỉ mục có thể hoạt động theo nhiều cách. Một chỉ mục trên A, B, C cũng hoạt động cho A, B và đơn giản là A, vì vậy bạn có thể thiết kế các chỉ mục của mình linh hoạt hơn nếu bạn đặt chúng chính xác. Danh bạ điện thoại được lập chỉ mục trên Họ, Tên, vì vậy bạn có thể dễ dàng tra cứu mọi người bằng họ của họ hoặc kết hợp giữa họ và tên. Bạn không thể, tuy nhiên, tìm kiếm chúng trực tiếp bằng tên của họ. Bạn sẽ cần một chỉ mục riêng cho điều đó. Điều tương tự cũng xảy ra với số điện thoại mà bạn cũng sẽ phải lập chỉ mục.

Với ý nghĩ đó, có nhiều điều sẽ quyết định cách bạn tạo chỉ mục:

  • Nếu bạn có một cặp belongs_to- has_manymối quan hệ, bạn cần phải có một chỉ mục trên khóa ngoại được sử dụng.
  • Nếu bạn đặt hàng hồ sơ của bạn, và có một số lượng lớn chúng sẽ được phân trang, bạn nên thêm cột thứ tự đó vào cuối chỉ mục.
  • Nếu bạn có has_many :throughmối quan hệ, bảng tham gia của bạn sẽ có một chỉ mục duy nhất trên cả hai thuộc tính liên quan đến phép nối dưới dạng khóa ghép.
  • Nếu bạn lấy bản ghi trực tiếp bằng một mã định danh duy nhất như tên người dùng hoặc email, thì đó phải là một chỉ mục duy nhất.
  • Nếu bạn tìm nạp các bộ bản ghi từ một has_manymối quan hệ bằng cách sử dụng một phạm vi, hãy đảm bảo có một chỉ mục bao gồm has_manykhóa ngoại và cột phạm vi theo thứ tự đó.

Mục tiêu với các chỉ mục là loại bỏ các hoạt động "quét bảng" hoặc "sắp xếp tệp" đáng sợ xảy ra khi dữ liệu của bạn không được lập chỉ mục đúng.

Nói một cách đơn giản, hãy xem các truy vấn được tạo bởi ứng dụng của bạn và đảm bảo rằng các cột được tham chiếu trong WHEREhoặc các HAVINGđiều kiện và ORDER BYmệnh đề được trình bày theo thứ tự đó.


1
Tôi tò mò tại sao Rails không ngụ ý các chỉ mục nếu bạn luôn muốn sử dụng chúng cho mọi khóa ngoại. Có một tình huống mà nó không phải là một ý tưởng tốt để lập chỉ mục nó?
Chuyến đi

1
@trip Khá dễ dàng để thêm index: truevào định nghĩa cột của bạn cho các trường hợp đơn giản, nhưng đôi khi bạn có thể muốn kiểm soát nhiều hơn đối với nó. Có các chỉ mục theo mặc định trên các khóa ngoại không phải là một mặc định khủng khiếp, nhưng nó có thể khiến mọi người ngạc nhiên.
tadman

13
  • Luôn lập chỉ mục khóa ngoại
  • Luôn lập chỉ mục các cột bạn sẽ đặt hàng theo
  • Tất cả các trường duy nhất (để đảm bảo tính duy nhất ở cấp cơ sở dữ liệu. Di chuyển ví dụ add_index :users, :email, unique: true:)
  • Nếu bạn đặt hàng theo hai thứ, hoặc tìm kiếm theo hai thứ, ví dụ: order by [a, b]hoặc find where( a and b ), thì bạn cần một chỉ mục kép:

Ví dụ cụ thể:

Nếu bạn có:

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

Bạn nên thêm:

add_index :photos, [:created_at, :version]

Lưu ý: Một chỉ mục chiếm thêm dung lượng trên đĩa và khiến cho việc tạo và cập nhật từng bản ghi chậm hơn, bởi vì nó phải xây dựng lại từng chỉ mục.

Tín dụng:

https://tomafro.net/2009/08/using-indexes-in-rails-choosing-additional-indexes , đường ray - created_at khi người dùng cho đặt hàng, nên bạn thêm một chỉ số để bàn? và những câu trả lời ở trên

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.