対話型AI活用術:ViewCreator SQLビルダ アシスタントによる既存SQLのパフォーマンス改善

はじめに

対話型AI活用術:ViewCreator SQLビルダ アシスタントによるSQL開発の効率化では、ViewCreator SQLビルダ アシスタントを活用して、SQLを作成あるいは修正する方法(例)についてご紹介しました。

「ViewCreator SQLビルダ アシスタント」は、SQLに関する生成AIです。SQLを作成するイメージが強いかもしれませんが、改善する用途にも有効です。
本記事では、実行に時間がかかるSQLの改善に「ViewCreator SQLビルダ アシスタント」をどのように活用するのかを、具体的なレシピを交えて見ていきます。

前提条件

以下のガイドを参考に、環境設定を行ってください。

intra-mart Accel Platform ViewCreator 管理者操作ガイド - ViewCreator SQLビルダ アシスタント によるSQL生成

レシピ

対話型AI活用術:ViewCreator SQLビルダ アシスタントによるSQL開発の効率化」の最後で、以下のようなプロンプトをご紹介しました。

所属組織別のユーザ一覧を作ってください。一覧には所属組織の直近の親組織名とユーザの役職名も含めてください。
各テーブルでロケールや期間を管理している場合は、日本語のみ取得、現在有効な期間のみを参照してください。
以下のテーブルを利用できると思います。
imm_user, imm_department, imm_department_ath, imm_department_inc_ath, imm_department_post_ath, imm_company_post

実際にやってみたところ、以下のSQLが生成されました。(1例です)

SELECT
    u.user_cd AS user_cd,
    u.user_name AS user_name,
    d.department_name AS department_name,
    dp.post_name AS post_name,
    p.parent_department_cd AS parent_department_cd,
    parent_d.department_name AS parent_department_name
FROM
    imm_user u
INNER JOIN
    imm_department_ath da ON u.user_cd = da.user_cd
INNER JOIN
    imm_department d ON da.company_cd = d.company_cd
    AND da.department_set_cd = d.department_set_cd
    AND da.department_cd = d.department_cd
LEFT JOIN
    imm_department_post_ath dpa ON da.user_cd = dpa.user_cd
    AND da.company_cd = dpa.company_cd
    AND da.department_set_cd = dpa.department_set_cd
    AND da.department_cd = dpa.department_cd
LEFT JOIN
    imm_company_post dp ON dpa.post_cd = dp.post_cd
    AND dpa.company_cd = dp.company_cd
INNER JOIN
    imm_department_inc_ath p ON d.company_cd = p.company_cd
    AND d.department_set_cd = p.department_set_cd
    AND d.department_cd = p.department_cd
INNER JOIN
    imm_department parent_d ON p.company_cd = parent_d.company_cd
    AND p.department_set_cd = parent_d.department_set_cd
    AND p.parent_department_cd = parent_d.department_cd
WHERE
    u.locale_id = 'ja'
    AND d.locale_id = 'ja'
    AND dp.locale_id = 'ja'
    AND parent_d.locale_id = 'ja'
    AND u.start_date <= CURRENT_TIMESTAMP
    AND u.end_date > CURRENT_TIMESTAMP
    AND da.start_date <= CURRENT_TIMESTAMP
    AND da.end_date > CURRENT_TIMESTAMP
    AND d.start_date <= CURRENT_TIMESTAMP
    AND d.end_date > CURRENT_TIMESTAMP
    AND dpa.start_date <= CURRENT_TIMESTAMP
    AND dpa.end_date > CURRENT_TIMESTAMP
    AND p.start_date <= CURRENT_TIMESTAMP
    AND p.end_date > CURRENT_TIMESTAMP
    AND p.delete_flag = '0'
    AND parent_d.start_date <= CURRENT_TIMESTAMP
    AND parent_d.end_date > CURRENT_TIMESTAMP
ORDER BY u.user_cd, d.department_name;

構文的には正しく、実行もできます。

しかし、時間が経ってこのSQLを本番環境で運用し始めると、「実行時間が長い」という報告が上がってくることがあるかもしれません。本当にこのSQLは最適な書き方だったのでしょうか?

この CookBook では、生成AIの支援を受けながら作成済みのSQLを改善していく過程の例をご紹介します。

ステップ1:問題点の指摘を依頼する

生成AIから提供されたSQLが本当に最適か、確認してみましょう。
SQLを示しつつ、以下のように質問してみます。

