本ブログはアフィリエイト広告を利用しています。

AI Programmer にSQL改善してもらった話

私はSQLが苦手で本当に簡単なCRUDくらいなら書けますけどgroup byやらhavingやら結合やらが必要になると途端に書けなくなるポンコツ具合です。
あんまり覚える気もないので難しそうだったら誰かに頼んだり、なんとか調べて作ったり(そしてその後すぐ忘れる)。
そんな具合なものであまりにも遅かったSQLをAI Programmer(https://aiprogrammer.hashlab.jp/)に直してもらいました。

経緯

現在私はこのブログが乗っているVPSやらアプリやらの状態を監視する目的でGrafanaを使用しています。
CPUやメモリの使用率についてはPrometheusとかで見ているのでこちらはあまり関係ないのですが、アプリ側についてはDBの中身を監視しています。
そのSQLの1つがあまりにも遅かったのです。まぁ欲しい情報は取れていたのでしばらく放っておいたのですがAI Programmerが登場し、なんか改善できそうだったので試してみました。

問題のSQL

まずはテーブルの定義です。このテーブルは履歴テーブル的な感じで使用しています。
ちなみに使用しているDBはPostgreSQLです。

appdb=# \d tool_info
                 Table "public.tool_info"
    Column    |            Type             |       Modifiers
--------------+-----------------------------+------------------------
 execute_type | integer                     | not null
 execute_name | character varying(256)      | not null
 name         | character varying(256)      |
 user         | character varying(256)      |
 memo         | character varying(256)      |
 created_at   | timestamp without time zone | not null default now()

SQLがこちらです。
user、user毎の件数、created_atの最初の日時、最後の日時を取得しています。条件はexecute_typeが0以外。
長々と書いてますがこれが非常に遅かったです。

select ip_address as ip, count(*) as count,
(select
created_at - interval '9 hour'
from
tool_statistic_info
where
execute_type != 0
and
ip_address = t.ip_address
order by created_at asc limit 1) as first_use_date,
(select
created_at - interval '9 hour'
from
tool_statistic_info
where
execute_type != 0
and
ip_address = t.ip_address
order by created_at desc limit 1) as last_use_date
from tool_statistic_info t
where
execute_type != 0
group by ip_address
order by first_use_date desc;

AI Programmerに改善してもらう

AI Programmer(https://aiprogrammer.hashlab.jp/)にアクセスし、言語はSQLを選択。
処理内容として以下のように記載しました。この処理内容が変だったりうまく理解されないと何も返答してくれないのでお返事くるまで色々試してみましょう。

tool_infoというテーブルがあり、以下のカラムが存在します。
1. execute_type
2. execute_name
3. name
4. user
5. memo
6. created_at

user毎の件数とuser、さらにcreated_atで昇順ソートし最初と最後のcreated_atを取得するSQLを作成してください。

生成されたSQLがこちらです。

SELECT user, COUNT(user) AS count, MIN(created_at) AS start_date, MAX(created_at) AS end_date
FROM tool_info
GROUP BY user
ORDER BY user ASC

自分で書いてたSQLがあほに思える。というかGROUP BYの使い方わかってなさすぎだなと。
まぁそれは置いておいて出来上がったSQLでは元のSQLと少し条件が違うので手を加えていきます。

SELECT 
  ip_address as ip,
  COUNT(ip_address),
  MIN(created_at - interval '9 hour') as first_use_date,
  MAX(created_at - interval '9 hour') as last_use_date
FROM tool_statistic_info
WHERE execute_type != 0
GROUP BY ip_address ORDER BY first_use_date DESC;

で、どれくらいSQLの速度が改善されたかというと 8984.580ms から 30.779ms です。
やっぱり元のSQLはip_address = t.ip_addressの辺りが遅かったのかな。これでサクッと情報見れるようになったのでめでたしめでたし。

しかし本当にこれすごいですね。
仕事の方でもちょっとだけ使ったことがあって、その時は正規表現でお世話になりました。
だれかが作った正規表現を別の言語に移植したかったのですがいちいち正規表現全部なんて覚えてないので都度検索して調べるのですが、AI Programmerにこの正規表現説明して!って書いたら大体の内容が把握できたのであとは移植先の言語で正規表現書きました。
使い方次第ではかなり有用だなと思いました。

関連記事

コメント

タイトルとURLをコピーしました