QuickSight の SPICE 増分更新の挙動をイメージ図付きで解説します

QuickSight の SPICE 増分更新の挙動をイメージ図付きで解説します

QuickSight の SPICE 増分更新の時間の計算方法、ウィンドウサイズ変更時の挙動、スケジュールを削除し再度スケジュール設定した際の挙動等をイメージ図付きで詳細に解説します。
Clock Icon2025.02.17

コーヒーが好きな emi です。

QuickSight の SPICE 増分更新の挙動はやや癖があり、理解に時間を要しましたので、イメージ図付きでガッツリ解説します。

そもそも SPICE とは、というところは以下のブログの SPICE(スパイス) 部分を参照いただけますと幸いです。

https://dev.classmethod.jp/articles/introduction-2024-amazon-quicksight/#toc-spice

最初にまとめ

  • A. 日本時間 JST でSPICE 増分更新をした際の増分更新の範囲は以下
      1. JST ⇒ UTC に変換して - 9 時間
        1. から「頻度」に設定した時間をマイナス
      • 「毎日」なら - 24 時間、「毎時」なら - 1 時間、など
        1. からウィンドウサイズに指定した時間をマイナス
      • 「ウィンドウサイズ 1 時間」なら - 1 時間、「ウィンドウサイズ 12 時時」なら - 12 時間、など

▼頻度:毎日、ウィンドウサイズ:1 時間、0:30 JST に SPICE 増分更新を設定した場合のイメージ
QuickSight_SPICE_Incremental_Update_3

  • B. 一度 SPICE 増分更新スケジュールを削除して、日を置いて再度 SPICE 増分更新スケジュールを設定すると、増分更新の設定に関わらず、前回の最後の SPICE 増分更新で取り込んだ時間から現在の時刻までのデータが全部 SPICE に取り込まれる。その後、 SPICE 増分更新が設定した頻度で開始される
    QuickSight_SPICE_Incremental_Update_6

  • C. SPICE 増分更新のウィンドウサイズを変更すると、まずフル更新が走り、その後 SPICE 増分更新が設定した頻度で開始される

    • 「今すぐ更新」で SPICE 増分更新のウィンドウサイズを変更すると、既存の SPICE 増分更新スケジュールのウィンドウサイズも変更される

▼「今すぐ更新」で SPICE 増分更新のウィンドウサイズを 1⇒12 時間に変更した場合のイメージ
QuickSight_SPICE_Incremental_Update_4

  • D. ウィンドウサイズを変えずに SPICE 増分更新を「今すぐ更新(手動更新)」すると、前回の更新時点から現時点までのレコードが取り込まれる
    • つまり、SPICE 増分更新のウィンドウサイズを変更しなければ、フル更新は走らず、SPICE 増分更新で設定した通りにスケジュールされる

▼ウィンドウサイズを変えずに SPICE 増分更新を「今すぐ更新(手動更新)」した場合のイメージ
QuickSight_SPICE_Incremental_Update_5

  • E. SPICE 増分更新のスケジュールの頻度のみを変更する際は必ず未来日付を指定する必要があり、変更保存後もフル更新は走らない
    • 指定した未来日付から設定した頻度でスケジュール実行される
    • 頻度を変更した 1 回目の SPICE 増分更新は、前回の取り込み範囲の後から漏れなく取り込むよう範囲指定される

▼ SPICE 増分更新スケジュールで頻度のみを変えた場合のイメージ
QuickSight_SPICE_Incremental_Update_16

挙動確認

事前準備

まず、S3 バケットへのデータ配置、Athena テーブル作成、データセット・分析・ダッシュボード作成を行います。

QuickSight_SPICE_Incremental_Update_7

事前準備手順は以下トグルを展開して確認ください。本記事の本題ではないのでトグルにたたんでいます。

S3 バケットへのデータ配置、Athena テーブル作成、データセット・分析・ダッシュボード作成

S3 バケットに置く CSV ファイル

ある会社でお菓子を食べたり持ってきて補充するデータです。お菓子を食べたらごきげんになったり、お菓子が無くて不調になったりする会社をイメージしました。

