使用日期时间查询防止大规模顺序扫描
Prevent massive sequential scan with datetime query
如何按日期过滤查询以防止对大型数据库进行大量顺序扫描?
我的调查应用程序收集 response
s,调查中每个问题的答案都存储在 table response_answer
中。
当我查询所有 response_answers 月份时,我按日期过滤;但是 postgres 运行对所有 response_answers(数以百万计)进行顺序扫描,而且速度很慢。
查询:
explain analyse
select count(*)
from response_answer
left join response r on r.id = response_answer.response_id
where r.date_recorded between '2019-08-01T00:00:00.000Z' and '2019-08-29T23:59:59.999Z';
QUERY PLAN
Aggregate (cost=517661.09..517661.10 rows=1 width=8) (actual time=139362.882..139362.899 rows=1 loops=1)
-> Hash Join (cost=8063.39..517565.30 rows=38316 width=0) (actual time=126512.031..136806.093 rows=316558 loops=1)
Hash Cond: (response_answer.response_id = r.id)
-> Seq Scan on response_answer (cost=0.00..480365.73 rows=7667473 width=4) (actual time=1.443..70216.817 rows=7667473 loops=1)
-> Hash (cost=8053.35..8053.35 rows=803 width=4) (actual time=173.467..173.476 rows=7010 loops=1)
Buckets: 8192 (originally 1024) Batches: 1 (originally 1) Memory Usage: 311kB
-> Seq Scan on response r (cost=0.00..8053.35 rows=803 width=4) (actual time=0.489..107.417 rows=7010 loops=1)
Filter: ((date_recorded >= '2019-08-01'::date) AND (observed_at <= '2019-08-29'::date))
Rows Removed by Filter: 153682
Planning time: 21.310 ms
Execution time: 139373.365 ms
我在 response_answer(response_id)、response_answer(id) 和 response(id) 上有索引。
随着系统的增长,此查询将变得非常慢以致于无法使用,因为顺序扫描将继续花费更长的时间。
在处理大量数据时,我应该如何设计queries/tables,这样数据库就不必运行顺序扫描每一个。单身的。排。在找到所有相关 response_answers?
之前,Postgres 肯定有一种方法只考虑日期范围内的响应
您需要
上的索引
response (date_recorded, id)
和
response_answer (response_id)
VACUUM
仅索引扫描的表。
对于这样的查询,您不需要外部联接。 PostgreSQL 足够聪明,可以从 response.id
不能是 NULL
.
的事实中推断出
如何按日期过滤查询以防止对大型数据库进行大量顺序扫描?
我的调查应用程序收集 response
s,调查中每个问题的答案都存储在 table response_answer
中。
当我查询所有 response_answers 月份时,我按日期过滤;但是 postgres 运行对所有 response_answers(数以百万计)进行顺序扫描,而且速度很慢。
查询:
explain analyse
select count(*)
from response_answer
left join response r on r.id = response_answer.response_id
where r.date_recorded between '2019-08-01T00:00:00.000Z' and '2019-08-29T23:59:59.999Z';
QUERY PLAN
Aggregate (cost=517661.09..517661.10 rows=1 width=8) (actual time=139362.882..139362.899 rows=1 loops=1)
-> Hash Join (cost=8063.39..517565.30 rows=38316 width=0) (actual time=126512.031..136806.093 rows=316558 loops=1)
Hash Cond: (response_answer.response_id = r.id)
-> Seq Scan on response_answer (cost=0.00..480365.73 rows=7667473 width=4) (actual time=1.443..70216.817 rows=7667473 loops=1)
-> Hash (cost=8053.35..8053.35 rows=803 width=4) (actual time=173.467..173.476 rows=7010 loops=1)
Buckets: 8192 (originally 1024) Batches: 1 (originally 1) Memory Usage: 311kB
-> Seq Scan on response r (cost=0.00..8053.35 rows=803 width=4) (actual time=0.489..107.417 rows=7010 loops=1)
Filter: ((date_recorded >= '2019-08-01'::date) AND (observed_at <= '2019-08-29'::date))
Rows Removed by Filter: 153682
Planning time: 21.310 ms
Execution time: 139373.365 ms
我在 response_answer(response_id)、response_answer(id) 和 response(id) 上有索引。
随着系统的增长,此查询将变得非常慢以致于无法使用,因为顺序扫描将继续花费更长的时间。
在处理大量数据时,我应该如何设计queries/tables,这样数据库就不必运行顺序扫描每一个。单身的。排。在找到所有相关 response_answers?
之前,Postgres 肯定有一种方法只考虑日期范围内的响应您需要
上的索引response (date_recorded, id)
和
response_answer (response_id)
VACUUM
仅索引扫描的表。
对于这样的查询,您不需要外部联接。 PostgreSQL 足够聪明,可以从 response.id
不能是 NULL
.