是否使用 :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,而不是常规的整数列。
我还想知道是否有一种简单的方法来决定最后一个索引行中列的顺序。
没有。没有简单的方法。这取决于应用程序中的访问路径。