为啥 Redshift 不支持 DOES EXIST 相关子查询?

Posted

技术标签:

【中文标题】为啥 Redshift 不支持 DOES EXIST 相关子查询?【英文标题】:Why doesn't Redshift support the DOES EXIST correlated sub-query?为什么 Redshift 不支持 DOES EXIST 相关子查询? 【发布时间】:2016-03-05 22:25:27 【问题描述】:

众所周知,RedShift 有一组相关的子查询,它可以去相关,从而使查询运行得更快。

为什么 Redshift 不能去关联常见的 DOES NOT EXIST 子查询?例如,下面的查询基本上是:

SELECT ProductID,
       ProductName
FROM   Products p
WHERE  NOT EXISTS (SELECT *
                   FROM   [Order Details] od
                   WHERE  p.ProductId = od.ProductId) 

有人能解释一下为什么 Redshift 不能去关联这个查询吗?

【问题讨论】:

【参考方案1】:

我不知道为什么会做出这个决定,但这可能是因为效率。执行NOT EXISTS 意味着数据库必须扫描整个子查询以查找不存在的记录。这是非常低效的,应该尽可能避免——尤其是在处理大数据时。

我注意到您正在从Orders 检索所有列,其中只需要ProductId。鉴于 Redshift 是一个列式数据库,选择所需的最小列数会更有效。

您似乎正在尝试查找任何订单上不存在的产品,因此请尝试:

SELECT
  ProductID,
  ProductName
FROM
  Products
WHERE
  ProductID NOT IN (SELECT DISTINCT ProductId from Orders)

在英语中,这表示“选择任何不在订单上的产品”。

【讨论】:

嗯,一定是有原因的。您的查询是 O(n),因为查询是不相关的。但是亚马逊明确提到他们不支持我提到的查询,当它应该是微不足道的转换时。【参考方案2】:

我在 RedShift documentation 中没有看到任何排除这种情况的东西。但是,它很容易表达为LEFT JOIN

SELECT p.*
FROM Products p LEFT JOIN
     [Order Details] od
     ON p.ProductId = od.ProductId
WHERE od.ProductId IS NULL;

至于为什么亚马逊选择特定功能,您必须询问他们的开发人员或营销人员。

【讨论】:

我对为什么感兴趣。看起来像亚马逊这样的蒙古人可以负担得起开发这种奢侈品。【参考方案3】:

Redshift 不是在 Amazon 开发的,而是被收购以换取对 ParAccel 的投资(因为被其他人收购)。 ParAccel 显然急需现金,于是将家里的白银卖给了亚马逊。

Redshift 是 ParAccel 在投资时提供的数据库的一个子集(假定是其中的大部分,但从未明确定义)。亚马逊在这笔交易中没有聘请任何工程师 - 只是代码。

在 Redshift 的早期,我们只看到产品的细微变化。很明显,他们正在努力安全地做出深刻的改变。他们现在拥有一支扎实的工程团队,拥有丰富的代码知识,并且改进正在以不错的速度推出。

所有这些实际上都是一种冗长的说法,即数据库引擎是一个非常复杂且昂贵的软件。亚马逊是出了名的,呃,“吝啬”,我认为建立这个团队/经验的成本是我们没有(也不会)看到产品降价的原因。

Curt Monash 说: "规则 1: 开发一个好的 DBMS 需要 5-7 年和数千万美元。如果事情进展顺利的话。规则 2: 你不是规则 1 的例外情况。”http://www.dbms2.com/2013/03/18/dbms-development-marklogic-hadoop/

【讨论】:

【参考方案4】:

AWS Redshift 支持此功能。可以在on the AWS Redshift page here 找到文档。以下解释摘自上述链接。

语法是:

[ NOT ] EXISTS (table_subquery)

地点:

EXISTS 当 table_subquery 返回至少一行时为真。 NOT EXISTS 当 table_subquery 没有返回任何行时为真。 table_subquery 一个子查询,计算结果为包含一列或多列和一列或多行的表。

例子:

select dateid from date
where exists (
select 1 from sales
where date.dateid = sales.dateid
)
order by dateid;

dateid
--------
1827
1828
1829
...

【讨论】:

以上是关于为啥 Redshift 不支持 DOES EXIST 相关子查询?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C++11 不支持匿名结构,而 C11 支持?

为啥不能在 Redshift 的 CTE 的某些子句中调用不可变的 UDF?

为啥我会收到“您的账户不支持该地区的 EC2-Classic 平台。”?

由于 Databricks 不公开支持 spark-redshift lib,使用 Scala spark 从 Redshift 读取/写入 Redshift 的最佳方法是啥

Redshift 加载数据问题:Redshift 表不支持指定的类型或函数(每条 INFO 消息一个)

为啥在redshift中创建表需要很多时间?