実験の背景

TaoBao などの E-commerce 企業は、ユーザーデータ分析に関してあらゆる種類の視点と手順を持っています。 E-commerce データウェアハウスとビジネス分析では、 過去数日間の訪問者、購入者、常連客の数などさまざまな指標の計算が必要になることも珍しくありません。

こういった指標の計算は、一定期間にわたって E-commerce プラットフォームまたはオンラインストアに蓄積されたデータに基づくものです。 ここでは、計算用のデータが MaxCompute に格納されていることを前提としています。

一般に、これらの指標はログ詳細テーブルを使用して計算されます。 以下に、あるプロダクトの過去 30 日間の訪問者数を計算するコードを示します。


select item_id --Item ID 
  ,count(distinct visitor_id) as ipv_uv_1d_001 
from Log detail table that stores the data about the visits to the item 
where ds <= ${bdp.system.bizdate} 
and ds >=to_char(dateadd(to_date(${bdp.system.bizdate},'yyyymmdd'),-29,'dd'),'yyyymmdd') 
 group by item_id;
このコード内のすべての変数は、DataWorks のスケジューリング変数です。 DataWorks のスケジューリングタスクにのみ適用可能な変数です。 このドキュメントの以降の内容にもこの条件が適用されます。

上記のようなコードは、毎日数多くのログが生成される場合、重大な問題を引き起こします。 大量の マップインスタンスが必要となり、99999 の数量制限を超えて マップタスクの実行とその後の操作に影響を与えかねません。

ログデータが 30 日間にわたって生成されるだけでなく、1 日当たりのログデータが大量になるため、大量のマップインスタンスが必要になります。 SELECT 操作には、上限で許可されているよりも多くのマップインスタンスが必要となり、 異常なコード実行の原因となります。

チュートリアルの目標

長期指標の計算によるパフォーマンスへの影響は、以下のいずれかの方法で最小限に抑えることができます。

  • 複数日にわたってデータのサマリーを作成しなくてよいようデータ量を減らします。

  • 一時テーブルを作成し、1D データのサマリーを作成して重複データを削除することにより、日次でデータ量を減らすことができます。

チュートリアルスキーム

手順
  1. 中くらいの大きさのテーブルを作成して、毎日サマリーを作成します。

    上記の例では、毎日のサマリーに、item_id + visitor_id の精度を持つ中規模のテーブルを作成できます。 このテーブルを A として記録します。例:

    
    insert overwrite table mds_itm_vsr_xx(ds='${bdp.system.bizdate} ')
    select item_id,visitor_id,count(1) as pv
      from
      (
      select item_id,visitor_id
      from Log detail table that stores the data about the visits to the item 
      where ds =${bdp.system.bizdate} 
      group by item_id,visitor_id
      )a;
  2. この中規模テーブルを使用して複数日のデータを演算しサマリーを作成します。

    以下のようにコーディングして、30 日間のサマリーをテーブル A に作成します。

    
    select item_id
            ,count(distinct visitor_id) as uv
            ,sum(pv) as pv
      from mds_itm_vsr_xx
      where ds <= '${bdp.system.bizdate} '
      and ds >= to_char(dateadd(to_date('${bdp.system.bizdate} ','yyyymmdd'),-29,'dd'),'yyyymmdd')
      group by item_id;

影響と考慮事項

上記の方法では、毎日のアクセスログの詳細データが重複排除され、データ量を削減しつつパフォーマンスも改善されます。 ただ、複数日のデータを計算するたびに N 個のパーティションからデータを読み取る必要があり、これはこの方法の弱点です。

データの読み取りを繰り返さなくてよいようにするため、N 個のパーティションのデータを、すべての履歴データを含む 1 つのパーティションに圧縮することができます。

この圧縮を行うには、段階的かつ累計的な手法で長期指標を計算できます。

使用事例

過去 1 日の店舗の常連客の数を計算します。 常連客は、過去 30 日間など一定の期間にわたって店舗で品目を購入した購入者として定義されます。

常連の購入者数の計算は以下のとおりです。


select item_id ----Item ID     
        ,buyer_id as old_buyer_id
from Detail table that stores the data about buyers and purchased items 
where ds < ${bdp.system.bizdate} 
and ds >=to_char(dateadd(to_date(${bdp.system.bizdate},'yyyymmdd'),-29,'dd'),'yyyymmdd') 
group by item_id
        ,buyer_id;

改善:

  • あるテーブルをテーブル A として、購入者と購入品目の関係を記録するテーブルにします。 具体的には、最初の購入期間、最後の購入期間、購入した品目の総数、および合計購入金額をこのテーブルに記録します。

  • 過去 1 日の支払い詳細ログに基づいて、テーブル A のデータを毎日更新します。

  • 個人が常連の購入者であるかどうかを判断するには、最後の購入が過去 30 日以内であるかどうかを確認します。 これにより、データ関係のペアが重複排除され、入力データの量が減ります。