1700_sweets_with_status.csv
datetime,department,section,status,chocolate,donut,osenbei
2024-10-16 17:00:00.000,コンピューティング部,EC2課,不調,19,1,20
2024-10-16 17:00:00.000,コンピューティング部,Lambda課,不調,12,4,22
2024-10-16 17:00:00.000,コンピューティング部,Lightsail課,不調,13,3,24
2024-10-16 17:00:00.000,ストレージ部,EFS課,超ごきげん,18,7,29
2024-10-16 17:00:00.000,ストレージ部,FSx課,ごきげん,18,1,24
2024-10-16 17:00:00.000,ストレージ部,S3課,不調,15,2,20
2024-10-16 17:00:00.000,データベース部,RDS課,普通,14,2,28
2024-10-16 17:00:00.000,データベース部,DocumentDB課,不調,19,7,29
2024-10-16 17:00:00.000,データベース部,DynamoDB課,超ごきげん,11,2,24

CSV のひな形は生成 AI に生成してもらって、自分でいくつか数字やステータスを変更しました。
生成したモデルは GPT-4o です。ちなみにプロンプトはこちらです。

AWS株式会社は以下のような組織構造を持っています。

- コンピューティング部
    - EC2課
    - Lambda課
    - Lightsail課
- ストレージ部
    - EFS課
    - FSx課
    - S3課
- データベース部
    - RDS課
    - DocumentDB課
    - DynamoDB課

それぞれの課は時間帯によって以下のステータスを持ちます。

- 超ごきげん
- ごきげん
- 普通
- 不調

それぞれの課に所属する人はお菓子を食べたり持ってきたりします。お菓子の種類は以下の通りです。

- チョコレート
- ドーナツ
- おせんべい

日時, 部署名, 課名, ステータス, チョコレートの個数, ドーナツの個数, おせんべいの個数 が記載された CSV ファイルを作成してください。
カラム名は `datetime`, `department`, `section`, `status`, `chocolate`, `donut`, `osenbei` としてください。

日時の形式は `YYYY-MM-DD HH:MM:SS` で date 型としてください。

S3 のパス構成は以下のようになっています。/jst/ の後ろの日付パスを Athena の Partition Projection(パーティション射影)で自動認識させます。

s3://<S3 バケット名>/sweets_with_status/jst/2024/10/16/17/1700_sweets_with_status.csv

Athena テーブルの作成

sweets_with_status テーブル作成クエリ
CREATE EXTERNAL TABLE IF NOT EXISTS `spiceincrementalupdatedb`.`sweets_with_status` (
  `datetime` timestamp,
  `department` string,
  `section` string,
  `status` string,
  `chocolate` int,
  `donut` int,
  `osenbei` int
)
PARTITIONED BY (
  `partition_date` string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
  'field.delim' = ',',
  'skip.header.line.count' = '1'
)
LOCATION 's3://<S3 バケット名>/sweets_with_status/jst/'
TBLPROPERTIES (
  'classification' = 'csv',
  'projection.enabled' = 'true',
  'projection.partition_date.type' = 'date',
  'projection.partition_date.format' = 'yyyy/MM/dd/HH',
  'projection.partition_date.range' = '2024/10/15/00,NOW+9HOURS',
  'projection.partition_date.interval' = '1',
  'projection.partition_date.interval.unit' = 'HOURS',
  'storage.location.template' = 's3://<S3 バケット名>/sweets_with_status/jst/${partition_date}'
);

データセット、分析、ダッシュボードの作成

データソースに Athena を選択してカスタム SQL クエリを作成します。
ドーナツの個数とステータスを取得するクエリです。

SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section

クエリモードは SPICE を選択し、「保存して公開」で分析を作成します。
QuickSight_SPICE_Incremental_Update_1

分析では日ごとのドーナツの個数と、日ごとのステータスをビジュアルで可視化します。「公開」をクリックしてダッシュボードも保存します。
QuickSight_SPICE_Incremental_Update_2

QuickSight_SPICE_Incremental_Update_8
以上で準備完了です。

===事前準備ここまで===

SPICE 増分更新の設定

データセットの詳細を開き、更新タブで「新しいスケジュールの追加」をクリックします。
QuickSight_SPICE_Incremental_Update_9

  • 増分更新
  • タイムゾーン:Asia/Tokyo (UTC+09:00)
  • 開始時刻:2024/10/16 11:20 午後(いかにブログを下書きで眠らせていたかバレてしまいますね)
  • 頻度:毎時

