0

我有一個基於RubyOnRails 4.0的應用程序。我有兩個模型:商店和產品。如果我不正確地使用索引,系統中大約有150萬個產品會使其非常慢。在RubyOnRails中爲內部連接創建表的postgres索引

一些基本信息

  • 商店的has_many產品
  • Store.affiliate_type_id使用其中1 =附屬2 =不附屬
  • 產品有像 「category_connection_id」(整數)和「is_available屬性「(布爾值)

In Feeded產品型號:

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

此查詢需要500ms左右,基本上中斷的網站:

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) 

問:如何創建,將採取內的索引聯接起來考慮,使這個更快?

+0

'EXPLAIN ANALYZE'返回更多有用的細節。 –

+0

謝謝,但我找不到在RubyOnRails中做這件事的好方法。有什麼建議嗎? – Christoffer

+0

在PostgreSQL中,使用'explain analyze'而不是'explain'。 –

回答

1

這取決於PostgreSQL選擇的連接算法。在查詢上使用EXPLAIN來查看PostgreSQL如何處理查詢。

這些都是取決於連接算法的答案:

  1. 嵌套循環連接

    在這裏,您應該對於內在聯繫(下表中創建連接條件的索引在EXPLAIN輸出中)。你可以通過添加出現的WHERE子句在和顯著改善選擇性(即,顯著減少索引掃描期間過濾掉的行數列進一步改善的事情。
    對於外關係,在列的索引出現在WHERE子句中,如果這些條件篩選出表中大部分的行會加快查詢。

  2. 哈希聯接

    這有助於對這些列在兩個表的索引中WHERE子句,其中條件過濾掉表中的大部分行。

  3. 合併連接

    在這裏你需要在合併條件列的索引,讓PostgreSQL的使用索引掃描排序。另外,您可以附加出現在WHERE子句中的列。

如果您的索引得到使用,請始終使用EXPLAIN進行測試。如果不是,則可能是它們不能被使用,或者使用它們會使查詢比順序掃描慢,例如,因爲它們不會過濾出足夠的行。

+0

謝謝勞倫茲,我從來沒有真正使用解釋,所以我沒有考慮它。我將輸出添加到了我的問題中,但說實話,這對我來說並不多,因爲我不知道如何解釋它。你能幫我一下嗎? – Christoffer

+0

您需要生產系統的'EXPLAIN'輸出。在測試系統上,它看起來像一切都很好(內部表中只有453行,外部表使用索引)。 –

+0

我重做了生產系統。請注意,FeededProducts有大約150萬,而商店有大約1.200個項目(過濾器的子公司,大概453)。 FeededProducts的加載是需要時間的。 – Christoffer