对于不存在的行,Redshift SELECT *性能与COUNT(*)相比

时间:2014-07-04 15:47:16

标签: postgresql amazon-redshift paraccel

当我运行两个看似相似的查询时,我对Redshift正在做什么感到困惑。也不应该返回结果(查询不存在的配置文件)。具体做法是:

SELECT * FROM profile WHERE id = 'id_that_doesnt_exist' and project_id = 1;
  Execution time: 36.75s

SELECT COUNT(*) FROM profile WHERE id = 'id_that_doesnt_exist' and project_id = 1;
  Execution time: 0.2s

鉴于该表按project_id排序,然后id我认为这只是一个关键查找。 SELECT COUNT(*) ...返回0结果为0.2秒,这与我的期望大致相同。 SELECT * ...返回0结果为37.75秒。对于相同的结果,这是一个巨大的差异,我不明白为什么?

如果它有助于架构如下:

CREATE TABLE profile (
    project_id integer not null,
    id varchar(256) not null,
    created timestamp not null,
    /* ... approx 50 other columns here */
)
DISTKEY(id)
SORTKEY(project_id, id);

SELECT COUNT(*) ...

解释
XN Aggregate  (cost=435.70..435.70 rows=1 width=0)
  ->  XN Seq Scan on profile  (cost=0.00..435.70 rows=1 width=0)
        Filter: (((id)::text = 'id_that_doesnt_exist'::text) AND (project_id = 1))

SELECT * ...

解释
XN Seq Scan on profile  (cost=0.00..435.70 rows=1 width=7356)
    Filter: (((id)::text = 'id_that_doesnt_exist'::text) AND (project_id = 1))

为什么非计数要慢得多?当然Redshift知道行不存在吗?

1 个答案:

答案 0 :(得分:1)

原因是:在许多RDBMS中,关于count(*)问题的答案通常没有实际的数据扫描:仅来自索引或表统计信息。 Redshift存储曾经存在或不存在答案的块的最小值和最大值,例如在描述情况下。如果在最小/最大块边界内请求值,则仅对过滤字段数据执行扫描。如果请求的值是较低或较高的块边界,则根据存储的统计数据,可以更快地给出答案。如果是"选择*"问题RedShift实际扫描查询中询问的所有列数据:" *"但只能按"中的列过滤"子句。