複数のスレッド間でセッションや接続を再利用する場合の考慮点¶
Snowflakeドライバーはステートフル接続を使用します。スレッド間で同じセッションや接続を再利用することには、複数の欠点があります。例えば、セッションが初期化されると、既定のデータベース、スキーマ、ロール、パラメーターのセットで始まります。接続はセッションの開始と終了を行い、セッションと接続の間に1対1の関係を確立します。以下のセクションでは、並行スレッド間で接続を再利用することによる一般的な影響について説明します。
複数のスレッドでセッションや接続を再利用する効果¶
ドライバーユーザーは、マルチスレッドのアプリケーションを作成することがよくあります。スレッドごとに別々のセッションや接続を作成するのではなく、異なるスレッドでセッションや接続を再利用することで、オーバーヘッドを節約しようとするかもしれません。そうすることで、以下のような好ましくない動作を引き起こす可能性があることに注意してください。
セッション状態
セッションは現在のデータベース、スキーマ、ロールを追跡します。あるスレッドが(USE DATABASE のように)これらの値を変更すると、他のスレッドが影響を受ける可能性があります。同じテーブルを持つ別のスキーマに変更すると、スレッドが誤って間違ったテーブルを変更する可能性があるため、この影響は特に重要です。さらに、1つのセッションで接続パラメーターや構成パラメーターを変更すると、そのセッションを使用するすべてのスレッドに影響します。
トランザクションの状態
トランザクションは1つのセッションで始まるかもしれません。複数のスレッドがそのセッションにアクセスすると、それぞれのスレッドが同じトランザクションのデータを変更する可能性があります。そのため、トランザクションがコミットされたりロールバックされたりすると、データが誤って永続化されたり失われたりする可能性があります。
シーケンスカウンター
ドライバーはリクエストを再試行するためにシーケンスカウンターを使用します。シーケンスカウンタはセッションに対してグローバルなので、異なるスレッドでセッションを再利用すると、グローバルシーケンスカウンタが不注意に変更され、リクエストを再試行するときに予測できない動作になる可能性があります。
クエリコンテキストキャッシュ
パフォーマンスを向上させるために、セッションはいくつかの内部情報をドライバー固有または内部キャッシュに記録します。キャッシュはクエリごとに更新されるため、セッション内で複数のクエリを同時に実行するとデータが破損する可能性があります。
最後のクエリ ID
接続は最後のクエリ ID を記録しており、それを検索して使用することができます。2つのクエリが異なるスレッドで並列に実行される場合、競合条件が最後のクエリ ID のセットに影響する可能性があります。
Snowflake推奨事項¶
可能な限り接続プールを使用してください。
スレッド間で接続を再利用して頻繁な認証を避ける場合は、接続プールの使用を検討すべきです。接続プールを使うことで、認証リクエストの数を減らすことができます。なぜなら、セッションは終了時に閉じられるのではなく、次の機会に使えるようにプールに戻されるだけだからです。接続プールを使用する場合でも、アプリケーションは、特定のクエリや現在のデータベースにのみ影響するパラメーターを変更またはリセットしないように注意する必要があります。また、アプリケーションは、接続プールに接続を返す前に、アクティブなトランザクションをコミットまたは中止する責任があります。
非同期クエリは慎重に使用してください。
1つの接続で複数の非同期クエリを同時に開始したり、非同期クエリの実行中に同期クエリを開始したりすると、競合状態が発生し、予測できない結果が発生する可能性があります。
認証コードの最適化を追加します。
特定のドライバーは、認証パフォーマンスを向上させるために使用できる、以下の最適化の一部またはすべてをサポートしています。
SSO トークン・キャッシュ
MFA トークン・キャッシュ
TOML 構成ファイルのトークン
カスタムトークンアクセサ
ドライバーがどのオプションをサポートしているかは、ドライバーのドキュメントを確認してください。
クエリコンテキストのキャッシュを無効にします。
複数のスレッドでセッションと接続を再利用することに関連するすべての問題を認識しているが、それでも使用したい場合、Snowflakeは接続定義で:codenowrap:
DisableQueryContextCache
パラメーターを:codenowrap:false
にセットしてクエリキャッシュを無効にすることを推奨します。