と設定し「増分更新を設定」をクリックします。
QuickSight_SPICE_Incremental_Update_10

増分更新の設定が開きますので設定します。今回は以下のように設定しました。

  • 日付の列:formatted_date(データセット作成時のカスタム SQL クエリで作成した日付列)
  • ウィンドウサイズ(数値):1
  • ウィンドウサイズ(単位):時間

QuickSight_SPICE_Incremental_Update_11

ちなみに、データ自身が日付列を持ってないと SPICE 増分更新はできません。以下ブログも参照ください。
https://dev.classmethod.jp/articles/quicksight-incremental-update/

「更新スケジュールの編集」に戻りますので、「保存」します。
QuickSight_SPICE_Incremental_Update_12

保存すると、最初の更新が走り始めます。

SPICE 増分更新スケジュール設定直後の更新はフル更新か、増分更新か?

ここで問題です。
さて、増分更新スケジュールを一番最初に設定したときに走るこの更新は増分更新でしょうか。それともフル更新でしょうか。
履歴を見ると更新時間は「2024/10/16 23:20」、更新の種類は「手動、編集」となっています。スケジュールを設定したり変更したりした際は「手動、編集」と表示されるようです。
QuickSight_SPICE_Incremental_Update_13

完了しました。
QuickSight_SPICE_Incremental_Update_14

QuickSight 側の更新が完了したら、Athena でクエリの履歴を確認します。
QuickSight_SPICE_Incremental_Update_15

内部的には、QuickSight が Athena で経由 SPICE に取り込むクエリを発行しています。
Athena の「最近のクエリ」タブで /* QuickSight xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx */ から始まるものが該当します。

2024/10/16 23:20 に実行された「手動、編集」のクエリに該当するクエリは Athena の履歴を開くと以下のようになっていました。

/* QuickSight d9db2f74-399d-4980-958a-70e08703c28b */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"

これは フル更新クエリ です。
増分更新クエリだと where 句で時刻範囲が指定されるのですが、この SQL 文には時刻指定範囲がありません。

A. 日本時間 JST でSPICE 増分更新をした際の増分更新の範囲を調べる

スケジュールされた増分更新が実行される(1 回目)

さて、増分更新スケジュールが走る前に S3 バケットにいくつかデータを足しておきました。増分更新が走るのを待ちます。

はい、2024/10/16 23:30 に実行されました。

QuickSight_SPICE_Incremental_Update_17

ダッシュボードの方も更新されています。
QuickSight_SPICE_Incremental_Update_18

ダッシュボードの見え方調整

一部ダッシュボードの見え方が気に入らなかったので調整します。ブログの本筋とは関係ないので飛ばして大丈夫です。

Status の折れ線グラフが日単位になっていたのでデータが増えても変わっていませんでした。そのため分単位に変えます。

formatted_date の集計を分単位に変えます。
QuickSight_SPICE_Incremental_Update_19

形式を yyyy/mm/dd hh:mm にします。
QuickSight_SPICE_Incremental_Update_20

折れ線グラフの見え方が変わりました。これで OK です。
QuickSight_SPICE_Incremental_Update_21

===ダッシュボード調整ここまで===

Athena で QuickSight から実行されたクエリを確認します。時刻で該当のクエリを確認できます。
QuickSight_SPICE_Incremental_Update_22

開くと以下のようになっていました。
QuickSight_SPICE_Incremental_Update_23

▼ 2024/10/16 23:30 実行クエリ

