Sql 6gb表的昂贵查询

Sql 6gb表的昂贵查询,sql,postgresql,heroku,rdms,Sql,Postgresql,Heroku,Rdms,我有很多桌子,比如Foo和Buzz: Foos buzz_id date Foo在外键buzz_id上有一个索引。它还有一个日期索引 Buzzes name group Buzz有一个关于名称的索引、一个关于组的索引,以及一个结合名称和组的多列唯一索引。嗡嗡声有很多食物 我正在进行以下查询,时间太长了: SELECT DISTINCT ON (foos.buzz_id) foos.id, foos.date, buzzes.name, buzzes.group FROM foos INNER

我有很多桌子,比如Foo和Buzz:

Foos
buzz_id
date
Foo在外键buzz_id上有一个索引。它还有一个日期索引

Buzzes
name
group
Buzz有一个关于名称的索引、一个关于组的索引,以及一个结合名称和组的多列唯一索引。嗡嗡声有很多食物

我正在进行以下查询,时间太长了:

SELECT DISTINCT ON (foos.buzz_id) foos.id, foos.date, buzzes.name, buzzes.group FROM foos INNER JOIN buzzes ON buzzes.id = foos.buzz_id 
WHERE (buzzes.group = ANY (ARRAY_OF_GROUPS) 
AND buzzes.name = ANY (ARRAY_OF_NAMES)
AND foos.date <= GIVEN_DATE) ORDER BY foos.buzz_id DESC, foos.date DESC;
我的本地表缺少数据,因此查询返回的行数少于Heroku环境

我在\u名称的数组\u中有大量项,在本例中为500项,而在\u组的数组\u中的项相对较少,比如说4项

我的Heroku环境没有足够的RAM来保存缓存中的所有数据,因此我知道目前查询的速度比缓存时慢

使用EXPLAIN ANALYSE运行查询将提供以下输出:

Local:
 Unique  (cost=330087.91..336514.17 rows=1485 width=46) (actual time=3602.511..4131.322 rows=736 loops=1)
   ->  Sort  (cost=330087.91..333301.04 rows=1285252 width=46) (actual time=3602.509..4003.598 rows=1404653 loops=1)
         Sort Key: foos.buzz_id DESC, foos.date DESC
         Sort Method: external merge  Disk: 96096kB
         ->  Hash Join  (cost=311.50..160136.33 rows=1285252 width=46) (actual time=10.815..1438.885 rows=1404653 loops=1)
               Hash Cond: (foos.buzz_id = buzz.id)
               ->  Seq Scan on foos  (cost=0.00..131923.55 rows=4013004 width=32) (actual time=1.728..925.871 rows=4186572 loops=1)
                     Filter: (date <= GIVEN_DATE)
               ->  Hash  (cost=301.48..301.48 rows=801 width=18) (actual time=9.035..9.035 rows=736 loops=1)
                     Buckets: 1024  Batches: 1  Memory Usage: 47kB
                     ->  Index Scan using index_buzzes_on_name on buzzes  (cost=0.28..301.48 rows=801 width=18) (actual time=0.057..8.189 rows=736 loops=1)
                           Index Cond: ((name)::text = ANY (ARRAY_OF_NAMES::text[]))
                           Filter: ((group)::text = ANY (ARRAY_OF_GROUPS::text[]))
                           Rows Removed by Filter: 5
 Planning time: 5.804 ms
 Execution time: 4151.021 ms
