3

我在 TwinFin 6 上的 Netezza 中有一个小的(ish)聚合数据集,大约 1000 万行。

为了简化问题,我减少了列数:

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 上进行排名,它可能会更快。

关于如何加快速度的任何想法?

4

1 回答 1

3

似乎主要问题源于NTILE在同一个 SQL 语句中使用了多个分析函数 ()(我的实际语句以 7 种不同的方式对客户进行排名)。

据我所知,正如@GordonLinoff 在评论中解释的那样,Netezza 会在每个处理器上进行快速排序,并在控制器系统(Netezza 主机)上进行最终快速排序。然而,它只执行一次,然后,正如他猜测的那样 - 将其全部推送到控制器系统。

它继续对控制器系统上的数据进行快速排序以用于剩余的分析功能,根本不使用并行性。我希望它应该以每种方式对数据进行排序,在每个处理器上,在主机上进行最终排序,然后将数据推送回处理器,以便对每列进行最终哈希连接。

我最终创建了一个类似这样的查询。

WITH 
NT AS (
  select customer_id, 
         number_trans,
         ntile(10) over (order by number_trans) as trans_decile
),
TD AS (
  select customer_id, 
         total_dollars,
         ntile(10) over (order by total_dollars) as dollars_decile
),
NI AS (
  select customer_id, 
         total_items,
         ntile(10) over (order by total_items) as items_decile
)
SELECT
    NT.CUSTOMER_ID, NT.NUMBER_TRANS, NT.TRANS_DECILE,
    TD.TOTAL_DOLLARS, TD.DOLLARS_DECILE,
    NI.TOTAL_ITEMS, NI.ITEMS_DECILE
FROM NT
JOIN TD ON (NT.CUSTOMER_ID = TD.CUSTOMER_ID)
JOIN NI ON (NT.CUSTOMER_ID = NI.CUSTOMER_ID);

这个查询的计划要复杂得多,但对于我进行 7 次分析排名的情况,查询时间从 12 分钟减少到不到 5 分钟。

于 2012-09-07T21:14:41.400 回答