/* QuickSight cad73016-324c-409c-95dc-522ad5ab66f3 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1729084842045 as varchar), 1, 10) AS bigint))

クエリの最後の行を見ると、Athena は以下のような where 句で、SPICE に取り込むデータの範囲を指定しています。

WHERE "formatted_date" > from_unixtime(cast(substr(cast(1729084842045 as varchar), 1, 10) AS bigint))

from_unixtime から始まる時刻は、以下のクエリで何時か確認することができます。

select from_unixtime(cast(substr(cast(1729084842045 as varchar), 1, 10) AS bigint))

結果は 2024-10-16 13:20:42.000 となりました。
QuickSight_SPICE_Incremental_Update_24

つまり、日付列が 2024-10-16 13:20 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。
ここで、この日付は JST とか UTC とかの意味を失っていて、QuickSight は formatted_date 列の日付数字で SPICE に取り込むかどうかを判断しているという点がポイントです。

前回の更新時間との差
スケジュール設定時のフル更新時間 2024/10/16 23:20 基準
増分更新実行時間 2024/10/16 23:30
~より新しい時刻のデータを取り込む 2024-10-16 13:20 -10 時間

初回の更新時間との差を考えます。

  • JST ⇒ UTC に変換して - 9 時間
  • から「頻度」に設定した時間をマイナス
    • 「毎時」なので - 1 時間の予定だが、まだ増分更新 1 回目なので換算しない⇒ 0 時間
  • からウィンドウサイズに指定した時間をマイナス
    • 「ウィンドウサイズ 1 時間」なら - 1 時間
  • 前回の更新時間との差:10 時間

このように考えればつじつまが合います。

スケジュールされた増分更新が実行される(2 回目)

同様に二回目の増分更新も見ていきます。

▼ 2024/10/17 0:30 更新クエリ

/* QuickSight daa50094-8cec-4e74-9e32-21d09bf8a934 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1729085403149 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1729085403149 as varchar), 1, 10) AS bigint))

実行結果:2024-10-16 13:30:03.000

つまり、日付列が 2024-10-16 13:30 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

前回の更新時間との差
増分更新実行時間 2024/10/17 0:30
~より新しい時刻のデータを取り込む 2024-10-16 13:30 -11 時間

初回の更新時間との差を考えます。

  • JST ⇒ UTC に変換して - 9 時間
  • から「頻度」に設定した時間をマイナス
    • 「毎時」なので - 1 時間
  • からウィンドウサイズに指定した時間をマイナス
    • 「ウィンドウサイズ 1 時間」なら - 1 時間
  • 前回の更新時間との差:11 時間

スケジュールされた増分更新が実行される(3 回目)

三回目の増分更新も見ていきます。

▼ 2024/10/17 1:30 更新クエリ

/* QuickSight fe049a49-8eae-48c7-b8ad-ebab724e4977 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1729089002850 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1729089002850 as varchar), 1, 10) AS bigint))

実行結果:2024-10-16 14:30:02.000

つまり、日付列が 2024-10-16 14:30 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

前回の更新時間との差
増分更新実行時間 2024/10/17 1:30
~より新しい時刻のデータを取り込む 2024-10-16 14:30 -11 時間

初回の更新時間との差を考えます。

  • JST ⇒ UTC に変換して - 9 時間
  • から「頻度」に設定した時間をマイナス
    • 「毎時」なので - 1 時間
  • からウィンドウサイズに指定した時間をマイナス
    • 「ウィンドウサイズ 1 時間」なら - 1 時間
  • 前回の更新時間との差:11 時間

スケジュールされた増分更新が実行される(3 回目)

四回目の増分更新も見ていきます。

▼ 2024/10/17 2:30 更新クエリ

/* QuickSight 376abcf4-6ff2-4f36-96bc-2ffc4e237607 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1729092602768 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1729092602768 as varchar), 1, 10) AS bigint))

実行結果:2024-10-16 15:30:02.000

つまり、日付列が 2024-10-16 15:30 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

前回の更新時間との差
増分更新実行時間 2024/10/17 2:30
~より新しい時刻のデータを取り込む 2024-10-16 15:30 -11 時間

もう分かってきましたね。

A. 結果:日本時間 JST でSPICE 増分更新をした際の増分更新の範囲

結果をまとめると以下になります。

  • 日本時間 JST でSPICE 増分更新をした際の増分更新の範囲は以下
      1. JST ⇒ UTC に変換して - 9 時間
        1. から「頻度」に設定した時間をマイナス
      • 「毎日」なら - 24 時間、「毎時」なら - 1 時間、など
        1. からウィンドウサイズに指定した時間をマイナス
      • 「ウィンドウサイズ 1 時間」なら - 1 時間、「ウィンドウサイズ 12 時時」なら - 12 時間、など

▼頻度:毎日、ウィンドウサイズ:1 時間、0:30 JST に SPICE 増分更新を設定した場合のイメージ
QuickSight_SPICE_Incremental_Update_3

B. 一度 SPICE 増分更新スケジュールを削除して、日を置いて再度 SPICE 増分更新スケジュールを設定したときの挙動を調べる

増分更新ジョブは一時停止などができないため、スケジュールされた増分更新を止めるには削除するしかありません。スケジュールから「削除」します。
QuickSight_SPICE_Incremental_Update_25

~~~~~~~~~~~~~~~~~~~~
   ~~ここで数日、時が流れます~~
~~~~~~~~~~~~~~~~~~~~

数日後、再度 SPICE 増分更新の検証をしたくなった私は、また同じ設定(頻度:1 時間、ウィンドウサイズ:1 時間)で増分更新の設定を行いました。
QuickSight_SPICE_Incremental_Update_26

QuickSight_SPICE_Incremental_Update_27

QuickSight_SPICE_Incremental_Update_28

初回の増分更新が完了しました。本当の本当に一番最初に増分更新を設定した際はフル更新が走ったのですが、今回はいきなり「スケジュール済み、増分更新」となりました。
QuickSight_SPICE_Incremental_Update_29

Athena 側で増分更新クエリを確認します。
QuickSight_SPICE_Incremental_Update_30

▼ 2024/10/30 21:30 実行クエリ

/* QuickSight 765fb68c-3306-4188-ae25-e775a528360a */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1729096202907 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1729096202907 as varchar), 1, 10) AS bigint))

