Эффективный выбор и отличительные черты в большой ассоциации - PullRequest
0 голосов
/ 22 октября 2018

У меня есть три модели: Catalog, Product и Value.Таблица Value имеет столбец characteristic_id, и я хотел бы получить список различных characteristic_id для набора values.

Отношения:

  • a catalog имеет много products
  • a product имеет много values

Вот запрос, который я придумал:

Value.joins(:product).select(:characteristic_id).distinct.where(products: {catalog_id: catalog.id}).pluck(:characteristic_id)
=> [441, 2582, 3133]

, который возвращает правильный результат, но он очень медленный в большом каталоге с миллионом товаров (около 50 секунд).Я не могу найти более эффективный способ сделать это.

Вот EXPLAIN запроса:

=> EXPLAIN for: SELECT DISTINCT "values"."characteristic_id" FROM "values" INNER JOIN "products" ON "products"."id" = "values"."product_id" WHERE "products"."catalog_id" = $1 [["catalog_id", 1767]]
                                                      QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
 HashAggregate  (cost=1515106.82..1515109.15 rows=233 width=4)
   Group Key: "values".characteristic_id
   ->  Hash Join  (cost=124703.76..1492245.65 rows=9144469 width=4)
         Hash Cond: ("values".product_id = products.id)
         ->  Seq Scan on "values"  (cost=0.00..1002863.07 rows=34695107 width=8)
         ->  Hash  (cost=114002.20..114002.20 rows=652285 width=4)
               ->  Bitmap Heap Scan on products  (cost=12311.64..114002.20 rows=652285 width=4)
                     Recheck Cond: (catalog_id = 1767)
                     ->  Bitmap Index Scan on index_products_on_catalog_id  (cost=0.00..12148.57 rows=652285 width=0)
                           Index Cond: (catalog_id = 1767)
(10 rows)

Есть идеи, как выполнить этот запрос быстрее?

Ответы [ 2 ]

0 голосов
/ 31 октября 2018
  1. Попробуйте добавить индекс для values.characteristic_id.
  2. Часто GROUP BY может быть быстрее, чем DISTINCT:

    Value.joins (: product).where (products: {catalog_id: catalog.id}). выберите (: характеристический_ид) .группа (: характеристический_ид) .pluck (: характеристический_ид)

0 голосов
/ 25 октября 2018

Убедитесь, что у вас есть индексы для обоих внешних ключей:

  • index "values"."product_id"
  • index "products"."catalog_id"
...