以下のSQLの問題点を指摘してください

cookbook272636_03

アシスタントからの回答は以下でした。
ViewCreator SQLビルダ アシスタント は、利用可能なテーブル定義を確認できるため、delete_flag や locale_id などのカラムについて実際どういう定義になっているかを確認しながらアドバイスが可能です。

cookbook272636_04

このSQLの問題点を指摘させていただきます。

主な問題点
1. 削除フラグの条件が不完全
複数のテーブルで delete_flag = '0' の条件が欠けています:

imm_user の delete_flag チェックがない
imm_department_ath の delete_flag チェックがない
imm_department の delete_flag チェックがない
imm_department_post_ath の delete_flag チェックがない
imm_company_post の delete_flag チェックがない
imm_department_inc_ath の delete_flag チェックがない(p.delete_flag = '0' のみ存在)
parent_d の delete_flag チェックがない
論理削除されたレコードが結果に含まれる可能性があります。

2. LEFT JOINの後にINNER JOINの条件がある

LEFT JOIN imm_company_post dp ON ...
の直後に、WHERE句で dp.locale_id = 'ja' という条件を指定しています。LEFT JOINの後のWHERE句の条件は、事実上INNER JOINと同じ動作になります。LEFT JOINの意図が不明確です。

3. department_set_cdの条件が不足
imm_company_post テーブルへのJOIN条件に department_set_cd がありません:


LEFT JOIN imm_company_post dp ON dpa.post_cd = dp.post_cd
AND dpa.company_cd = dp.company_cd
-- ← department_set_cd の条件が欠けている
4. locale_idの条件の重複

WHERE
...
AND parent_d.locale_id = 'ja'
AND parent_d.locale_id = 'ja'  -- ← 重複している
5. 有効期間の条件が不統一
u.end_date > CURRENT_TIMESTAMP (期間終了日が現在より未来)
d.end_date >= CURRENT_TIMESTAMP (期間終了日が現在以上)
一般的には >= を使用して「終了日時点で有効」とするべきです。

6. 親組織の階層レベル条件がない
imm_department_inc_ath に対して、直近の親組織(depth = 1)を取得するのか、すべての祖先組織を取得するのかが不明確です。複数の階層レベルのデータが取得される可能性があります。

7. 主所属フラグの条件がない
imm_department_ath に department_main フラグがあります。主所属のみを対象とするなら da.department_main = '1' の条件が必要です。

修正例(改善版)

SELECT
u.user_cd AS user_cd,
u.user_name AS user_name,
d.department_name AS department_name,
dp.post_name AS post_name,
p.parent_department_cd AS parent_department_cd,
parent_d.department_name AS parent_department_name
FROM
imm_user u
INNER JOIN imm_department_ath da
  ON u.user_cd = da.user_cd
  AND da.delete_flag = '0'
INNER JOIN imm_department d
  ON da.company_cd = d.company_cd
  AND da.department_set_cd = d.department_set_cd
  AND da.department_cd = d.department_cd
  AND d.delete_flag = '0'
LEFT JOIN imm_department_post_ath dpa
  ON da.user_cd = dpa.user_cd
  AND da.company_cd = dpa.company_cd
  AND da.department_set_cd = dpa.department_set_cd
  AND da.department_cd = dpa.department_cd
  AND dpa.delete_flag = '0'
LEFT JOIN imm_company_post dp
  ON dpa.post_cd = dp.post_cd
  AND dpa.company_cd = dp.company_cd
  AND dpa.department_set_cd = dp.department_set_cd
  AND dp.delete_flag = '0'
  AND dp.locale_id = 'ja'
INNER JOIN imm_department_inc_ath p
  ON d.company_cd = p.company_cd
  AND d.department_set_cd = p.department_set_cd
  AND d.department_cd = p.department_cd
  AND p.depth = 1
  AND p.delete_flag = '0'
INNER JOIN imm_department parent_d
  ON p.company_cd = parent_d.company_cd
  AND p.department_set_cd = parent_d.department_set_cd
  AND p.parent_department_cd = parent_d.department_cd
  AND parent_d.delete_flag = '0'
  AND parent_d.locale_id = 'ja'
