AWS Athena API利用時にQUEUEDステータスが数十秒も引っかかることがある

# 引っかかった話
AWS Athena API(AWS SDK for JavaScript)を呼び出してるLambda関数で**本当にたまにタイムアウトによるエラーが発生**されました。
Lambda関数で設定して置いたタイムアウト時間は40秒で短い時間でしたが、平均2秒±1ぐらいのクエリ時間がたまに40秒を超えるのはおかしいでした。
Athenaの対象データ(S3 Objects)がどんどん増えてAhtenaのクエリが比較的に重くなることはありえますが、速度改善のためパーティショニングも真面目にしているクエリに40秒のタイムアウトに引っかかったのはQuery Running Time (RUNNING)とは違う原因でしょう。
（API呼び出しの前後に時間が秒以上かかるところもありませんでした）
また、AthenaにもAPIごとに 「1 秒あたりのデフォルトの呼び出し数」と 「バーストキャパシティー」のクォータがありますが、これに引っかかったら明確にFAILEDで返してくれるのでこの原因じゃないでした。

もっと確認した結果、**たまにQuery Queuing Time(QUEUED)が何十秒も掛かってた**ことがその原因でした。

# QUEUEDステータスとは
QUEUEDステータスはクエリがサービスに提出されたことを示し、クエリがリソースを待ってキューに並んでいた時間(Query Queuing Time)で、Athenaはリソースを利用できる時点ですぐクエリを実行します。
つまり、このステータスは正常な状態で、Query Running Time (RUNNING)とは違います。
Athenaは最近までキューにあるクエリを「RUNNING」として表示してましたが、新しくメトリクスが追加されたそうです。
AWSから回答をもらったそうな[stackoverflowの回答を見ると](https://stackoverflow.com/questions/59063219/querying-athena-from-lambda-function-queued-state)
> Take a look on Athena hook in Apache Airflow. 
> Athena has final states (SUCCEEDED, FAILED and CANCELLED) and intermediate states - RUNNING and QUEUED. 
> QUEUED is a normal state for a query before it got stared.
> ...
> As part of the deployment of more granular metrics, Athena now includes a QUEUED status for queries. 
> This status indicates that an Athena query is waiting for resources to be allocated for processing. 
> Query flow is roughly: 
>  `SUBMITTED -> QUEUED -> RUNNING -> COMPLETED/FAILED`

# 試してみる
以下の通りタイムアウトを長くして何回もAPIでクエリを投げて、どのぐらいの頻度で長いQuery Queuing Timeが発生されるか見た結果、意外と頻繁に短いQuery Queuing Timeが発生され、激しい連続クエリを投げた場合は長いQuery Queuing Time時間がたまに発生されますね。
スキャンデータは176KBで2つの2種類のQuery内容をそれぞれ繰り替えながら実行しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108364/b0d20e03-af34-3a37-85d8-5310b17a03be.png)

### API呼び出しLambda関数

```test.js
...
(function loop() {
  if (time < 180) {
    athena.getQueryExecution(params, (err, data) => {
      console.log('Status : ' , data.QueryExecution.Status.State);
      if (data.QueryExecution.Status.State == 'SUCCEEDED'){
        resolve(queryExecutionId);
      } else {
        if (data.QueryExecution.Status.State == 'FAILED') {
          console.error(err, err.stack);
        }
        const startMsec = new Date();
        while (new Date() - startMsec < 1000);
        time+=1;
        loop();
      }
    });
  } else {
    reject('408 Request Timeout');
    return false;
  }
}())
...
```

### 動作テスト① Lambda関数を連続で3回連続実行する
|  番目  |  Query Queuing Time(sec)  | トータル処理実行時間(sec) |
| ---- | ---- | ---- |
|  1  |  1  | 4  |
|  2  |  1  | 2  |
|  3  |  **16**  | 21  |

### 動作テスト② Lambda関数を連続で4回連続実行する
|  番目  |  Query Queuing Time(sec)  | トータル処理実行時間(sec) |
| ---- | ---- | ---- |
|  1  |  1  | 3  |
|  2  |  1  | 4  |
|  3  |  1  | 4  |
|  4  |  1  | 3  |

### 動作テスト③ Lambda関数を連続で6回連続実行する
|  番目  |  Query Queuing Time(sec)  | トータル処理実行時間(sec) |
| ---- | ---- | ---- |
|  1  |  1  | 3  |
|  2  |  1  | 3  |
|  3  |  1  | 5  |
|  4  |  0  | 1  |
|  5  |  1  | 2  |
|  6  |  1  | 4  |

### 動作テスト④ Lambda関数を連続で10回連続実行する
|  番目  |  Query Queuing Time(sec)  | トータル処理実行時間(sec) |
| ---- | ---- | ---- |
|  1  |  1  | 3  |
|  2  |  1  | 2  |
|  3  |  1  | 3  |
|  4  |  1  | 2  |
|  5  |  1  | 3  |
|  6  |  1  | 2  |
|  7  |  0  | 1  |
|  8  |  1  | 3  |
|  9  |  0  | 1  |
|  10  |  1  | 2  |

### 動作テスト⑤ 長いQuery Queuing Timeが発生されるまで連続実行
|  番目  |  アクション  |  5秒以上のQuery Queuing Time(sec)
| ---- | ---- | ---- |
|  1  |  10回連続  |  x  |
|  2  |  10回連続  |  **5秒、7秒が一回ずつ発生**  |
|  3  |  10回連続  |  x  |
|  4  |  10回連続  |  x |
|  5  |  20回連続  | **9秒、10秒、14秒、23秒、24秒、38秒、50秒が一回ずつ発生**  |

#最後に
自分は今回の対応で単純にタイムアウト時間を長く設定して長くなるケースを許して置きましたが、
クエリの結果を長く待てない利用ケースでしたら、サポートセンターに問い合わせして見た方が良さそうです。
GlueにもAthenaにもクォータがありますが正直にどのクォータに引っかかってQUEUEDになってしまうのか自分の中では不明で、
Query Queuing Timeが長くなるケースを避ける方法を引き続き調べて見るつもりです。
その方法をご存知な方はぜひコメントお願いいたします！

※ 関連リンク
https://aws.amazon.com/about-aws/whats-new/2019/11/amazon-athena-adds-four-new-query-related-metrics/?nc1=h_lshttps://docs.aws.amazon.com/ja_jp/athena/latest/ug/service-limits.htmlhttps://stackoverflow.com/questions/57170330/athena-getqueryexecution-returns-a-status-of-running-for-1-minute-even-thoughhttps://stackoverflow.com/questions/57145967/aws-athena-concurrency-limits-number-of-submitted-queries-vs-number-of-runninghttps://prestosql.io/docs/current/connector/hive.html#aws-glue-catalog-configuration-properties