Rails生成的带有迁移的模型在执行where时从不使用索引

时间:2019-08-08 04:20:57

标签: sql ruby-on-rails postgresql indexing

我用rails g model project name # with more columns

创建了一个模型

每当我在sql查询上运行解释时,postgres都不会使用索引。为什么会这样?

my_db=# \d projects
                                         Table "public.projects"
   Column    |            Type             | Collation | Nullable |               Default
-------------+-----------------------------+-----------+----------+--------------------------------------
 id          | integer                     |           | not null | nextval('projects_id_seq'::regclass)
 name        | character varying           |           |          |
 active      | boolean                     |           | not null | true
 team_id     | integer                     |           |          |
 created_at  | timestamp without time zone |           | not null |
 updated_at  | timestamp without time zone |           | not null |
 account_id  | integer                     |           |          |
Indexes:
    "projects_pkey" PRIMARY KEY, btree (id)
    "index_projects_on_account_id" btree (account_id)
    "index_projects_on_team_id" btree (team_id)
Foreign-key constraints:
    "fk_rails_b4884d7210" FOREIGN KEY (account_id) REFERENCES accounts(id)
    "fk_rails_ecc227a0c2" FOREIGN KEY (team_id) REFERENCES teams(id)
Referenced by:
    TABLE "products" CONSTRAINT "fk_rails_7327dd6d39" FOREIGN KEY (project_id) REFERENCES projects(id)

当我搜索时,我得到了:

my_db=# explain select name from projects where id = 28;
                       QUERY PLAN
---------------------------------------------------------
 Seq Scan on projects  (cost=0.00..2.60 rows=1 width=32)
   Filter: (id = 28)
(2 rows)

我向ActiveRecord询问索引并得到false

ActiveRecord::Base.connection.index_exists?(:projects, :id)
=> false

projects_pkey就在“索引”下,而Postgres在项目上使用了Seq Scan。我试图将查询搜索更改为大于100000或小于100000的ID。没关系,它始终使用Seq Scan

有人可以解释为什么不使用索引吗?在小型数据集上,这很好。但是,问题来自运行一个连接了许多表的查询,并对每个表运行解释仍然使用Seq Scan,这让我发了问。 (关于查询,它是将大约10个表与几个穿透表连接在一起。数据集并不大,只是很宽)

1 个答案:

答案 0 :(得分:3)

@Rthi评论中的链接提供了一些很好的建议!

简而言之,Postgres也不使用索引是因为:

  1. 不能
  2. 它认为不会更快

1不太可能,但是如果由于某种原因索引不再存在,则可能是这种情况。

2的可能性更大。小型表的顺序扫描速度更快!因此,Postgres统计信息可能是错误的。如果是这样,您需要进行分析(或VACUUM ANALYZE)以使其更新:https://www.postgresql.org/docs/current/sql-analyze.html

如果您在数据较少的开发数据库上运行这些文件,那也将解释其选择!

有关更多信息,您可以运行EXPLAIN(ANALYZE,BUFFERS)。 https://wiki.postgresql.org/wiki/Performance_Analysis_Tools#Web_tools

有几种工具可以使查看和共享这些工具变得更加容易。

免责声明:我正在研究最新列出的pgMustard。