WHERE
u.locale_id = 'ja'
AND u.delete_flag = '0'
AND d.locale_id = 'ja'
AND u.start_date <= CURRENT_TIMESTAMP
AND u.end_date >= CURRENT_TIMESTAMP
AND da.start_date <= CURRENT_TIMESTAMP
AND da.end_date >= CURRENT_TIMESTAMP
AND d.start_date <= CURRENT_TIMESTAMP
AND d.end_date >= CURRENT_TIMESTAMP
AND dpa.start_date <= CURRENT_TIMESTAMP
AND dpa.end_date >= CURRENT_TIMESTAMP
AND p.start_date <= CURRENT_TIMESTAMP
AND p.end_date >= CURRENT_TIMESTAMP
AND parent_d.start_date <= CURRENT_TIMESTAMP
AND parent_d.end_date >= CURRENT_TIMESTAMP
ORDER BY u.user_cd, d.department_name;
主な修正点:

すべてのテーブルに delete_flag = '0' を追加
imm_company_post への条件に department_set_cd を追加
imm_department_inc_ath に depth = 1 で直近の親組織のみを取得
JOIN条件にWHERE条件を移行して可読性を改善
有効期間の条件を >= に統一
  1. の指摘は、論理削除フラグが条件に含まれていないという指摘で、最初に指示した内容から鑑みると妥当と考えられます。
    無駄レコードの参照を避けることでパフォーマンス改善が期待できます。

  2. の指摘は、imm_company_post を LEFT JOIN しているにもかかわらず、WHERE句で dp.locale_id = 'ja' という条件でフィルタリングしている点です。
    LEFT JOINはマッチしないレコードをNULLで返すはずですが、WHERE句での条件判定によってNULL行が除外され、事実上INNER JOINと同じ動作になります。このような場合は、ON句に条件を移すか、INNER JOINに変更するなど、意図を明確にする必要があると考えられます。

  3. 以降についても同様に、正しいデータ取得ができない懸念がある点が指摘されています。

ただし、これらの提案がすべて妥当とは限りません。アシスタントに問題点を指摘させたら、その回答が正しいかを人間が判断することが重要です。疑問点があれば、さらに質問を重ねて理解を深めることもできます。このような対話を繰り返しながら、SQLを段階的に改善していきます。

ステップ2:実行計画の取得

おおよその問題点は修正できてきたとして、今度は「実行計画」を取ってみたくなります。

実行計画とは

実行計画(Execution Plan)は、SQLをどのような手順で実行するかをデータベースが決めた「実行手順書」のようなものです。インデックスを使うか、テーブル全体を読むか、複数のテーブルをどの順序で結合するか—こうした処理内容が記録されます。
実行計画はSQLのパフォーマンスを評価する上でとても重要です。

ということで、なんとなくこんな風に質問してみます。

実行計画を取ってみたい気がします

cookbook272636_05

それに対する、アシスタントからの回答

実行計画を取得するためのコマンドを提供させていただきます。

PostgreSQL での実行計画取得方法
1. 基本的な実行計画(推定)

EXPLAIN
SELECT
u.user_cd AS user_cd,
u.user_name AS user_name,
d.department_name AS department_name,
dp.post_name AS post_name,
p.parent_department_cd AS parent_department_cd,
parent_d.department_name AS parent_department_name
FROM
imm_user u
INNER JOIN imm_department_ath da
  ON u.user_cd = da.user_cd
  AND da.delete_flag = '0'
INNER JOIN imm_department d
  ON da.company_cd = d.company_cd
  AND da.department_set_cd = d.department_set_cd
  AND da.department_cd = d.department_cd
  AND d.delete_flag = '0'
LEFT JOIN imm_department_post_ath dpa
  ON da.user_cd = dpa.user_cd
  AND da.company_cd = dpa.company_cd
  AND da.department_set_cd = dpa.department_set_cd
  AND da.department_cd = dpa.department_cd
  AND dpa.delete_flag = '0'
LEFT JOIN imm_company_post dp
  ON dpa.post_cd = dp.post_cd
  AND dpa.company_cd = dp.company_cd
  AND dpa.department_set_cd = dp.department_set_cd
  AND dp.delete_flag = '0'
  AND dp.locale_id = 'ja'
INNER JOIN imm_department_inc_ath p
  ON d.company_cd = p.company_cd
  AND d.department_set_cd = p.department_set_cd
  AND d.department_cd = p.department_cd
  AND p.depth = 1
  AND p.delete_flag = '0'
INNER JOIN imm_department parent_d
  ON p.company_cd = parent_d.company_cd
  AND p.department_set_cd = parent_d.department_set_cd
  AND p.parent_department_cd = parent_d.department_cd
  AND parent_d.delete_flag = '0'
  AND parent_d.locale_id = 'ja'
