我在我的应用程序中遇到了一个有趣的问题,即使用Rails 4和Postgresql的postgresql索引。基本上,我有一个项目表和一个邀请表。
邀请有一个外键project_id和一个外键user_id。
我有一个ID为770的项目,
Invitation.find(761816).project_id # 770
Invitation.find(761816).user_id # 389
但是,基于user_id搜索此项目的查询失败。
Invitation.where(project_id: 770, user_id: 389) #<ActiveRecord::Relation []>
当然,邀请belongs_to用户,belongs_to项目和用户has_many邀请。相同的查询适用于我能找到的任何其他邀请对象。
邀请表上的这些属性已编入索引,这可能是导致此行为的原因:
add_index :invitations, :user_id
add_index :invitations, :project_id
这是我第一次在一个已经运行了一年多的大型数据库中遇到这个问题。
我很感激,如果有人可以就如何发生这种情况给出一些建议,可以采取哪些措施来解决这个问题,或者如果有理由重建它们,可以如何重建postgres索引。
更新
以下是我被要求执行的查询结果:
Invitation.count # 787322
Invitation.first.inspect # "#<Invitation id: 13, ... user_id: 358, ... project_id: 14, status: 5, followup_status: 0 ...>"
Invitation.first.project_id.class.name # Fixnum
Invitation.first.user_id.class.name # Fixnum
Invitation.where(project_id:770).count # 353
Invitation.where(user_id:389).count # 775
Invitation.where(project_id:770,user_id:389).count # 0
和最有趣的部分:
Invitation.where(project_id:770,user_id:389,id:761816).count # 1
更新2
以下是这两个问题查询的解释说明:
Invitation.where(project_id:770,user_id:389)
-------------------------------
Bitmap Heap Scan on invitations (cost=45.18..49.20 rows=1 width=192)
Recheck Cond: ((user_id = 389) AND (project_id = 770))
-> BitmapAnd (cost=45.18..45.18 rows=1 width=0)
-> Bitmap Index Scan on index_invitations_on_user_id (cost=0.00..22.36 rows=792 width=0)
Index Cond: (user_id = 389)
-> Bitmap Index Scan on index_invitations_on_project_id (cost=0.00..22.57 rows=819 width=0)
Index Cond: (project_id = 770)
(7 rows)
和第二个正确的:
Invitation.where(project_id:770,user_id:389,id:761816)
----------------------
Index Scan using invitations_pkey on invitations (cost=0.42..8.45 rows=1 width=192)
Index Cond: (id = 761816)
Filter: ((project_id = 770) AND (user_id = 389))
(3 rows)
答案 0 :(得分:2)
如果它是一个腐败索引的问题,那么很容易诊断 - 删除索引并重试查询。
我假设生成的查询是正确的?
使用Rails看起来不是一种非常自然的方式,顺便说一句。也许:
@user.projects.find_by(:id => 770)
答案 1 :(得分:1)
让我们在这里记录我们的结果。
Callable
Invitation.find 761816 # => #<Invitation id: 761816, ... user_id: 389, ... project_id: 770, status: 6, ....>
Invitation.where(project_id: 770, user_id: 389) # => #<ActiveRecord::Relation []>
给出
Invitation.where(project_id: 770, user_id: 389).explain
和
Bitmap Heap Scan on invitations (cost=45.93..49.94 rows=1 width=193)
Recheck Cond: ((project_id = 770) AND (user_id = 389))
-> BitmapAnd (cost=45.93..45.93 rows=1 width=0)
-> Bitmap Index Scan on index_invitations_on_project_id (cost=0.00..22.72 rows=839 width=0)
Index Cond: (project_id = 770)
-> Bitmap Index Scan on index_invitations_on_user_id (cost=0.00..22.96 rows=871 width=0)
Index Cond: (user_id = 389)
(7 rows)
给出
Invitation.where(id: 761816).explain
您能否为这些查询提供结果?
Index Scan using invitations_pkey on invitations (cost=0.42..8.44 rows=1 width=193)
Index Cond: (id = 761816)
(2 rows)
为了确定,我们可以查看以下内容吗?