【发布时间】:2012-09-07 18:28:05
【问题描述】:
我在 Netezza 中有一个小型(ish)聚合数据集,大约 1000 万行,位于 TwinFin 6 上。
为了简化问题,我减少了列数:
CUSTOMER_SALES_AGG
CUSTOMER_ID
NUMBER_TRANS
TOTAL_DOLLARS
TOTAL_ITEMS
此表分布在 CUSTOMER_ID 上,每个客户 ID 有 1 行,收集客户进行的总交易、他们花费的总美元以及他们购买的物品数量。
我正在尝试通过 # 次交易、总花费的美元和购买的总物品来计算每个客户在所有客户中的十分位排名。例如。如果客户花费 >= 90% 的其他客户,他们将排名第 1 个十分位。
我已经建立了一个查询:
SELECT
CUSTOMER_ID,
NUMBER_TRANS,
NTILE(10) OVER(ORDER BY NUMBER_TRANS DESC NULLS LAST) as TRANS_DECILE,
TOTAL_DOLLARS,
NTILE(10) OVER(ORDER BY TOTAL_DOLLARS DESC NULLS LAST) as DOLLARS_DECILE,
TOTAL_ITEMS,
NTILE(10) OVER(ORDER BY TOTAL_ITEMS DESC NULLS LAST) as ITEMS_DECILE
FROM CUSTOMER_SALES_AGG;
这可行,但它非常很慢,需要将近 10-20 分钟才能运行。
由于进行十分位数计算需要对数据进行排序,然后将排序后的数据分组,Netezza 的 MPP 结构似乎可以很好地处理这个问题。如果我对十分位数进行分区,我可以重新分配并在每个 SPU 上进行排名,它可能会更快。
关于如何加快速度的任何想法?
【问题讨论】:
-
排名和排序本质上是可并行化的操作。我希望多处理器数据库能够有效地处理这些操作。但是,我不能谈论特定的 Netezza 操作。
-
在某些方面,是的,确实如此。但是,对存在于单独的无共享系统上的数据进行排序需要对数据进行两次排序 - 在每个 SPU 上一次,然后在主机上再次对完整数据集进行排序..?
-
。 .数据确实需要排序。如果正确实施,引擎将执行相当于快速排序的操作,以在处理器之间拆分数据,然后枚举结果,并在控制处理器上完成排序。这需要只发送一次数据——并且只发送被排名的字段——尽管还有额外的枚举和其他工作。此操作需要一些时间,但在合理的硬件上以秒而不是分钟为单位。
-
同意,这基本上就是我认为它应该做的事情。我们的盒子上有 6 个 s-blade(我相信这意味着 48 个处理器)。
-
你可以试试 row_number() 吗? Netezza 可能没有针对未分区的情况进行优化;似乎它正在将所有内容发送到一个处理器。他们可能会更好地优化 ROW_NUMBER()。如果是这样,您也许可以将查询重写为更有效的内容。