WHERE
u.locale_id = 'ja'
AND u.delete_flag = '0'
AND d.locale_id = 'ja'
AND u.start_date <= CURRENT_TIMESTAMP
AND u.end_date >= CURRENT_TIMESTAMP
AND da.start_date <= CURRENT_TIMESTAMP
AND da.end_date >= CURRENT_TIMESTAMP
AND d.start_date <= CURRENT_TIMESTAMP
AND d.end_date >= CURRENT_TIMESTAMP
AND dpa.start_date <= CURRENT_TIMESTAMP
AND dpa.end_date >= CURRENT_TIMESTAMP
AND p.start_date <= CURRENT_TIMESTAMP
AND p.end_date >= CURRENT_TIMESTAMP
AND parent_d.start_date <= CURRENT_TIMESTAMP
AND parent_d.end_date >= CURRENT_TIMESTAMP
ORDER BY u.user_cd, d.department_name;
2. より詳細な実行計画(推定コストと行数を含む)

EXPLAIN (FORMAT JSON)
SELECT
u.user_cd AS user_cd,
u.user_name AS user_name,
d.department_name AS department_name,
dp.post_name AS post_name,
p.parent_department_cd AS parent_department_cd,
parent_d.department_name AS parent_department_name
FROM
imm_user u
INNER JOIN imm_department_ath da
  ON u.user_cd = da.user_cd
  AND da.delete_flag = '0'
INNER JOIN imm_department d
  ON da.company_cd = d.company_cd
  AND da.department_set_cd = d.department_set_cd
  AND da.department_cd = d.department_cd
  AND d.delete_flag = '0'
LEFT JOIN imm_department_post_ath dpa
  ON da.user_cd = dpa.user_cd
  AND da.company_cd = dpa.company_cd
  AND da.department_set_cd = dpa.department_set_cd
  AND da.department_cd = dpa.department_cd
  AND dpa.delete_flag = '0'
LEFT JOIN imm_company_post dp
  ON dpa.post_cd = dp.post_cd
  AND dpa.company_cd = dp.company_cd
  AND dpa.department_set_cd = dp.department_set_cd
  AND dp.delete_flag = '0'
  AND dp.locale_id = 'ja'
INNER JOIN imm_department_inc_ath p
  ON d.company_cd = p.company_cd
  AND d.department_set_cd = p.department_set_cd
  AND d.department_cd = p.department_cd
  AND p.depth = 1
  AND p.delete_flag = '0'
INNER JOIN imm_department parent_d
  ON p.company_cd = parent_d.company_cd
  AND p.department_set_cd = parent_d.department_set_cd
  AND p.parent_department_cd = parent_d.department_cd
  AND parent_d.delete_flag = '0'
  AND parent_d.locale_id = 'ja'
WHERE
u.locale_id = 'ja'
AND u.delete_flag = '0'
AND d.locale_id = 'ja'
AND u.start_date <= CURRENT_TIMESTAMP
AND u.end_date >= CURRENT_TIMESTAMP
AND da.start_date <= CURRENT_TIMESTAMP
AND da.end_date >= CURRENT_TIMESTAMP
AND d.start_date <= CURRENT_TIMESTAMP
AND d.end_date >= CURRENT_TIMESTAMP
AND dpa.start_date <= CURRENT_TIMESTAMP
AND dpa.end_date >= CURRENT_TIMESTAMP
AND p.start_date <= CURRENT_TIMESTAMP
AND p.end_date >= CURRENT_TIMESTAMP
AND parent_d.start_date <= CURRENT_TIMESTAMP
AND parent_d.end_date >= CURRENT_TIMESTAMP
ORDER BY u.user_cd, d.department_name;
3. 実際の実行コストと統計情報を含む詳細計画

EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT
u.user_cd AS user_cd,
u.user_name AS user_name,
d.department_name AS department_name,
dp.post_name AS post_name,
p.parent_department_cd AS parent_department_cd,
parent_d.department_name AS parent_department_name
FROM
imm_user u
INNER JOIN imm_department_ath da
  ON u.user_cd = da.user_cd
  AND da.delete_flag = '0'
INNER JOIN imm_department d
  ON da.company_cd = d.company_cd
  AND da.department_set_cd = d.department_set_cd
  AND da.department_cd = d.department_cd
  AND d.delete_flag = '0'
