Amazon QuickSight の SPICE データセット更新失敗時の具体的なエラーメッセージの確認方法
はじめに
Amazon QuickSight を運用していると、SPICE へのデータ取り込み処理のスケジュール更新で失敗することがあります。本記事では、SPICE データセットの更新失敗時に具体的なエラーメッセージを確認する方法を紹介します。
SPICE データセット更新失敗の通知仕様
SPICE データセットのスケジュール更新が失敗すると、対象データセットの所有者のみにメール通知が送信されます。
所有者以外のユーザーには通知されません。そのため利用者から「ダッシュボードが見えない」という連絡を受けて初めて問題に気付くことが私は多いです。
私は先人の作成した便利なデータセットを活用していることが多く、所有者ではないことがあります。データセットの所有者にトラブルシュートしてもらえば早い話ですが、自分でも対応可能なので切り分けてから報告のスタンスです。
エラーメッセージの確認手順
ダッシュボードから問題のデータセットを特定
問題が確認されたダッシュボード画面の DB アイコンをクリックします。私はよく分析画面を開いてしまうのですが、ダッシュボード画面なので注意です。
更新失敗したデータセットの確認
更新に失敗したデータセットが一覧で確認できます。今回は 1 件のデータセットが更新に失敗していました。
具体的なエラーメッセージの確認
データセットを開き、「更新」タブから失敗したステータスをクリックします。
具体的なエラーメッセージが表示されます。
ここからがトラブルシュートのスタートです。エラーは多岐にわたるため、特筆すべきものがあれば別の機会に紹介します。
対処方法の一例
更新の再実行
データ取得タイミングの問題なら再実行で解決することもあります。その後で更新スケジュールの時間調整をします。
クエリの修正方法
エラーの原因が SQL クエリにある場合の修正手順です。参照元のデータベースのデータ量が増えてクエリの結果が返ってこなくなることが多いので、期間指定しているなら期間を短くするなどの調整をたびたびしています。
データセットの編集画面を開く
「概要」タブから「データセットの編集」をクリックします。
SQL クエリの修正
「SQL クエリを編集」からクエリを修正します。
保存して公開
クエリの修正が完了したら、変更内容を保存して公開する必要があります。画面右上の「保存して公開」ボタンをクリックします。
更新処理の確認
保存と公開が完了すると、自動的に SPICE への更新処理が開始されます。更新状況は「データセット」画面の「更新」タブで確認できます。
SQL クエリ修正後の切り戻し方法
クエリを修正した後により状況が悪化して、元の状態に戻したい場合の切り戻し手順です。QuickSight では、データセットの公開履歴を利用して以前のバージョンに戻すことができます。
データセットの履歴確認
データセット編集画面で、右上のメニューから「矢印のところ」をクリックして「公開履歴」を選択します。
戻したいバージョンの選択
公開履歴が一覧表示されます。戻したいバージョンを選択し、「元に戻す」ボタンをクリックします。
切り戻しの実行と確認
選択したバージョンへの切り戻しが実行されます。処理完了後、データセットが指定したバージョンの状態に戻ります。
切り戻し後は、自動的に SPICE の更新が開始されます。更新が完了すれば以前の状態に戻ります。根本原因が解決していなければ引き続き更新が失敗することには変わりません。
全 SPICE データセットの更新状況を確認したい
他の SPICE データセットは問題ないのか気になることがあります。しかし、AWS マネジメントコンソールには、全 SPICE データセットの更新状況を一覧表示する機能がありません。更新失敗通知も所有者にしかメール通知されないため、現状把握が困難です。
AWS CLI で一覧を作成してみた
良い方法がないかと検討した結果、QuickSight の API から取得できる情報を加工すれば全データセットの最終更新日と更新成否を一覧表示できました。AWS CLI で試した結果です。
+------------------------------+------------+---------------------+----------+----------+----------+
| Dataset Name | Status | Last Updated | Duration | Size MB | Rows |
+------------------------------+------------+---------------------+----------+----------+----------+
| social_media_analytics | COMPLETED | 2022-06-30 17:59:36 | 16s | 0.34 | 1461 |
| employee_directory | COMPLETED | 2022-07-07 16:21:32 | 16s | 0.73 | 1956 |
| account_billing_audit | COMPLETED | 2025-05-20 10:00:30 | 46s | 0 | 28 |
| customer_refund_data | COMPLETED | 2025-05-20 10:00:29 | 137s | 0 | 36 |
| insurance_coverage_daily | COMPLETED | 2024-07-11 16:49:06 | 147s | 157.86 | 147889 |
| marketing_campaign_metrics | FAILED | 2021-11-09 16:14:33 | 16s | 0.34 | 1461 |
| insurance_coverage_hourly | COMPLETED | 2024-08-29 13:47:42 | 164s | 113.81 | 106173 |
+------------------------------+------------+---------------------+----------+----------+----------+
実行スクリプト全文。
#!/bin/bash
# Default parameters
AWS_ACCOUNT_ID=${1:-"123456789012"}
REGION=${2:-"ap-northeast-1"}
OUTPUT_DIR=${3:-"datasets-output"}
REPORT_FILE="$OUTPUT_DIR/spice-ingestion-report.txt"
echo "Checking SPICE dataset ingestions for AWS account: $AWS_ACCOUNT_ID in region: $REGION"
# Create output directory if it doesn't exist
mkdir -p "$OUTPUT_DIR"
# Fetch datasets directly and process in memory
echo "Fetching datasets..."
DATASETS_JSON=$(aws quicksight list-data-sets \
--aws-account-id "$AWS_ACCOUNT_ID" \
--region "$REGION" \
--output json)
if [ $? -ne 0 ]; then
echo "Error fetching datasets. Please check your AWS credentials and permissions."
exit 1
fi
# Extract SPICE dataset IDs
echo "Filtering SPICE datasets..."
DATASET_IDS=($(echo "$DATASETS_JSON" | jq -r '.DataSetSummaries[] | select(.ImportMode == "SPICE") | .DataSetId'))
DATASET_COUNT=${#DATASET_IDS[@]}
if [ $DATASET_COUNT -eq 0 ]; then
echo "No SPICE datasets found."
exit 0
fi
echo "Found $DATASET_COUNT SPICE datasets."
# Create table header for the report
{
echo "+$(printf '%0.s-' {1..30})+$(printf '%0.s-' {1..12})+$(printf '%0.s-' {1..21})+$(printf '%0.s-' {1..10})+$(printf '%0.s-' {1..10})+$(printf '%0.s-' {1..10})+"
printf "| %-28s | %-10s | %-19s | %-8s | %-8s | %-8s |\n" "Dataset Name" "Status" "Last Updated" "Duration" "Size MB" "Rows"
echo "+$(printf '%0.s-' {1..30})+$(printf '%0.s-' {1..12})+$(printf '%0.s-' {1..21})+$(printf '%0.s-' {1..10})+$(printf '%0.s-' {1..10})+$(printf '%0.s-' {1..10})+"
} > "$REPORT_FILE"
# Process each dataset
for ((i=0; i<$DATASET_COUNT; i++)); do
DATASET_ID=${DATASET_IDS[$i]}
# Get dataset name from the fetched JSON
DATASET_NAME=$(echo "$DATASETS_JSON" | jq -r ".DataSetSummaries[] | select(.DataSetId == \"$DATASET_ID\") | .Name")
echo "Fetching ingestion data for: $DATASET_NAME"
# Get ingestions for this dataset
INGESTIONS_JSON=$(aws quicksight list-ingestions \
--aws-account-id "$AWS_ACCOUNT_ID" \
--data-set-id "$DATASET_ID" \
--region "$REGION" \
--output json)
if [ $? -ne 0 ]; then
# If there's an error, add a row indicating the error
printf "| %-28s | %-10s | %-19s | %-8s | %-8s | %-8s |\n" "${DATASET_NAME:0:28}" "ERROR" "N/A" "N/A" "N/A" "N/A" >> "$REPORT_FILE"
continue
fi
# Extract latest ingestion data
LATEST_INGESTION=$(echo "$INGESTIONS_JSON" | jq -r '.Ingestions | sort_by(.CreatedTime) | reverse | .[0]')
if [ -z "$LATEST_INGESTION" ] || [ "$LATEST_INGESTION" == "null" ]; then
# If no ingestion found, add a row indicating no data
printf "| %-28s | %-10s | %-19s | %-8s | %-8s | %-8s |\n" "${DATASET_NAME:0:28}" "NO DATA" "N/A" "N/A" "N/A" "N/A" >> "$REPORT_FILE"
continue
fi
# Extract ingestion details
INGESTION_STATUS=$(echo "$LATEST_INGESTION" | jq -r '.IngestionStatus')
# Format created time to be more readable
CREATED_TIME=$(echo "$LATEST_INGESTION" | jq -r '.CreatedTime' | sed 's/\+09:00//' | sed 's/T/ /' | cut -d. -f1)
# Duration
INGESTION_TIME=$(echo "$LATEST_INGESTION" | jq -r '.IngestionTimeInSeconds // "N/A"')
if [ "$INGESTION_TIME" == "null" ]; then INGESTION_TIME="N/A"; else INGESTION_TIME="${INGESTION_TIME}s"; fi
# Calculate size in MB
SIZE_BYTES=$(echo "$LATEST_INGESTION" | jq -r '.IngestionSizeInBytes // 0')
if [ "$SIZE_BYTES" == "null" ]; then SIZE_BYTES=0; fi
SIZE_MB=$(echo "scale=2; $SIZE_BYTES / 1024 / 1024" | bc)
# 小数点の前に0がない場合、0を追加
if [[ $SIZE_MB == .* ]]; then
SIZE_MB="0$SIZE_MB"
fi
# Extract row count
ROWS_INGESTED=$(echo "$LATEST_INGESTION" | jq -r '.RowInfo.RowsIngested // "N/A"')
if [ "$ROWS_INGESTED" == "null" ]; then ROWS_INGESTED="N/A"; fi
# Add to report
printf "| %-28s | %-10s | %-19s | %-8s | %-8s | %-8s |\n" "${DATASET_NAME:0:28}" "$INGESTION_STATUS" "$CREATED_TIME" "$INGESTION_TIME" "$SIZE_MB" "$ROWS_INGESTED" >> "$REPORT_FILE"
done
# Add table footer
echo "+$(printf '%0.s-' {1..30})+$(printf '%0.s-' {1..12})+$(printf '%0.s-' {1..21})+$(printf '%0.s-' {1..10})+$(printf '%0.s-' {1..10})+$(printf '%0.s-' {1..10})+" >> "$REPORT_FILE"
echo "Report generated at $REPORT_FILE"
# Display the report
echo ""
cat "$REPORT_FILE"
echo ""
まとめ
Amazon QuickSight の SPICE データセット更新時の切り分け方法と対処法の一例について解説しました。
問題のダッシュボードから、更新に失敗しているデータセットの特定と、具体的なエラーメッセージの確認ができれば、データセットの所有者でなくても基本的なトラブルシューティングが可能です。
おわりに
QuickSight の運用で感じる課題について共有させていただきました。マネージドサービスでも運用の手間は発生することをお伝えしたかった次第です。
本記事が QuickSight 運用でお困りの方の参考になれば幸いです。