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

标签 sql ruby-on-rails postgresql indexing

我用 rails g model project name # with more columns 创建了一个模型

每当我在 sql 查询上运行 explain 时,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 就在 Indexes 下,而 Postgres 正在对项目使用 Seq Scan。我试图更改查询搜索大于 100000 或小于 100000 的 ID。没关系,它始终使用 Seq Scan

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

最佳答案

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

简而言之,Postgres 也没有使用索引,因为:

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

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

2 的可能性更大。小表的顺序扫描更快!因此,Postgres 的统计数据可能是错误的。如果是这样,您需要进行 ANALYZE(或 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。

关于sql - Rails 生成的迁移模型在执行 where 时从不使用索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57405158/

相关文章:

ruby-on-rails - 如何将 xml 文件加入/合并到一个文件中并返回它?

postgresql - GORM 不会创建 Many2many 关联

postgresql - 按自定义命名行排序

sql - 如果序列未被破坏,则从多行获取总时间间隔

INSERT INTO 语句中的 Java SQL 语法错误

mysql - 如何删除MySQL中的记录并保持最新日期

ruby-on-rails - ActionController::UrlGenerationError,没有路由匹配

mysql - MySQL 中何时使用单引号、双引号和反引号

ruby-on-rails - 如何在 Rails 中的条件语句中访问保存的对象

python - 在 Python 中使用 psycopg2 将 PostgreSQL hstore 作为 OrderedDict 返回