📊

Athena × QuickSightで「運用できる」コンタクトセンター可視化を作る(全2回連載 第2回)

に公開

これは Amazon Connect 分析データレイク(Analytics Data Lake)をテーマにした全2回連載の第2回です。

第1回はこちら:


対象読者と、今回やること

対象読者はだいたいこのあたりです。

  • Analytics Data Lake を有効化して、Athena からクエリできる状態にはなった
  • QuickSight で「とりあえず」グラフを作れた(第1回のハンズオンまで到達)
  • ただ、運用し始めるとすぐにこうなる
    • KPIの定義が人によって違う
    • QuickSightの計算フィールドが増殖して「どれが真実?」になりがち
    • データ更新や権限が泥臭くなる
    • Athenaコストが読めなくなる

この回でやることは3つです。

  1. Athena View を Semantic Layer として扱う前提で、KPI定義と粒度を揃える
  2. **QuickSight のデータセット設計(SPICE / Direct Query / Refresh)**を、運用視点で整理する
  3. 「コンタクトセンターのダッシュボード」を 役割別に設計して、使われる形に落とす

0. 前提:Analytics Data Lakeは“ほぼリアルタイム”ではない

まず大事な前提。Analytics Data Lake は便利ですが、「秒単位で追えるリアルタイム基盤」ではありません。

  • レコードが作られてから 反映まで多少の遅延があり、概ね1時間以内に利用可能、という位置づけです[1]

つまり、

  • 運用KPIの「当日」「直近1時間」レベルなら十分
  • 「今この瞬間の混雑」を秒で追いたい用途は、別途(メトリクスAPIやリアルタイムパイプライン)が必要

という整理になります。


1. “運用できる可視化”の基本設計:Raw / Semantic / BI を分ける

第1回でも触れましたが、ここが今回の主役です。

  • Raw(Analytics Data Lakeのテーブル):事実の一次ソース。触るのは最小限
  • Semantic(Athena View / CTAS):KPI定義・粒度・ディメンションをここに集約
  • BI(QuickSight):表示とフィルタに寄せ、ロジックは薄く

「ロジックをどこに置くか」を一度決めると、あとが楽になります。

1.1 1枚で見る(図)

1.2 命名規約(例)

運用では「一覧したときに意味が分かる」が地味に効きます。

  • Raw(触らない想定でも、区別のために prefix を付けると吉)
    • raw_*
  • Semantic(View)
    • vw_*
  • マート(必要なら。CTASで作る/日次集計を置く)
    • mart_*

例:

  • vw_contact_daily
  • vw_queue_kpi_15min
  • vw_agent_occupancy_15min
  • mart_queue_kpi_daily(重い集計を日次で固めるなど)

2. Athena 側:Viewで「粒度」と「定義」を固定する

ここからが実務のキモです。

2.1 粒度は、まず “15分” から始めるのが無難

コンタクトセンターでよくある粒度はこのあたり:

  • リアル運用:5分 / 15分
  • 日次レポート:日次
  • 経営向け:週次 / 月次

いきなり全部作ると散ります。まずは 15分粒度 + 日次 の2本立てにするのが扱いやすいです。

  • 15分:SVのモニタリング(SL/ASA/入電/放棄/稼働)
  • 日次:現場改善・経営レポート(AHT/CS/品質/要因分析)

2.2 タイムゾーンは最初に潰す

Connect系は ISO8601 文字列の timestamp が混ざりがちです。View 側で timestamp型に寄せ、必要ならJSTに寄せるのが安全です。

-- 例:ISO8601文字列 -> timestamp
from_iso8601_timestamp(initiationtimestamp) as initiation_ts_utc

JST に寄せる場合は AT TIME ZONE を使う(環境の要件に合わせて統一)。

2.3 「問い合わせ(Contact)」と「エージェント(Agent)」は別ファクトとして扱う

よくある事故パターン:

  • Contact単位のテーブルと Agent interval 系を安易にJOINして、多対多で爆発する
  • QuickSight でJOINして、意図しない重複が入り KPI が壊れる

まずは割り切って、

  • Contactファクト:1件の問い合わせの結果
  • Agent intervalファクト:15分単位の稼働

を分け、両方が必要なダッシュボードは “並べて見る” から始めるのが安全です。


3. QuickSight 側:データセット設計(SPICE / Direct Query / Refresh)

第1回では「まず動かす」ためにデータセットを作りました。ここでは 運用のために 設計します。

3.1 SPICE と Direct Query、どう使い分けるか

ざっくり方針はこれ。

  • SPICE(基本):よく見るダッシュボード、インタラクティブ操作が多い、複数ビジュアルがある
  • Direct Query(例外):直近データが重要、データ量が巨大でSPICEに載せない、もしくは「とりあえず」確認用

Analytics Data Lakeは「だいたい1時間以内に入る」ので、実務ではこう分かれやすいです。

  • SVの「今朝からの状況」:Direct Query でもOK(ただしコスト注意)
  • 経営向けの週次・月次:SPICE で良い(むしろSPICEで固めたい)
  • 品質・要因分析:SPICE + 必要なら日次/週次マート化

