【问题标题】:How to fix slow distinct query如何修复缓慢的不同查询
【发布时间】:2019-07-01 16:56:10
【问题描述】:

使用 Rails 和 Postgres。

我有 3 张桌子(我们称它们为“制造商”、“直升机”和“船”)。 制造商模型与 has_many 关联到 Helicopter(通过“manufacturer_helicopters”表和模型)以及与 has_many 关联到 Boats(通过“manufacturer_boats”表和模型)。

在显示页面上,我应该呈现连接到 Helicopter(具有“helicopter_ids”之一)或连接到 Boat(具有“boat_ids”之一)的唯一制造商。

此外,“直升机”关联具有更高的优先级,因此我们应该只过滤那些具有给定直升机 ID 的“直升机”或根本没有“直升机”的制造商。

这是我提出的查询,但它真的很慢 - 查询需要几秒钟(每个表有近 100 万条记录)

result = Manufacturer.distinct(:id)
                     .left_outer_joins(:manufacturer_helicopters, :manufacturer_boats)
                     .where('helicopter_id IN (?) OR boat_id IN (?)', helicopter_ids, boat_ids)
result.where('manufacturer_helicopters.helicopter_id = ? OR manufacturer_helicopters.helicopter_id IS NULL', helicopter_id)

我非常感谢任何关于如何提高性能的建议。

编辑 这里解释一下

 Unique  (cost=104750.30..115799.60 rows=184155 width=384)
   ->  Sort  (cost=104750.30..105210.69 rows=184155 width=384)
         Sort Key: manufacturer.id, manufacturer.full_name, manufacturer.serial_number, manufacturer.contact_email, manufacturer.pending, manufacturer.created_at, manufacturer.updated_at, manufacturer.in_production, manufacturer.in_planning, manufacturer.web_url, manufacturer.mobile_url, manufacturer.country, manufacturer.city, manufacturer.zip_code, manufacturer.logo, manufacturer.street, manufacturer.address, manufacturer.last_manufactured_at, manufacturer.archived, manufacturer.external_manufacturer_id, manufacturer.external_serial_number, manufacturer.distributor_id, manufacturer.visible
         ->  Merge Left Join  (cost=1.35..24441.43 rows=184155 width=384)
               Merge Cond: (manufacturer.id = manufacturer_helicopter.helicopter_id)
               Filter: ((manufacturer_helicopter.helicopter_id = 4) OR (manufacturer_boat.boat_id = 1))
               ->  Merge Left Join  (cost=1.06..19442.76 rows=260211 width=388)
                     Merge Cond: (manufacturer.id = manufacturer_boat.boat_id)
                     ->  Index Scan using manufacturer_pkey on manufacturers  (cost=0.42..11437.12 rows=260211 width=384)
                     ->  Index Scan using manufacturer_on_boat_id_boat on manufacturer_boat  (cost=0.42..5352.52 rows=160207 width=8)
               ->  Index Scan using index_manufacturer_helicopter_on_helicopter_id on manufacturer_helicopter  (cost=0.29..3343.37 rows=100005 width=8)

【问题讨论】:

  • 我将首先在您的查询上运行 explain 以查看瓶颈在哪里。右 btree 索引可能会解决您的问题

标签: sql ruby-on-rails postgresql


【解决方案1】:

manufacturer.id 是否已编入索引?你的manufacturer_pk是什么?

【讨论】:

  • 是的,manufacturer.id 已编入索引。这是默认的主键。
  • 你有一个巨大的排序键,你的排序成本是最昂贵的一步。有什么方法可以消除其中一些排序字段?对索引字段进行排序比未索引字段更快。此外,IS NULL 过滤器可能会降低您的速度 - 我已经看到完全绕过索引。
  • 我怎样才能消除它?
  • 如果你的意思是删除列,那么不,不能这样做。
  • 不删除实际的列,只是将它们从排序语句中删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多