【问题标题】:2 similar tables with an indexed category_id - 2 different queries generated by Postgres2 个带有索引 category_id 的相似表 - Postgres 生成的 2 个不同查询
【发布时间】:2018-05-13 21:15:52
【问题描述】:

我正在使用:Rails 3.2.13 和 PostgreSQL 9.4.7

我有 2 个产品表,AProductsBProducts. 两个表都有一个 category_id 整数,它是一个索引列,并且两个表都有几百万条记录。

当我通过category_id查询AProducts时,响应很快并且使用索引,但是当我查询BProducts时响应非常非常慢,并且它使用顺序扫描而不是使用索引。我试图弄清楚为什么BProducts 会发生这种情况,因为表格和模型与AProducts 几乎相同。以下是 EXPLAIN 的结果:

irb(main):2290:0> BProduct.where(:category_id => 700).explain

  BProduct Load (219696.7ms)  SELECT "b_products".* FROM "b_products" WHERE "b_products"."category_id" = 700
  EXPLAIN (1.3ms)  EXPLAIN SELECT "b_products".* FROM "b_products" WHERE "b_products"."category_id" = 700
=> "EXPLAIN for: SELECT \"b_products\".* FROM \"b_products\"  WHERE \"b_products\".\"category_id\" = 700\n                                 QUERY PLAN\n-----------------------------------------------------------------------------\n Seq Scan on b_products  (cost=0.00..1791663.25 rows=926 width=2036)\n   Filter: (category_id = 700)\n(2 rows)\n"

上面的慢查询耗时 219696.7ms,并且不使用索引。下面对 AProduct 的查询很快,并且确实使用了索引。

irb(main):2289:0> AProduct.where(:category_id => 700).explain
  AProduct Load (51.0ms)  SELECT "a_products".* FROM "a_products" WHERE "a_products"."category_id" = 700
  EXPLAIN (1.2ms)  EXPLAIN SELECT "a_products".* FROM "a_products" WHERE "a_products"."category_id" = 700
=> "EXPLAIN for: SELECT \"a_products\".* FROM \"a_products\"  WHERE \"a_products\".\"category_id\" = 700\n                                                           QUERY PLAN\n--------------------------------------------------------------------------------------------------------------------------------\n Index Scan using index_a_products_on_category_id on a_products  (cost=0.56..5448.33 rows=1359 width=883)\n   Index Cond: (category_id = 700)\n(2 rows)\n"

我想弄清楚的是,如何让我的 BProduct 查找使用索引并以与 AProduct 相同的速度获取记录,为什么这不是我看到的默认行为?

【问题讨论】:

  • 您可以运行 psql 并输入 \d a_products\d b_products 并确保索引完全相同
  • 两个表都有一个索引:"index_b_products_on_category_id" btree (category_id)"index_a_products_on_category_id" btree (category_id)
  • 好的,有一些原因,为什么 PG 不在大表上使用索引。您可以尝试使用VACUUM ANALYZE pg SQL 命令,然后再次检查计划。
  • 那你可以试试/*+ IndexScan(b_products) */ SELECT "b_products".* FROM "b_products" ...
  • 如果没有结果,请仅使用postgresql 标签提出此问题,并提供两个表的表结构和行数。准备好提供有关 PG 配置和服务器参数(内存)的信息

标签: ruby-on-rails postgresql ruby-on-rails-3 postgresql-9.4


【解决方案1】:

也许你的表没有真正被索引?

在 Rails 控制台上检查:ActiveRecord::Base.connection.indexes(:table_name)

你也可以直接在postgres上做:SELECT indexname FROM pg_indexes;

【讨论】:

  • 当我运行SELECT indexname FROM pg_indexes; 时,我看到了正确的索引。当我运行ActiveRecord::Base.connection.indexes(:table_name) 时,我的所有表都得到[],包括a_product 和b_product
  • 也许可以尝试从 Rails 迁移中重新创建两个索引
猜你喜欢
  • 2018-09-21
  • 2021-04-30
  • 2021-09-27
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多