sql - 我如何优化这个 JOIN 查询?

标签 sql postgresql query-performance

来自 pg_stat_statements 我的这个查询平均需要 900 毫秒。优化此查询的推荐方法是什么?我确实有索引,但不确定瓶颈在哪里。这是 EXPLAIN ANALYZE

EXPLAIN ANALYZE 
SELECT "listing_variants".* 
FROM "listing_variants" 
  INNER JOIN "links" ON "links"."listing_variant_id" = "listing_variants"."id" 
  INNER JOIN "product_variants" ON "product_variants"."id" = "links"."product_variant_id" 
  INNER JOIN "listings" ON "listing_variants"."listing_id" = "listings"."id" 
WHERE "listings"."sales_channel_id" = 31 
  AND "listing_variants"."is_linked" = 'f' 
  AND (listing_variants.available_quantity != product_variants.available_quantity);

给予

    QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=5283.71..6960.01 rows=524 width=232) (actual time=54.138..54.138 rows=0 loops=1)
   Join Filter: (listing_variants.available_quantity <> product_variants.available_quantity)
   ->  Hash Join  (cost=5283.42..6648.69 rows=720 width=236) (actual time=54.137..54.137 rows=0 loops=1)
         Hash Cond: (links.listing_variant_id = listing_variants.id)
         ->  Index Only Scan using index_on_product_listing_variant_id on links  (cost=0.29..1205.14 rows=30643 width=8) (actual time=0.026..6.112 rows=30863 loops=1)
               Heap Fetches: 6799
         ->  Hash  (cost=5261.53..5261.53 rows=1728 width=232) (actual time=45.407..45.407 rows=368 loops=1)
               Buckets: 1024  Batches: 1  Memory Usage: 65kB
               ->  Hash Join  (cost=1671.82..5261.53 rows=1728 width=232) (actual time=11.147..45.075 rows=368 loops=1)
                     Hash Cond: (listing_variants.listing_id = listings.id)
                     ->  Seq Scan on listing_variants  (cost=0.00..3412.77 rows=42577 width=232) (actual time=0.018..29.882 rows=42713 loops=1)
                           Filter: (NOT is_linked)
                           Rows Removed by Filter: 30863
                     ->  Hash  (cost=1661.68..1661.68 rows=811 width=4) (actual time=10.585..10.585 rows=811 loops=1)
                           Buckets: 1024  Batches: 1  Memory Usage: 29kB
                           ->  Bitmap Heap Scan on listings  (cost=30.57..1661.68 rows=811 width=4) (actual time=0.362..10.224 rows=811 loops=1)
                                 Recheck Cond: (sales_channel_id = 31)
                                 Heap Blocks: exact=668
                                 ->  Bitmap Index Scan on index_listings_on_sales_channel_ext_svc_updated  (cost=0.00..30.37 rows=811 width=0) (actual time=0.242..0.242 rows=821 loops=1)
                                       Index Cond: (sales_channel_id = 31)
   ->  Index Scan using product_variants_pkey on product_variants  (cost=0.29..0.42 rows=1 width=12) (never executed)
         Index Cond: (id = links.product_variant_id)
 Planning time: 1.437 ms
 Execution time: 54.366 ms

谢谢!

最佳答案

仅当您需要从多个表中选择数据时才使用 JOIN Over Exists,而您在这里没有这样做。这是优化的第一步。在您的情况下,通过连接,它会根据连接的辅助表中可用的多个数据返回大量相同的数据行,从而污染您的结果集。

SELECT "listing_variants".* 
FROM "listing_variants" 
  WHERE "listing_variants"."is_linked" = 'f' 
    AND EXISTS(SELECT 1 FROM "links" ON "links"."listing_variant_id" = "listing_variants"."id" 
   JOIN "product_variants" ON "product_variants"."id" = "links"."product_variant_id" 
    AND "listing_variants"."available_quantity" != "product_variants"."available_quantity"
   JOIN "listings" ON "listing_variants"."listing_id" = "listings"."id"
    AND "listings"."sales_channel_id" = 31);

除此之外,您的查询非常简单,良好的索引和数据分区只会有助于进一步优化。

关于sql - 我如何优化这个 JOIN 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51214875/

相关文章:

sql - 查询包含oracle db中多个字段的年份

postgresql - 无法创建数据库 - OperationalError : source database "template1" is being accessed by other users

postgresql - Keycloak 无法连接到 Postgres : "SSL connection is required"

database - 如何让Greenplum 4.2.3只扫描指定分区?

sql-server - 为什么这个 CTE 比使用临时表慢这么多?

sql - 根据最大列值对唯一行进行分组

sql - 读取SQL死锁图

mysql - Ruby on Rails : JQuery autocomplete on heroku server (SQL, PostgreSql 可能错误)

sql-server - 使用 View 提高查询性能

sql - 动态月份和年份枢轴,排序不良