我用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个表与几个穿透表连接在一起。数据集并不大,只是很宽)
答案 0 :(得分:3)
@Rthi评论中的链接提供了一些很好的建议!
简而言之,Postgres也不使用索引是因为:
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。