LEFT JOIN imm_department_post_ath dpa
  ON da.user_cd = dpa.user_cd
  AND da.company_cd = dpa.company_cd
  AND da.department_set_cd = dpa.department_set_cd
  AND da.department_cd = dpa.department_cd
  AND dpa.delete_flag = '0'
LEFT JOIN imm_company_post dp
  ON dpa.post_cd = dp.post_cd
  AND dpa.company_cd = dp.company_cd
  AND dpa.department_set_cd = dp.department_set_cd
  AND dp.delete_flag = '0'
  AND dp.locale_id = 'ja'
INNER JOIN imm_department_inc_ath p
  ON d.company_cd = p.company_cd
  AND d.department_set_cd = p.department_set_cd
  AND d.department_cd = p.department_cd
  AND p.depth = 1
  AND p.delete_flag = '0'
INNER JOIN imm_department parent_d
  ON p.company_cd = parent_d.company_cd
  AND p.department_set_cd = parent_d.department_set_cd
  AND p.parent_department_cd = parent_d.department_cd
  AND parent_d.delete_flag = '0'
  AND parent_d.locale_id = 'ja'
WHERE
u.locale_id = 'ja'
AND u.delete_flag = '0'
AND d.locale_id = 'ja'
AND u.start_date <= CURRENT_TIMESTAMP
AND u.end_date >= CURRENT_TIMESTAMP
AND da.start_date <= CURRENT_TIMESTAMP
AND da.end_date >= CURRENT_TIMESTAMP
AND d.start_date <= CURRENT_TIMESTAMP
AND d.end_date >= CURRENT_TIMESTAMP
AND dpa.start_date <= CURRENT_TIMESTAMP
AND dpa.end_date >= CURRENT_TIMESTAMP
AND p.start_date <= CURRENT_TIMESTAMP
AND p.end_date >= CURRENT_TIMESTAMP
AND parent_d.start_date <= CURRENT_TIMESTAMP
AND parent_d.end_date >= CURRENT_TIMESTAMP
ORDER BY u.user_cd, d.department_name;
各オプションの説明
オプション 説明
EXPLAIN 基本的な実行計画を表示(推定値のみ)
ANALYZE 実際にクエリを実行して、実際のコストと行数を取得
BUFFERS バッファメモリの使用状況を表示
FORMAT JSON 結果をJSON形式で出力(パース・分析しやすい)
FORMAT TEXT テキスト形式で出力(デフォルト)
実行計画を見るときのポイント
Seq Scan: シーケンシャルスキャン(テーブル全体スキャン)
Index Scan: インデックスを使用したスキャン
Hash Join / Nested Loop / Merge Join: 結合方式
Actual Rows vs Planned Rows: 推定行数と実際の行数の乖離があれば、統計情報の更新が必要な可能性
I/O時間: バッファメモリヒット率やディスク読み込み時間
これらを確認することで、パフォーマンスボトルネックを特定できます。

なんだか、たくさん出てきましたが・上から読んでいくと「基本的な実行計画」というのがあるので、とりあえずこれをやってみるのが良さそうです。
提案されたコマンドはデータベース付属のツール等で実行可能です。
ここでは、Accel Platform 付属の「データベース操作」を使ってみることにします。

cookbook272636_06

コマンドの実行結果例