実行結果:2024-10-16 16:30:02.000

つまり、日付列が 2024-10-16 16:30 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

前回の更新時間との差
スケジュール削除前の最後の増分更新(~より新しい時刻のデータを取り込む) 2024-10-16 15:30 基準
増分更新実行時間 2024/10/30 21:30
~より新しい時刻のデータを取り込む 2024-10-16 16:30 14 日以上前

前回の更新時間との差を考えると、スケジュールした増分更新を削除する前、最後に実行された増分更新の 1 時間後からデータを取り込もうとしています。

増分更新スケジュールを削除する直前に行われた 2024/10/17 2:30 の更新クエリでは、日付列が 2024-10-16 15:30 より新しいデータを取得していました。おそらく頻度が 1 時間なので 1 時間間が空いたのではと予想します。

B. 結果:一度 SPICE 増分更新スケジュールを削除して、日を置いて再度 SPICE 増分更新スケジュールを設定したときの挙動

結果をまとめると以下になります。

  • 一度 SPICE 増分更新スケジュールを削除して、日を置いて再度 SPICE 増分更新スケジュールを設定すると、増分更新の設定に関わらず、前回の最後の SPICE 増分更新で取り込んだ時間から現在の時刻までのデータが全部 SPICE に取り込まれる。その後、 SPICE 増分更新が設定した頻度で開始される
    QuickSight_SPICE_Incremental_Update_6

C. SPICE 増分更新のウィンドウサイズを変更

SPICE 増分更新のウィンドウサイズを変更するとどうなるのかやってみます。まずは自動更新の結果を見ます。

まずは増分更新頻度:1 時間、ウィンドウサイズ:1 時間で走っているスケジュールされた自動増分更新を確認します。

▼ 2024/10/30 23:30 実行クエリ

