Spannerのクエリオプティマイザに苦しんだ話

本稿はJCB Advent Calendar 2023の12月22日の記事です。

はじめに

DXテックG アプリチームの森口です。
データの入れ替え対応を実施した際、クエリオプティマイザに苦しんだので、その使用上の注意点を記事にしてみました。

なにが起きたのか

Spannerに登録されてあるデータの入れ替え作業のため、既にあるツールを流用できるという理由からレコード更新(Update)でデータを更新するのではなく、新たにテーブルを作成し、一括で全レコード追加(Insert)を実施しました。
その結果、該当のテーブルよりデータを取得している処理で以前の状態よりも大幅に待ち時間が発生し、設定していたタイムアウト値を超えてしまいエラーになりました。

原因

Googleサポートに問い合わせた結果、全てのレコードがinsertされるのを待たずにクエリオプティマイザが情報を収集したため、結合の順序が変わってしまい、レコード数の多いテーブルをフルスキャンするようになってしまった可能性があるとの回答をいただきました。
改めて当該クエリのクエリ実行計画を確認してみると、確かに従来のクエリ実行とは異なり、レコード数が多いテーブルをフルスキャンするようになっていました。 今回は幸い外部影響が出るものではなかった為、再度クエリオプティマイザによる最適化がされるのを待ち、従来通りのクエリ実行計画になっているのを確認し、対応完了としました。
※下の図でparaccount_numberは1対多の関係で、レコード数はaccount_numberの方が多いです。

問題が発生した時のクエリ実行計画

本来あるべきクエリ実行計画

今回の事象を踏まえて

結合順が変わることによって、処理時間が変わるものに対しては、FORCE_JOIN_ORDERを使い、結合の順序を強制するように対応するようにしています。

SELECT *
FROM Singers AS s JOIN@{FORCE_JOIN_ORDER=TRUE} Albums AS a
ON s.SingerId = a.Singerid;

詳細は公式ページをご覧下さい。

また、新たにDBから取得処理を実装する際など、日頃からクエリ実行計画を見るようにしています。

終わりに

今回の事象は、外部影響が発生するものでありませんでしたが、今回のことを教訓に気をつけていきたいと思います。
最後になりますが、JCBでは我々と一緒に働きたいという人材を募集しています。 詳しい募集要項等については採用ページをご覧下さい。

詳しい募集要項等については採用ページをご覧下さい。


本文および図表中では、「™」、「®」を明記しておりません。 記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。

©JCB Co., Ltd. 20︎21