👻

AIエージェントでSQLクエリに関する性能問題の調査を少しでも楽にしたい

に公開

はじめに

どうもこんにちは。間瀬です。
今回は「AIエージェントでSQLクエリに関する性能問題の調査を少しでも楽にしたい」というテーマで記事をお届けしたいと思います。

性能問題とわたし

システム運用や性能試験をしていて、「性能が出ない」という問題に直面したことはありませんか?私は過去そのような経験が何度もあり、原因を調査するのにとても苦労していた経験があります。

現在ではクラウドサービスやオープンソースが充実してきており、以前と比べて比較的簡単に原因調査ができるようになってきたと実感していますが、依然として調査には時間がかかったり、アプリケーションで利用しているプログラミング言語やアプリケーションが依存するDB等の周辺システムに関する専門知識が必要になったりすることがあります。
あくまでも個人の感覚ですが、振り返ってみると性能問題の調査にかかった大半の時間はDBクエリ周りの調査に費やされていたと感じています。

そこでAIエージェントを使ってSQLクエリに関する性能問題の調査を少しでも楽にしたいと思い実践してみたので紹介したいと思います。

本記事の位置付け

本記事の内容はこれまでに私が公開している2つの記事の続編的な位置付けになります。

  • AIエージェントで障害対応とかにおける調査を少しでも楽にしたい
    Google ADKを使用してアプリケーションの性能問題やエラーをOpenTelemetryを通して取得したトレースやログ、ソースコードから調査を行い、原因調査から改善方法の提案までできるか検証した内容を記事にしています。
    https://zenn.dev/makocchan/articles/perf_investigating_agent

  • GoアプリケーションからDBにおけるSQLクエリの処理まで一気通貫で計装する(GORM+sqlcommenter)
    Goで実装したアプリケーションからRDBMSに対して発行するSQLクエリに関する処理まで一気通貫でOpenTelemetryで計装する方法を紹介した記事です。
    https://zenn.dev/makocchan/articles/otel_sql_agent

今回紹介する内容のシステム構成

今回は以下のような構成で検証を行なっていきます。
以前の記事で紹介したAIエージェントの検証構成からほとんど変化はなく、AIエージェントのインプットとなるコンテキストとして、DBのモデルやクエリに関連する情報を追加しています。

architecture

アプリケーション

  • Goで実装したアプリケーションで、処理の中でDBとなるCloudSQLに対してSQLクエリを発行している。
  • OpenTelemetryによってトレースを取得し、ログにもこれらトレース情報を付与してリンクさせている。
  • SQLクエリにも sqlcommenter を使用して上記のトレース情報をコメントとして付与している。
  • アプリケーションが出力するトレースやログはそれぞれCloud TraceとCloud Loggingをバックエンドとしている。

データベース(Cloud SQL for MySQL)

  • Cloud SQLのパフォーマンス分析ツールとして提供されているQuery Insightsを利用しており、本ツールがSQLクエリの処理に関するトレース情報をCloud Traceへ連携している。
  • データベース上のテーブルやインデックスはORM(今回はGORM)を使用して構築しているため、アプリケーションのソースコードと同梱させている。

Vertex AI Vector Search & Firestore

  • DBのモデル情報を含むソースコードを極力ファンクション単位に分割した上でエンべディングして Vertex AI Vector Search に登録している。
  • 上記でベクトル検索されたデータと実際のソースコードを紐づけるためのマッピングデータをFirestoreに登録している。

AIエージェント

  • Google ADKで実装している。
  • ルートエージェントが複数のサブエージェントを呼び出せる構成とし、サブエージェントはトレース分析、ログ分析、ソースコード分析とそれぞれ与えられたツールを使用してタスクを実施する。
  • モデルはいずれもGemini 2.5 Proを使用している。

SQLクエリの調査をさせるためにAIエージェントに与えるコンテキスト

SQLクエリを処理する実行計画やスキャンにかかった時間が分かる情報

データベースがSQLクエリによる処理を行うときにどのようにスキャンを行ったのか、そのスキャンにどれくらい時間がかかったのか等が分かる情報をAIエージェントに与えます。

Query Insightsを利用することでこれら情報をCloud Traceのデータとして連携することが可能であること、更にsqlcommenterによってアプリケーションのトレースと紐づけることができるようになっているため、これらをAIエージェントに与えることでアプリケーション内部の処理からDBにおけるクエリ処理まで一気通貫で分析することが可能になります。

