Ruby on rails 如果使用另一列对外键进行索引,是否需要显式地对其进行索引?

Ruby on rails 如果使用另一列对外键进行索引,是否需要显式地对其进行索引?,ruby-on-rails,indexing,Ruby On Rails,Indexing,我正在看这个例子: class CreateArtworkShares < ActiveRecord::Migration[5.2] def change create_table :artwork_shares do |t| t.integer :artwork_id, null: false t.integer :viewer_id, null: false t.timestamps end add_index :artw

我正在看这个例子:

class CreateArtworkShares < ActiveRecord::Migration[5.2]
  def change
    create_table :artwork_shares do |t|
      t.integer :artwork_id, null: false
      t.integer :viewer_id, null: false
      t.timestamps
    end
    add_index :artwork_shares, :artwork_id
    add_index :artwork_shares, :viewer_id
    add_index :artwork_shares, [:artwork_id, :viewer_id], unique: true
  end
end
class CreateArtworkShares
我指的是这个堆栈溢出帖子:

我有点困惑,为什么本例中的解决方案显式地索引:artwork_id。使用:artwork_id和:viewer_id(代码中索引的最后一行)的索引不是已经为:artwork_id创建了索引吗?我还想知道是否有一种简单的方法来决定最后一个索引行中列的顺序。我通读了上面发布的堆栈溢出答案,但是对这些列的顺序的解释太笼统了,我无法理解这个概念

索引是否使用:artwork_id和:viewer_id(文件的最后一行)进行 代码中的索引)已为:artwork\u id创建索引

不可以。只有在两列上都进行查询时才使用复合索引,这就是关键所在。这是组合的索引

irb(main):001:0> ArtworkShare.where(viewer_id: 1).explain
  ArtworkShare Load (0.8ms)  SELECT "artwork_shares".* FROM "artwork_shares" WHERE "artwork_shares"."viewer_id" = $1  [["viewer_id", 1]]
=> EXPLAIN for: SELECT "artwork_shares".* FROM "artwork_shares" WHERE "artwork_shares"."viewer_id" = $1 [["viewer_id", 1]]
                                           QUERY PLAN
------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on artwork_shares  (cost=4.20..13.67 rows=6 width=40)
   Recheck Cond: (viewer_id = '1'::bigint)
   ->  Bitmap Index Scan on index_artwork_shares_on_viewer_id  (cost=0.00..4.20 rows=6 width=0)
         Index Cond: (viewer_id = '1'::bigint)
(4 rows)

irb(main):002:0> ArtworkShare.where(viewer_id: 1, artwork_id: 1).explain
  ArtworkShare Load (1.7ms)  SELECT "artwork_shares".* FROM "artwork_shares" WHERE "artwork_shares"."viewer_id" = $1 AND "artwork_shares"."artwork_id" = $2  [["viewer_id", 1], ["artwork_id", 1]]
=> EXPLAIN for: SELECT "artwork_shares".* FROM "artwork_shares" WHERE "artwork_shares"."viewer_id" = $1 AND "artwork_shares"."artwork_id" = $2 [["viewer_id", 1], ["artwork_id", 1]]
                                                       QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
 Index Scan using index_artwork_shares_on_artwork_id_and_viewer_id on artwork_shares  (cost=0.15..8.17 rows=1 width=40)
   Index Cond: ((artwork_id = '1'::bigint) AND (viewer_id = '1'::bigint))
(2 rows)
而且移民是很好的。。。很糟糕

class CreateArtworkShares < ActiveRecord::Migration[6.0]
  def change
    create_table :artwork_shares do |t|
      t.belongs_to :artwork, null: false, foreign_key: true
      t.belongs_to :viewer, null: false, foreign_key: true
      t.timestamps
    end

    add_index :artwork_shares, [:artwork_id, :viewer_id], unique: true
  end
end
class CreateArtworkShares
这将在
artwork\u id
viewer\u id
上添加外键约束和索引。它还创建
bigint
而不是常规整数列

我还想知道是否有一种简单的方法来决定最后一个索引行中列的顺序


不,没有简单的方法。这取决于应用程序中的访问路径。

因此,为了决定顺序,post将最快的行缩小到第一行是什么意思?例如,如果一个艺术家不能拥有多个具有相同标题的艺术品,那么正确的顺序是:艺术品标题,然后是艺术家?如果我错了,请纠正我,但是如果我把艺术家放在第一位,那么它就必须浏览艺术家的所有作品。但是如果我把标题放在第一位,它只会抓住艺术家作品的一小部分(重复的标题)。是的,听起来差不多。我甚至认为我并不是真正了解自己。