在RubyOnRails中为内部联接创建表的postgres索引

时间:2016-11-14 10:46:01

标签: ruby-on-rails postgresql indexing postgresql-performance

我有一个基于RubyOnRails 4.0的应用程序。我有两种型号:商店和产品。如果我没有正确使用指数,系统中大约有150万种产品会很慢。

一些基本信息

  • 商店has_many产品
  • 使用Store.affiliate_type_id,其中1 =附属2 =非附属
  • 产品具有“category_connection_id”(整数)和“is_available”(布尔值)等属性

在FeededProduct模型中:

scope :affiliated, -> { joins(:store).where("stores.affiliate_type_id = 1") } 

此查询大约需要500毫秒,这基本上会中断网站:

FeededProduct.where(:is_available => true).affiliated.where(:category_connection_id => @feeded_product.category_connection_id)

对应的postgresql:

FeededProduct Load (481.4ms)  SELECT "feeded_products".* FROM "feeded_products" INNER JOIN "stores" ON "stores"."id" = "feeded_products"."store_id" WHERE "feeded_products"."is_available" = 't' AND "feeded_products"."category_connection_id" = 345 AND (stores.affiliate_type_id = 1)

更新。 Postgresql EXPLAIN:

                                           QUERY PLAN
-------------------------------------------------------------------------------------------------
 Hash Join  (cost=477.63..49176.17 rows=21240 width=1084)
   Hash Cond: (feeded_products.store_id = stores.id)
   ->  Bitmap Heap Scan on feeded_products  (cost=377.17..48983.06 rows=38580 width=1084)
         Recheck Cond: (category_connection_id = 5923)
         Filter: is_available
         ->  Bitmap Index Scan on cc_w_store_index_on_fp  (cost=0.00..375.25 rows=38580 width=0)
               Index Cond: ((category_connection_id = 5923) AND (is_available = true))
   ->  Hash  (cost=98.87..98.87 rows=452 width=4)
         ->  Seq Scan on stores  (cost=0.00..98.87 rows=452 width=4)
               Filter: (affiliate_type_id = 1)
(10 rows)

问题:我如何创建一个将内部联接考虑在内并使其更快的索引?

1 个答案:

答案 0 :(得分:1)

这取决于PostgreSQL选择的连接算法。在查询上使用EXPLAIN来查看PostgreSQL如何处理查询。

这些是取决于连接算法的答案:

  1. 嵌套循环连接

    在这里,您应该为内部关系EXPLAIN输出中的底部表)的连接条件创建索引。您可以通过添加WHERE子句中显示的列来进一步改进选项,从而显着提高选择性(即,显着减少索引扫描期间过滤掉的行数。) 对于外部关系,如果这些条件过滤掉表中的大多数行,WHERE子句中显示的列的索引将加速查询。

    < / LI>
  2. 哈希加​​入

    这里有条件在WHERE子句中的那些列上有索引,条件过滤掉表中的大多数行。

  3. 合并加入

    在这里,您需要合并条件中的列的索引,以允许PostgreSQL使用索引扫描进行排序。此外,您还可以附加WHERE子句中显示的列。

  4. 如果您的索引被使用,请始终使用EXPLAIN进行测试。如果不是,则可能是它们不能被使用或者使用它们会使查询比顺序扫描更慢,例如,因为他们没有过滤掉足够的行。