具体的は以下のようなトレース情報をAIエージェントに与えることになります。

trace_data

アプリケーションが発行しているSQLクエリまたは操作内容

上記の情報からボトルネックとなっている処理やスキャンを分析することは可能ですが、原因を特定して改善策を挙げられるために実際に発行されているSQLクエリもAIエージェントに与えます。
今回の構成では以下3つの情報からSQLクエリを参照できるようにしています。

  • エンべディングデータから参照できるアプリケーションのソースコード
    // ORMであるGORMを経由してデータベースに対して操作を行なっている
	result := h.db.WithContext(ctx).
		Preload("User").
		Preload("OrderItems").
		Preload("OrderItems.Product").
		Limit(100).
		Find(&orders)
  • Cloud Traceから参照できるSpanに含まれる属性
    gorm_span

  • Cloud loggingから参照できるログ

GORMのOpenTelemetryプラグインによってログを出力している。 ※一部項目を割愛・簡略化しています。
{"file":"/app/log/gormLogger.go:60", "latency":"8.806560301s", "rows":50, "slow_log":"SLOW SQL >= 200ms", "sql":"SELECT products.id as product_id・・・"}

データベースに定義されているテーブル、カラムやインデックス

SQLクエリと同様に原因を特定して改善策を挙げられるためにこれらの情報もAIエージェントに与えます。
今回の構成では、以下のようにアプリケーションでORM(GORM)を使ってテーブルやインデックスを構成しているため、これらの情報もアプリケーションのソースコードから取得することが可能となっています。

※仮にORMを使っていなくてもDDLファイル等を同様にエンべディングしてデータストアに登録することで、AIエージェントにインプット情報として与えることは可能だと思います。

// アプリケーションのソースコードの一部として定義されたテーブルとカラム、インデックスの定義
type Review struct {
	ID         uint           `gorm:"primarykey" json:"id"`
	CreatedAt  time.Time      `json:"created_at"`
	UpdatedAt  time.Time      `json:"updated_at"`
	DeletedAt  gorm.DeletedAt `json:"-"`
	UserID     uint           `gorm:"not null" json:"user_id"`
	User       User           `gorm:"foreignKey:UserID" json:"user"`
	ProductID  uint           `gorm:"not null" json:"product_id"`
	Product    Product        `gorm:"foreignKey:ProductID" json:"product"`
	Rating     int            `gorm:"not null" json:"rating"`
	Comment    string         `gorm:"type:text" json:"comment"`
	ReviewDate time.Time      `gorm:"not null" json:"review_date"`
}

実践してみる

上記で紹介したシステム構成とコンテキストを準備した上でAIエージェントにSQLクエリの調査をさせてみます。
今回はインデックスが設定されていないカラムをキーにJOINを行ってあえてクエリの処理に時間がかかるように実装しています。

  1. ユーザーからの調査依頼
    user_instruction

  2. トレース分析エージェントによる回答
    トレース情報に関連するサービスの全体像やそれぞれの処理時間、ボトルネックを分析してくれています。
    trace_agent
    ~スクショが収まらないので一部簡略~
    trace_agent2

  3. ソースコード分析エージェントによる回答
    トレース情報エージェントから連携された情報から関連するソースコードを検索して、ソースコード上の問題点を指摘してくれています。
    その上で性能改善に向けた改善策を複数提示してくれています。
    code_agent
    code_agent2
    code_agent3

今回はログ分析エージェントに連携されることなくボトルネックの特定と改善策の提示まで実施してくれました。スクリーンショットは省略しますが、「念のためログも分析して改善策が妥当か判断して」と依頼したところ、ログを確認した上で回答してくれました。

また、SQLクエリの処理以外にも改善すべき点があるか調査を依頼したところ、以下のようにアプリケーションコード内の問題を指摘してくれました。
code_agent4

以上より今回の例では調査の難易度は低いですが、クエリだけでなくアプリケーション全体を柔軟に調査することができるということが分かりました。

さいごに

今回はアプリケーション内部の処理からDBクエリまで一気通貫で計装されているシステムに対し、AIエージェントを使ってSQLクエリの調査と原因特定、改善策の提案までさせてみました。

改めてアプリケーションやデータベースにおける処理を可視化すればするほど人手による調査が捗ると同様に、AIエージェントによる調査精度も高まるということを実感したことから、業務においても効率的な調査を行えるよう、アプリケーションやデータベースにおける可視化を積極的に推進していきたいと思います。

記事を閲覧いただきありがとうございました。

Discussion