補足:SPICE/Direct Query の判断要素は AWS の公式ブログにまとまっています。本文末に参考リンクを載せます。

3.2 Refresh戦略:SPICEは "フル更新" から卒業する

SPICE を使うなら「更新設計」がセットです。

  • SQLベースのSPICEデータセットは 増分更新(Incremental Refresh) を設定できます。
  • ポイントは「増分キー(日付列)」と「ルックバック期間」をちゃんと決めること。

増分更新の前提条件

増分更新を使うには、以下の条件を満たす必要があります:

  1. データセットが SPICE モードであること(Direct Query では不可)
  2. 増分判定に使える列があること
    • 例:interval_15min(timestamp)、dt(日付)、ingested_at(取り込み時刻)など
  3. できれば Athena 側でパーティション化されていること(増分クエリが軽くなる)

増分更新は「指定した期間(ルックバック)だけ取り込み直して、それ以外は前回の SPICE を使う」動きになります。遅延到着データがある場合、ルックバックを長めにしないと取りこぼします。

設定方法(Enterprise Edition)

QuickSightのEnterprise Editionでは、データセット編集画面から増分更新を設定できます:

  1. データセット詳細画面で 「データセットを編集」 をクリック

  2. 画面上部の 歯車アイコン ⚙️「増分更新を設定」 を選択

  3. 以下を設定:

    • 増分列: interval_15min(タイムスタンプ列)
    • ルックバックウィンドウ: 7
  4. 「更新」タブで更新スケジュールを設定:

    • 頻度: 1時間ごと
    • タイムゾーン: Asia/Tokyo

SPICE Update

運用上のおすすめ(例):

  • ルックバック:2〜7日(遅延・再送・訂正を吸収したい場合は長め)
  • 実行頻度:1日数回〜1時間おき("ほぼ1時間以内"の特性に合わせる)

※ここは実データの遅延・訂正の出方に依存するので、後述の「計測メモ」で一度測るのがおすすめです。


4. 実装の型:まずは “Semantic View → Dataset → Dashboard” を一本道にする

「QuickSightの計算フィールドを育てる」より、先に Athena View を育てるほうが長期的に安定します。

4.1 例:Queue KPI(15分粒度)を View で作る

以下は、実際の Analytics Data Lake の CTR(Contact Trace Record)テーブルを元にした実装例です。

前提:

  • 元テーブル: connect_raw.ctr_v2(パーティションプロジェクション対応)
  • View作成先: connect_curated.vw_queue_kpi_15min
  • Analytics Data Lake は「だいたい1時間以内に入る」ため、リアルタイムではなく運用分析向け
CREATE OR REPLACE VIEW connect_curated.vw_queue_kpi_15min AS
SELECT
  -- 15分バケット (timestamp型にキャスト)
  CAST(
    date_trunc('minute', from_iso8601_timestamp(initiationtimestamp))
    - (minute(from_iso8601_timestamp(initiationtimestamp)) % 15) * interval '1' minute
    AS timestamp
  ) as interval_15min,

  -- Queue情報
  queue.arn as queue_arn,
  queue.name as queue_name,

  -- 対応済みコンタクト数(エージェントが対応したもの)
  count_if(agent.username IS NOT NULL AND disconnectreason IS NOT NULL) as handled,

  -- 放棄コンタクト数(エージェント接続前に顧客が切断)
  count_if(agent.username IS NULL AND channel = 'VOICE') as abandoned,

  -- 平均待機時間(秒)- initiationからconnectedtosystemまで
  avg(
    CASE
      WHEN connectedtosystemtimestamp IS NOT NULL
      THEN date_diff('second',
                     from_iso8601_timestamp(initiationtimestamp),
                     from_iso8601_timestamp(connectedtosystemtimestamp))
      ELSE NULL
    END
  ) as asa_seconds,

  -- 平均対応時間(秒)- connectedからdisconnectまで
  avg(
    CASE
      WHEN connectedtosystemtimestamp IS NOT NULL AND disconnecttimestamp IS NOT NULL
      THEN date_diff('second',
                     from_iso8601_timestamp(connectedtosystemtimestamp),
                     from_iso8601_timestamp(disconnecttimestamp))
      ELSE NULL
    END
  ) as aht_seconds,

  -- 総コンタクト数
  count(*) as total_contacts

FROM connect_raw.ctr

WHERE
  -- 過去90日のデータに絞る
  from_iso8601_timestamp(initiationtimestamp) >= current_timestamp - interval '90' day
  -- queueが存在するもののみ
  AND queue.name IS NOT NULL

GROUP BY
  1, 2, 3

ORDER BY
  interval_15min DESC, queue_name;

  • 重要なのは KPI定義をここに集約すること
  • QuickSight 側は avg(aht_seconds) などの単純集計で済むようにする

