こんにちは。
株式会社HRBrainでバックエンドエンジニアをしているみつです!
この春に新卒として入社し、さまざまな経験を積む中で、「sqlライブラリの移行」というタスクに立ち向かう機会がありました。
2024.05.20にししとうLTでは、時間の都合上話せなかった詳細について、この記事で補足したいと思います
(ちなみに、ししとうLTは私にとって人生初のLT登壇でした 記事執筆時点では、社外LTに聞く側でしか参加したことがないので、もし誘っていただけたら嬉しいですw)
- 資料はこちら ▼
sqlx
からpgx
への移行までの話- 出したかったログの種類
- 色々なGoのSQLライブラリを検討
- ログの導入の前に大変なことが発覚
- Query Insightsの導入をしつつ、ライブラリ移行は見送りに
- まとめ
- PR
資料はこちら ▼
sqlx
からpgx
への移行までの話
新規プロダクト開発を進める中で、「リリースまでにログを出したい!」というタスクがありました。
せっかくなのでやってみたい!と手を挙げ、チームで使用していたsqlx
にloggerを持たせる方法を検討しました。
しかし、sqlx
ではloggerを持たせることができないという壁にぶつかりました。
加えて、同じ時期にデータベースの設計見直しが行われており、この機会にライブラリも見直す必要があるのではないかと考えるようになり、"ぷち沼"にハマっていくことになります。
出したかったログの種類
出したいログの種類は、大きく3つでした。
- アクセスログ(いつアクセスしたかなど)
- アプリケーションログ(エラーのスタックトレースなど)
- SQL操作ログ(Cloud SQLでどんなSQLが実行されたかなど)
色々なGoのSQLライブラリを検討
まず、GoにはどんなSQLライブラリがあり、どのライブラリであればLoggerを持たせられるのかを検討しました。
標準パッケージであるdatabase/sql
から最近流行りのsqlc
(?)まで、一言にSQLと言ってもさまざまな種類のライブラリがあることを知りました。
正直なところ、種類が多くて、それぞれが何に使われるものなのかよく分からなかったので、一つずつドキュメントを読んで知識を深めることにしました。笑
- database/sql
- pq
- sqlx
- pgx
- sqlc
...etc.
pq
について
-
pq
パッケージは、database/sql
パッケージ用の純粋なGo PostgreSQLドライバです。[DeepL訳] - ほとんどの場合、クライアントはこのパッケージを直接使う代わりに
database/sql
パッケージを使うでしょう。[DeepL訳]
理解したのは、純粋なGoのPostgreSQLドライバとあるように、database/sql
と合わせて使うことで機能が拡張されるライブラリ。
database/sql
でPostgreSQLにある機能を使うためにこのドライバを使うことができます。
import (
"database/sql"
_ "github.com/lib/pq"
)
func main() {
connStr := "user=pqgotest dbname=pqgotest sslmode=verify-full"
db, err := sql.Open("postgres", connStr)
if err != nil {
log.Fatal(err)
}
age := 21
rows, err := db.Query("SELECT name FROM users WHERE age = $1", age)
…
}
sqlx
について
-
sqlx
は、Goの標準ライブラリdatabase/sql
を拡張するためのライブラリである。[DeepL訳]
これもpq
同様、database/sql
と合わせて使うことで拡張することが出来るライブラリのようです。(pq
≒ sqlx
)
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/lib/pq"
"github.com/jmoiron/sqlx"
)
pgx
について
- pgxはPostgreSQL用の純粋なGoドライバとツールキットです。[DeepL訳]
- pgx ドライバは低レベルで高性能なインタフェースであり、
LISTEN
/NOTIFY
やCOPY
といった PostgreSQL 固有の機能を提供します。また、標準のdatabase/sql
インタフェースのアダプタも含まれています。[DeepL訳]
最初にドキュメントを読んだ時は、pq
やsqlx
より強そうという印象を受けました。
このライブラリは、とても便利でpgxをドライバとして使用することもできたり、database/sql
のアダプタも含まれているとあるのでその機能を担うことも出来たりします。
実装例でも、database/sql
のimportなしに使っています。
package main
import (
"context"
"fmt"
"os"
"github.com/jackc/pgx/v5"
)
func main() {
// urlExample := "postgres://username:password@localhost:5432/database_name"
conn, err := pgx.Connect(context.Background(), os.Getenv("DATABASE_URL"))
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
defer conn.Close(context.Background())
var name string
var weight int64
err = conn.QueryRow(context.Background(), "select name, weight from widgets where id=$1", 42).Scan(&name, &weight)
if err != nil {
fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
os.Exit(1)
}
fmt.Println(name, weight)
}
sqlc
について
- 普通にORM
- sqlcはSQLから完全に型安全なイディオムGoコードを生成します。[DeepL訳]
これは調べて見てすぐ分かったことですが、必須のライブラリではありません。
オブジェクト関係マッピング(ORM、Object-Relational Mapping)というSQLを直接触ること無く記述するためのライブラリでした。
他にも有名どころだと、GORM
やSQLBoiler
など様々なものが存在していてそれぞれにメリット・デメリットがあるようです。
ログの導入の前に大変なことが発覚
様々なライブラリを調査し、選定を終え、ログ導入の準備が整いつつあったのですが…
「ちょっと待てよ。DBの設計見直しが入ったということは、APIが全て置き換わるということなんじゃないか」という議論が持ち上がりました。
実際にその通りで、DB設計の見直しが行われているため、ライブラリ導入でミスをしても影響は少ない(=今が導入しやすいタイミングと言える)一方で、DBが変更され、APIスキーマも変更され、実装も大きく方向転換することになります。
つまり、今頑張って書き換えや置き換え作業を行っても、膨大な時間ロスが発生するのではないかという議論も生まれました。
Query Insightsの導入をしつつ、ライブラリ移行は見送りに
そもそも、
- Cloud SQLを利用する中でどのようなSQLが実行されているのか
- クエリのパフォーマンスが明らかに悪い時に確認したい
などが背景で始まったログ導入タスク。
Query Insightsで一時的に必要なものな情報を取れることが判明し、それらの設定することでログの対応はひとまず見送ることになりました。
Query Insightsについては別記事でも紹介してるのでぜひ見てください
まとめ
インターン時代は既存サービスのフロントエンドを主に実装していましたが、新卒からは新規プロダクトでのバックエンド開発を担当しています。
その中で、ライブラリの導入は、初期段階だからこそ経験できる、楽しい壁だと感じています!
今回のライブラリ移行を通して、以下のようなことを学びました。
-
Goでデータベースを操作する際は、
database/sql
を使うのが基本であること -
しかし、
database/sql
はPostgreSQL以外のデータベース(MySQLなど)にも対応しているため、PostgreSQLの機能を利用する場合は、拡張ライブラリが必要になること- 例)↑ を埋めるのが、
pgx
,pq
,sqlx
だったりする - 例)↑
database/sql
+ PostgreSQL独自機能 =pgx
- 例)↑ を埋めるのが、
-
pq
は、database/sql
をより使いやすく、PostgreSQL風に設計されたライブラリ -
sqlx
も、database/sql
をより使いやすくしたり、database/sql
ではできない機能を提供するライブラリ- (ちなみに、機能的に重複しているため、
sqlx
とpgx
はあまり併用しないようです。)
- (ちなみに、機能的に重複しているため、
現在は、ライブラリの入れ替えはほとんど行われていませんが、チームではアーキテクチャ周りの議論でいつも大盛りあがり(?)です!
また明日からも楽しくコーディングを続けていきたいと思います!
PR
株式会社HRBrainでは、一緒に働く仲間を募集しています!
興味を持っていただいた方はぜひ弊社の採用ページをご確認ください!
HRBrain文化を一緒に作っていきましょう!