首页 > 解决方案 > 如果我用另一列索引外键,是否需要显式索引它?

问题描述

我正在经历这个例子:

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

我指的是这个 Stack Overflow 帖子:Index on multiple columns in Ruby on Rails

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

标签: ruby-on-railsindexing

解决方案


使用 :artwork_id 和 :viewer_id (代码中索引的最后一行)的索引是否已经为 :artwork_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

artwork_id这会在和上添加外键约束和索引viewer_id。它还创建bigint而不是常规整数列。

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

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


推荐阅读