(16 rows)
本地:
唯一(成本=330087.91..336514.17行=1485宽度=46)(实际时间=3602.511..4131.322行=736圈=1)
->排序(成本=330087.91..333301.04行=1285252宽度=46)(实际时间=3602.509..4003.598行=1404653循环=1)
排序键:foos.buzz\u id DESC,foos.date DESC
排序方法:外部合并磁盘:96096kB
->散列联接(成本=311.50..160136.33行=1285252宽度=46)(实际时间=10.815..1438.885行=1404653循环=1)
哈希条件:(foos.buzz\u id=buzz.id)
->foos上的顺序扫描(成本=0.00..131923.55行=4013004宽度=32)(实际时间=1.728..925.871行=4186572循环=1)
过滤器:(日期散列(成本=301.48..301.48行=801宽度=18)(实际时间=9.035..9.035行=736循环=1)
存储桶:1024批:1内存使用率:47kB
->在蜂鸣器上使用索引蜂鸣器进行索引扫描(成本=0.28..301.48行=801宽度=18)(实际时间=0.057..8.189行=736圈=1)
索引条件:((名称)::text=ANY(名称数组::text[]))
筛选器:((组)::text=ANY(组的数组:text[]))
被筛选器删除的行:5
计划时间:5.804毫秒
执行时间:4151.021毫秒
(16行)
希罗库:

Unique  (cost=1086348.46..1086579.42 rows=17073 width=44) (actual time=64428.256..64980.542 rows=1467 loops=1)
   ->  Sort  (cost=1086348.46..1086463.94 rows=230962 width=44) (actual time=64428.254..64801.540 rows=1889788 loops=1)
         Sort Key: foos.buzz_id DESC, foos.date DESC
         Sort Method: external merge  Disk: 129240kB
         ->  Gather  (cost=3860.54..1082233.34 rows=230962 width=44) (actual time=20.290..61998.689 rows=1889788 loops=1)
               Workers Planned: 1
               Workers Launched: 1
               ->  Hash Join  (cost=2860.54..1058137.14 rows=135860 width=44) (actual time=16.240..61607.831 rows=944894 loops=2)
                     Hash Cond: (foos.buzz_id = buzz.id)
                     ->  Parallel Seq Scan on foos  (cost=0.00..953099.09 rows=28986598 width=32) (actual time=0.312..59310.999 rows=24527783 loops=2)
                           Filter: (date <= GIVEN_DATE)
                     ->  Hash  (cost=2855.15..2855.15 rows=1539 width=16) (actual time=9.022..9.022 rows=1467 loops=2)
                           Buckets: 2048  Batches: 1  Memory Usage: 90kB
                           ->  Bitmap Heap Scan on buzzes  (cost=973.85..2855.15 rows=1539 width=16) (actual time=6.534..8.753 rows=1467 loops=2)
                                 Recheck Cond: (((group)::text = ANY (ARRAY_OF_GROUPS::text[])) AND ((name)::text = ANY (ARRAY_OF_NAMES::text[])))
                                 Heap Blocks: exact=902
                                 ->  BitmapAnd  (cost=973.85..973.85 rows=1539 width=0) (actual time=6.416..6.416 rows=0 loops=2)
                                       ->  Bitmap Index Scan on index_buzzes_on_group  (cost=0.00..87.51 rows=10174 width=0) (actual time=1.059..1.059 rows=10504 loops=2)
                                             Index Cond: ((group)::text = ANY (ARRAY_OF_GROUPS::text[]))
                                       ->  Bitmap Index Scan on index_buzzes_on_name  (cost=0.00..886.14 rows=49668 width=0) (actual time=5.168..5.168 rows=50042 loops=2)
                                             Index Cond: ((name)::text = ANY (ARRAY_OF_NAMES::text[]))
 Planning time: 1.993 ms
 Execution time: 64999.534 ms
Unique(成本=1086348.46..1086579.42行=17073宽度=44)(实际时间=64428.256..64980.542行=1467圈=1)
->排序(成本=1086348.46..1086463.94行=230962宽度=44)(实际时间=64428.254..64801.540行=1889788循环=1)
排序键:foos.buzz\u id DESC,foos.date DESC
排序方法:外部合并磁盘:129240kB
->聚集(成本=3860.54..1082233.34行=230962宽度=44)(实际时间=20.290..61998.689行=1889788循环=1)
计划人数:1人
劳工处推出:1
->散列联接(成本=2860.54..1058137.14行=135860宽度=44)(实际时间=16.240..61607.831行=944894循环=2)
哈希条件:(foos.buzz\u id=buzz.id)
->foos上的并行顺序扫描(成本=0.00..953099.09行=28986598宽度=32)(实际时间=0.312..59310.999行=24527783循环=2)
过滤器:(日期散列(成本=2855.15..2855.15行=1539宽度=16)(实际时间=9.022..9.022行=1467循环=2)
存储桶:2048批:1内存使用率:90kB
->蜂鸣器上的位图堆扫描(成本=973.85..2855.15行=1539宽度=16)(实际时间=6.534..8.753行=1467循环=2)
重新检查条件:((组)::text=ANY(组的数组::text[])和((名称)::text=ANY(组的数组::text[]))
堆块:精确=902
->BitmapAnd(成本=973.85..973.85行=1539宽度=0)(实际时间=6.416..6.416行=0循环=2)
->索引组上的位图索引扫描蜂鸣器(成本=0.00..87.51行=10174宽度=0)(实际时间=1.059..1.059行=10504循环=2)
索引条件:((组)::text=ANY(组的数组::text[]))
->索引上的位图索引扫描在名称上蜂鸣器(成本=0.00..886.14行=49668宽度=0)(实际时间=5.168..5.168行=50042循环=2)
索引条件:((名称)::text=ANY(名称数组::text[]))
计划时间:1.993毫秒
执行时间:64999.534毫秒

您对加快我的查询速度有什么建议吗?或者这是预期的行为吗?我想我一定是做错了什么,因为我真诚地怀疑我是否将postgres推向了it性能的边缘。

如果您只需要从
foo
获取最长日期,那么聚合查询将更合适。它可能会随着时间的推移变得更快ll,值得一看:

select
  b.id,
  b.name,
  b."group",
  max(f.date)
  from buzz b,
       foo f
 where b.id = f.buzz_id
   and b."group" in [ARRAY]
   and b.name in [ARRAY]
  and f.date < NOW()
 group by b.id;
选择
b、 身份证,
b、 名字,
b、 “集团”,
最大值(截止日期)
来自buzz b,
福福
其中b.id=f.buzz\u id
和[ARRAY]中的b.“group”
和b.数组中的名称
和f.date

关于索引:如果这是在该数据库上运行的唯一查询,则单列索引(名称和组)因为where条件同时使用了这两个条件,所以没有帮助。如果没有其他查询连接或仅基于其中一列进行筛选,则可以删除这两个索引以加快插入/更新速度。

还可以将where条件移动到内部连接。这样可以尽早减少数据集。理想情况下,您可能希望这样做这样可以尽快减少数据量(并且一定要远离交叉连接):

选择b.id、b.name、b.“组”,最大值(f.date)
from(选择*from buzz bz,其中[ARRAY]中的bz.“group”和[ARRAY]中的bz.name)b,
在b.id=f.buzz\u id上加入(选择*FROM foo WHERE date
re:Susan的答案:移动where条件不会加快速度。Postgres散列连接到foo,然后扫描日期列。我的查询的解释计划与可读性较差/简洁的答案相同。我的j表示法
select
  b.id,
  b.name,
  b."group",
  max(f.date)
  from buzz b,
       foo f
 where b.id = f.buzz_id
   and b."group" in [ARRAY]
   and b.name in [ARRAY]
  and f.date < NOW()
 group by b.id;
 select b.id, b.name, b."group", max(f.date)
 from (SELECT * FROM buzz bz WHERE bz."group" in [ARRAY] and bz.name in [ARRAY]) b,
   JOIN (SELECT * FROM foo WHERE date < NOW()) f ON b.id = f.buzz_id
 group by b.id;