/* QuickSight 9ba5e1e0-43e1-45a2-af3e-82b587d9a457 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730291440976 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730291440976 as varchar), 1, 10) AS bigint))

実行結果:2024-10-30 12:30:40.000

つまり、日付列が 2024-10-30 12:30 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

ウィンドウサイズを 1⇒12 時間に変更

ではウィンドウサイズを変更します。「今すぐ更新」からウィンドウサイズを変更します。
QuickSight_SPICE_Incremental_Update_31

「増分プロパティの設定」
QuickSight_SPICE_Incremental_Update_32

ウィンドウサイズを 12 時間にします。
QuickSight_SPICE_Incremental_Update_33

続行します。
QuickSight_SPICE_Incremental_Update_34

すると、「更新の確認」のポップアップが出て「今すぐ更新を開始してもよろしいですか?」と聞かれている裏で。ないにゃら更新が走っていることが分かりました。まだ「更新」は押下していません。
更新の種類は「手動、編集」となっています。
QuickSight_SPICE_Incremental_Update_35

ここで初めて「更新」を押下します。
QuickSight_SPICE_Incremental_Update_36

さて、履歴には更新が 2 行追加されました。裏で勝手に走った「手動、編集」と、「更新」を押下して初めて走った「手動、増分更新」の 2 行です。
QuickSight_SPICE_Incremental_Update_37

終わりました。
QuickSight_SPICE_Incremental_Update_38

Athena 側でクエリを確認していきます。まずは裏で勝手に走った「手動、編集」に該当する 2024/10/30 23:53 のクエリから見ます。
QuickSight_SPICE_Incremental_Update_39

▼ 2024/10/30 23:53 に手動で増分更新しようとしたら裏で勝手に走ったクエリ(手動、編集)

/* QuickSight 46538fed-c2d4-4a46-b4ac-1b06b5517567 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"

おや。これは where 句で時間範囲が指定されていません。フル更新です。

次に、「更新」を押下して実行した 2024/10/30 23:54 の増分更新クエリを確認します。

QuickSight_SPICE_Incremental_Update_40

▼ 2024/10/30 23:54 実行クエリ(手動、増分更新)(毎時、ウィンドウサイズ12時間)

/* QuickSight 3f021d47-b1a6-4938-bfd6-5c8c9123c569 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730256792880 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730256792880 as varchar), 1, 10) AS bigint))

実行結果:2024-10-30 02:53:12.000

つまり、日付列が 2024-10-30 02:53 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

前回の更新時間との差
前回のスケジュール増分更新(~より新しい時刻のデータを取り込む) 2024-10-30 12:30
勝手に走ったフル更新実行時間 2024/10/30 23:53
増分更新実行時間 2024/10/30 23:54
~より新しい時刻のデータを取り込む 2024-10-30 02:53

前回の更新時間との差を考えると、

    1. 増分更新実行時間 2024/10/30 23:54 JST ⇒ UTC に変換(- 9 時間)すると 2024/10/30 14:54
      1. から頻度:1 時間をマイナスするところだが、手動のため換算しない
      1. からウィンドウサイズ:12 時間をマイナスして 2024-10-30 02:53

ということになります。

ウィンドウサイズ変更後のスケジュールされた自動増分更新(1 回目)

ではこの後のスケジュールされた自動増分更新も見てみます。

▼ 2024/10/31 0:30 実行クエリ

/* QuickSight 27b55df2-7405-4004-80f1-6319b2fb7a21 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730256858675 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730256858675 as varchar), 1, 10) AS bigint))

実行結果:2024-10-30 02:54:18.000

つまり、日付列が 2024-10-30 02:54 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。
手動の増分更新で取得した時間範囲とほぼ同じです。

ウィンドウサイズ変更後のスケジュールされた自動増分更新(2 回目)

▼ 2024/10/31 1:30 実行クエリ

/* QuickSight cf7f54aa-4f9e-4f5d-8cb8-3690b0f10480 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730259040895 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730259040895 as varchar), 1, 10) AS bigint))

実行結果:2024-10-30 03:30:40.000

つまり、日付列が 2024-10-30 03:30 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

前回の更新時間との差
増分更新実行時間 2024/10/31 1:30
~より新しい時刻のデータを取り込む 2024-10-30 03:30 -22 時間

前回の更新時間との差を考えます。

  • 2024/10/31 1:30 JST ⇒ UTC に変換(- 9 時間)して 2024/10/30 16:30 UTC
  • 頻度:1 時間をマイナスして 2024/10/30 15:30
  • ウィンドウサイズ:12 時間をマイナスして 2024-10-30 03:30
  • 前回の更新時間との差:22 時間

なるほど、「今すぐ更新」からウィンドウサイズを変更した場合、スケジュールされた自動増分更新のウィンドウサイズも変更されるということですね。

ウィンドウサイズ変更後のスケジュールされた自動増分更新(3 回目)

▼ 2024/10/31 2:30 実行クエリ

/* QuickSight d3cf3077-f329-4f29-8794-6efd8625d6e7 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730262641209 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730262641209 as varchar), 1, 10) AS bigint))

実行結果:2024-10-30 04:30:41.000

つまり、日付列が 2024-10-30 04:30 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

C. 結果:SPICE 増分更新のウィンドウサイズを変更すると、まずフル更新が走り、その後 SPICE 増分更新が設定した頻度で開始される

結果をまとめると以下になります。

  • SPICE 増分更新のウィンドウサイズを変更すると、まずフル更新が走り、その後 SPICE 増分更新が設定した頻度で開始される
  • 「今すぐ更新」で SPICE 増分更新のウィンドウサイズを変更すると、既存の SPICE 増分更新スケジュールのウィンドウサイズも変更される

▼「今すぐ更新」で SPICE 増分更新のウィンドウサイズを 1⇒12 時間に変更した場合のイメージ
QuickSight_SPICE_Incremental_Update_4

D. ウィンドウサイズを変えずに SPICE 増分更新を「今すぐ更新(手動更新)」する

では、ウィンドウサイズを変えずに SPICE 増分更新を「今すぐ更新(手動更新)」するとどうなるか試します。

まずはスケジュールされた自動増分更新の結果を確認しておきます。

▼ 2024/10/31 21:40 実行クエリ(スケジュールされた自動増分更新)

/* QuickSight c9a6f918-c910-4ffc-a874-df7298d0a5c9 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730371247250 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730371247250 as varchar), 1, 10) AS bigint))

実行結果:2024-10-31 10:40:47.000

つまり、日付列が 2024-10-31 10:40 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

「今すぐ実行」でウィンドウサイズを変えずに増分更新する

では「今すぐ実行」で増分更新します。

▼ 2024/10/31 22:17 に「今すぐ実行」で増分クエリを実行する

/* QuickSight 39d68cd8-b247-4bc2-8358-f1192452143d */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730374847561 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730374847561 as varchar), 1, 10) AS bigint))