4.2 QuickSight データセット定義:View をそのままソースにする

QuickSight でデータセットを作成する際は、Athena View を直接ソースとして指定します。

基本設定

  1. データソース: Athena(事前に作成済みのデータソース接続)
  2. データベース: connect_curated
  3. テーブル: vw_queue_kpi_15min(View)
  4. インポートモード: SPICE(推奨)

View をソースにする利点:

  • KPI定義が一元管理される:View側でKPI計算が完了しているため、QuickSightでは単純な集計のみ
  • カラムがシンプル:8カラム程度なので、データセット設計がシンプル
  • パフォーマンス:集計済みデータなので、SPICEへの取り込みが高速(実測 421KB 程度)

データセット構成例

カラム名 データ型 用途
interval_15min DATETIME 時系列分析・増分更新キー
queue_arn STRING キュー識別子
queue_name STRING キュー名(フィルタ・グルーピング)
handled INTEGER 対応済みコンタクト数
abandoned INTEGER 放棄コンタクト数
asa_seconds DECIMAL 平均待機時間(秒)
aht_seconds DECIMAL 平均対応時間(秒)
total_contacts INTEGER 総コンタクト数

Calculated Field の追加(オプション)

QuickSight のデータセット定義で、ビジネス指標を追加する場合:

// 放棄率 (%)
ifelse({total_contacts} > 0, ({abandoned} / {total_contacts}) * 100, 0)

// ASA(分)
{asa_seconds} / 60

// AHT(分)
{aht_seconds} / 60

設計原則:View側で計算できるものはViewに寄せ、QuickSight側はユーザーが理解しやすい表示単位への変換程度に留める。

QuickSight DataSource 01
QuickSight DataSource 02
QuickSight DataSource 03
QuickSight DataSource 04


5. “役割別ダッシュボード”の型(よくある4枚)

5.1 経営向け(週次 / 月次)

目的:傾向と意思決定
よく置くもの:

  • 入電/処理件数(チャネル別)
  • SL/ASA/AHT(週次の推移)
  • 品質(評価スコア、センチメントの悪化割合)
  • 重要カテゴリ(問い合わせ理由トップN)

設計ポイント:

  • SPICE前提(サクサク動くことが価値)
  • “上から読んで”理解できる(KPI→要因→内訳)

5.2 SV向け(当日〜直近)

目的:現場運用
よく置くもの:

  • 今日の入電・放棄・SL(時間帯)
  • キュー別の詰まり(Top N)
  • エージェント稼働(占有率/ACW/離席)

設計ポイント:

  • 15分粒度が中心
  • Direct Query にしたい誘惑が出るが、Athenaコストとトレードオフ
  • “重いビジュアル”は下に置く(QuickSight は上から順に評価されるので体感が変わる)

5.3 品質・改善向け(QA/企画)

目的:原因分析と施策
よく置くもの:

  • Contact Lens のキーワード/カテゴリ
  • センチメント分布(悪化の多いキュー/時間帯)
  • 再入電(リピート)や転送の多いパターン

設計ポイント:

  • ここは Join が増えやすいので、Athena View で “分析用フラットテーブル” を作ると安定
  • 期間を絞るUI(パラメータやフィルタ)を先に用意する

5.4 エージェント本人向け(セルフモニタ)

目的:自己改善(ただし見せ方は繊細)
よく置くもの:

  • 自分の対応件数・AHT・ACW
  • 直近の評価/フィードバック
  • チーム平均との差(出し方は運用と相談)

設計ポイント:

  • RLS をちゃんと設計(自分のデータだけ)
  • “ランキング”を前面に出しすぎない(現場の空気が荒れる)

6. Athena コストとパフォーマンス:最低限これだけ

QuickSight を Direct Query で使い始めると、Athena コストは簡単に跳ねます。

6.1 Workgroup でガードレールを作る

Athena の Workgroup は、

  • クエリ結果の保存先
  • 1クエリあたりのスキャン上限
  • メトリクス

などを強制できます。

Athena WG Limit 01
Athena WG Limit 02

おすすめの運用:

  • QuickSight 用 Workgroup を分ける(例:wg_quicksight_connect
  • 1クエリのスキャン上限を設定して事故を防ぐ
  • 出力先は専用S3に固定

7. まとめ:第2回の結論

  • 「運用できる可視化」は、KPI定義の置き場所でだいたい決まる
    • Rawは触らない
    • Semantic(Athena View)で定義を集約
    • QuickSightは表示に寄せる
  • QuickSight は SPICE/Direct Query/Refresh を設計しないと、コストと運用が破綻する
  • ダッシュボードは 役割別に分けると使われる(全部盛りはだいたい死ぬ)

参考リンク(公式中心)

脚注
  1. Amazon Connect analytics data lake は、レコード作成後の処理遅延を経て「1時間以内」に利用可能になる旨が記載されています。 https://docs.aws.amazon.com/connect/latest/adminguide/data-lake.html ↩︎

Discussion