QUERY PLAN
Sort (cost=30.74..30.75 rows=1 width=785)
 Sort Key: u.user_cd, d.department_name
 -> Nested Loop (cost=0.70..30.73 rows=1 width=785)
 Join Filter: ((p.parent_department_cd)::text = (parent_d.department_cd)::text)
 -> Nested Loop (cost=0.56..28.90 rows=1 width=1697)
 -> Nested Loop Left Join (cost=0.42..25.57 rows=1 width=1289)
 -> Nested Loop (cost=0.28..17.39 rows=1 width=991)
 -> Nested Loop (cost=0.14..15.78 rows=1 width=933)
 -> Nested Loop (cost=0.00..14.42 rows=1 width=1139)
 Join Filter: (((da.user_cd)::text = (dpa.user_cd)::text) AND ((da.company_cd)::text = (dpa.company_cd)::text) AND ((da.department_set_cd)::text = (dpa.department_set_cd)::text) AND ((da.department_cd)::text = (dpa.department_cd)::text))
 -> Seq Scan on imm_department_post_ath dpa (cost=0.00..10.90 rows=1 width=1090)
 Filter: (((delete_flag)::text = '0'::text) AND (start_date <= CURRENT_TIMESTAMP) AND (end_date >= CURRENT_TIMESTAMP))
 -> Seq Scan on imm_department_ath da (cost=0.00..3.24 rows=14 width=49)
 Filter: (((delete_flag)::text = '0'::text) AND (start_date <= CURRENT_TIMESTAMP) AND (end_date >= CURRENT_TIMESTAMP))
 -> Index Scan using imm_user_pkey on imm_user u (cost=0.14..1.35 rows=1 width=19)
 Index Cond: (((user_cd)::text = (da.user_cd)::text) AND ((locale_id)::text = 'ja'::text))
 Filter: (((delete_flag)::text = '0'::text) AND (start_date <= CURRENT_TIMESTAMP) AND (end_date >= CURRENT_TIMESTAMP))
 -> Index Scan using imm_department_pkey on imm_department d (cost=0.14..1.61 rows=1 width=58)
 Index Cond: (((company_cd)::text = (da.company_cd)::text) AND ((department_set_cd)::text = (da.department_set_cd)::text) AND ((department_cd)::text = (da.department_cd)::text) AND ((locale_id)::text = 'ja'::text))
 Filter: (((delete_flag)::text = '0'::text) AND (start_date <= CURRENT_TIMESTAMP) AND (end_date >= CURRENT_TIMESTAMP))
 -> Index Scan using imm_comp_p_idx_ref_del on imm_company_post dp (cost=0.14..8.16 rows=1 width=1170)
 Index Cond: (((company_cd)::text = (dpa.company_cd)::text) AND ((department_set_cd)::text = (dpa.department_set_cd)::text) AND ((post_cd)::text = (dpa.post_cd)::text) AND ((delete_flag)::text = '0'::text))
 Filter: ((locale_id)::text = 'ja'::text)
 -> Index Scan using imm_dept_ia_idx_parents on imm_department_inc_ath p (cost=0.14..3.32 rows=1 width=872)
 Index Cond: (((company_cd)::text = (da.company_cd)::text) AND ((department_set_cd)::text = (da.department_set_cd)::text) AND ((department_cd)::text = (da.department_cd)::text))
 Filter: (((delete_flag)::text = '0'::text) AND (depth = '1'::numeric) AND (start_date <= CURRENT_TIMESTAMP) AND (end_date >= CURRENT_TIMESTAMP))
 -> Index Scan using imm_department_pkey on imm_department parent_d (cost=0.14..1.82 rows=1 width=58)
 Index Cond: (((company_cd)::text = (da.company_cd)::text) AND ((department_set_cd)::text = (da.department_set_cd)::text) AND ((locale_id)::text = 'ja'::text))
 Filter: (((delete_flag)::text = '0'::text) AND (start_date <= CURRENT_TIMESTAMP) AND (end_date >= CURRENT_TIMESTAMP))

この結果を、アシスタントにそのまま渡してみます。

cookbook272636_07

アシスタントからの回答

cookbook272636_08

実行計画を人間が読んで理解することも重要ですが、その前に一旦アシスタントに分析してもらって意見をもらうことも可能になります。
このように、常にアシスタントを活用しながら、問題点の指摘、修正案の提示、実行計画の分析を繰り返して、SQLを段階的に改善していくことができます。

たとえば、今回はアシスタントから「より詳細な実行計画」の取得方法も提案されていたので、同じように実行して、結果をアシスタントに渡して分析してもらうこともできます。

まとめ

  • 生成AIは間違った回答をすることがある

    • SQL作成のときと同じく、生成AIはあくまで「支援ツール」です。最終的な判断は人間が行う必要があります。
  • 生成AIは、成果物の作成以外の用途にも利用できる

    • SQLの問題点指摘や実行計画の分析など、成果物に対してフィードバックをもらう用途にも活用できます。
  • 生成AIの回答に分からないことがある場合、それを質問して理解を深めることができる

    • 生成AIの回答に対して更に質問を重ねることで、理解を深めたり、別の視点を得たりすることができます。
  • 生成AIが作成した成果物のクオリティを生成AIに高めてもらうことができる

    • 生成AIが作成したSQLの問題点を生成AI自身に指摘してもらい、改善案を提示してもらうことで、より良い成果物に仕上げることができます。
    • 最終的には人間が判断する必要がありますが、50点の成果物を70点、80点に高める支援を受けることができます。