実行結果:2024-10-31 11:40:47.000

つまり、日付列が 2024-10-31 11:40 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。
この時、特に裏でフル更新が走ると言ったことはありませんでした。

「今すぐ実行」の後のスケジュールされた自動増分更新

さて、この後のスケジュールされた自動増分更新を確認します。

▼ 2024/10/31 22:40 実行クエリ

/* QuickSight 381bff2f-85da-4967-a3a0-71baba06007d */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1730377042192 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1730377042192 as varchar), 1, 10) AS bigint))

実行結果:2024-10-31 12:17:22.000

つまり、日付列が 2024-10-31 12:17 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。
「今すぐ実行」で実行した増分更新の時間より新しいデータを取り込もうとしていることが分かりました。

D. 結果:ウィンドウサイズを変えずに SPICE 増分更新を「今すぐ更新(手動更新)」すると、前回の更新時点から現時点までのレコードが取り込まれる

結果をまとめると以下になります。

  • ウィンドウサイズを変えずに SPICE 増分更新を「今すぐ更新(手動更新)」すると、前回の更新時点から現時点までのレコードが取り込まれる
    • つまり、SPICE 増分更新のウィンドウサイズを変更しなければ、フル更新は走らず、SPICE 増分更新で設定した通りにスケジュールされる
      QuickSight_SPICE_Incremental_Update_5

E. SPICE 増分更新のスケジュールの頻度を変更する

では最後に SPICE 増分更新のスケジュールの頻度を変更してみます。

「更新スケジュールの編集」で頻度を変える際は以下のように未来日付を入力するよう注意されます。
QuickSight_SPICE_Incremental_Update_41

ちなみに SPICE 増分更新では以下の頻度が選べます。

  • 15 分ごと
  • 30 分ごと
  • 毎時
  • 毎日
  • 毎週
  • 毎月

他の増分更新の設定はそのままで続行します。
QuickSight_SPICE_Incremental_Update_42

開始日付を未来日付にして保存します。
QuickSight_SPICE_Incremental_Update_43

保存できました。増分更新が走るのを待ちます。
QuickSight_SPICE_Incremental_Update_44

30 分毎に増分更新が実行されているのが分かりました。裏でフル更新が走ることはないようです。
QuickSight_SPICE_Incremental_Update_45

頻度変更前のクエリの実行結果

まずは頻度変更前のクエリの実行結果を確認します。

▼ 2024/11/10 19:35 実行クエリ(頻度:1 時間)

