Rails Postgresql数据库查询失败

时间:2015-09-02 15:02:45

标签: ruby-on-rails database postgresql activerecord indexing

我在我的应用程序中遇到了一个有趣的问题,即使用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)

2 个答案:

答案 0 :(得分:2)

如果它是一个腐败索引的问题,那么很容易诊断 - 删除索引并重试查询。

我假设生成的查询是正确的?

使用Rails看起来不是一种非常自然的方式,顺便说一句。也许:

@user.projects.find_by(:id => 770)

答案 1 :(得分:1)

让我们在这里记录我们的结果。

第1步。

Callable

步骤2.解释

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

步骤3.不同的查询

您能否为这些查询提供结果?

Index Scan using invitations_pkey on invitations (cost=0.42..8.44 rows=1 width=193)
Index Cond: (id = 761816)
(2 rows)

步骤4.不同的检查

为了确定,我们可以查看以下内容吗?

  1. 比较生产/开发机器的LC_COLLATE设置(低机会,它影响任何事情,但仍然有趣的知道)
  2. 在数据库中运行步骤#3查询。我们至少知道问题与Rails或Postgres有关。
  3. 是否可以在生产数据库中删除(并在以后重新创建)索引?只是为了查看删除索引时查询的行为方式。