/* QuickSight 8da46374-3f89-4ca3-9616-0c4586255c34 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1731227741599 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1731227741599 as varchar), 1, 10) AS bigint))

実行結果:2024-11-10 08:35:41.000

つまり、日付列が 2024-11-10 08:35 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

頻度変更後のスケジュールされた自動増分更新(1 回目)

▼ 2024/11/10 20:15 実行クエリ(スケジュール済み、増分更新)

/* QuickSight 7132442a-42bc-4cc9-a912-c78137a45358 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1731231341217 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1731231341217 as varchar), 1, 10) AS bigint))

実行結果:2024-11-10 09:35:41.000

つまり、日付列が 2024-11-10 09:35 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

    1. 2024/11/10 20:15JST⇒2024/11/10 11:15UTC
    1. 2024/11/10 11:15⇒頻度30分⇒2024/11/10 10:45
    1. 2024/11/10 10:45⇒ウィンドウサイズ1時間⇒2024/11/10 09:45

おや。計算があいません。ちょっと理由は分からなかったのですが、前回更新分から漏れることはないので一旦このまま次の更新クエリも確認します。

頻度変更後のスケジュールされた自動増分更新(2 回目)

▼ 2024/11/10 20:45 JST 実行クエリ

/* QuickSight 67ab33be-7ff4-43e3-94bb-7252a23058c4 */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1731233723708 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1731233723708 as varchar), 1, 10) AS bigint))

実行結果:2024-11-10 10:15:23.000

つまり、日付列が 2024-11-10 10:15 より新しいデータを取得するよ、という意味の増分更新クエリであることが分かります。

    1. 2024/11/10 20:45 JST⇒2024/11/10 11:45 UTC
    1. 2024/11/10 11:45⇒頻度30分⇒2024/11/10 11:15
    1. 2024/11/10 11:15⇒ウィンドウサイズ1時間⇒2024/11/10 10:15

OK!計算通りです。

頻度変更後のスケジュールされた自動増分更新(3 回目)

▼ 2024/11/10 21:15 JST 実行クエリ

/* QuickSight a1e1d96b-668b-4da2-a904-ad78384e30ba */
SELECT "formatted_date", "department", "section", "status", "donut"
FROM (SELECT 
    date_parse(partition_date, '%Y/%m/%d/%H') AS formatted_date,
    department,
    section,
    status,
    donut
FROM 
    spiceincrementalupdatedb.sweets_with_status
GROUP BY 
    partition_date,
    department,
    section,
    status,
    donut
ORDER BY 
    formatted_date,
    department,
    section) AS "sweets_with_status_donut"
WHERE "formatted_date" > from_unixtime(cast(substr(cast(1731235523686 as varchar), 1, 10) AS bigint))

時間確認

select from_unixtime(cast(substr(cast(1731235523686 as varchar), 1, 10) AS bigint))

実行結果:2024-11-10 10:45:23.000

OK ですね。

E. 結果:SPICE 増分更新のスケジュールの頻度のみを変更する際は必ず未来日付を指定する必要があり、変更保存後もフル更新は走らない

結果をまとめると以下になります。

  • E. SPICE 増分更新のスケジュールの頻度のみを変更する際は必ず未来日付を指定する必要があり、変更保存後もフル更新は走らない
    • 指定した未来日付から設定した頻度でスケジュール実行される
    • 頻度を変更した 1 回目の SPICE 増分更新は、前回の取り込み範囲の後から漏れなく取り込むよう範囲指定される
      QuickSight_SPICE_Incremental_Update_16

おわりに

SPICE 増分更新は奥が深くて大変でした。ある程度腹落ちするまで検証でき図示もできたと思いますが、やはり複雑かなと思いますので、不明点があればお問い合わせください。増分更新は重複が発生しないデータで利用した方が良いと思います。

検証にも時間がかかりまして、スクショやクエリの日付からいかに私がこのブログを書くのに時間がかかってしまったかおわかりいただけたかと思います。一旦書き終われてよかったです。

本記事への質問やご要望については画面下部のお問い合わせ「DevelopersIO について」からご連絡ください。記事に関してお問い合わせいただけます。

参考

https://dev.classmethod.jp/articles/quicksight-incremental-update/

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/partition-projection-dynamic-id-partitioning.html

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.