RDBのPrimary KeyにUUIDかAuto IncrementなBigintを使うか問題
各所で話題なので思い出したことを書きたい。
私はどっち派ということもないというか一概にどっちが絶対いいとは言い切れない派だが、以下のことは考慮に入れたいと思っている。
-
UUIDは別環境の同じスキーマのレコードを持ってきても問題ない。Bigintだと衝突を考慮に入れる必要がある。昔やっていた仕事ではステージング環境で作ったデータを本番環境にコピーしてほしいという要望が少なからずあり、そのときはPrimary KeyがUUIDであったことがメリットだった。特にリレーションを貼っているレコードのセットをそのまま持ってこようとするとAuto IncrementなBigintがIDだとほぼ必ずIDを書き換える必要があるが、UUIDであればその必要はない。また、Test環境のFixtureデータやローカル環境のSeedデータみたいなのをあとから追加したいときにもUUIDであればPrimaryKeyを決め打ちにできる。BigintだとそのときのDBのレコードの状態次第でPrimary Keyを変えなければいけない。UUIDはステートレスにできるといってもいいかもしれない。
-
IDの読みやすさ、可読性の高さ、人間が見て暗記するような運用が生じそうであればBigintのほうがいい。UUIDを覚えるのはほぼ無理なのでコピペするしかない。
-
Auto incrementということは、データベースが採番する必要があることを意味する。高負荷な環境では採番することがボトルネックになることがあるので油断できない。超並列で書き込みたい要件がありそうであればUUIDのほうが無難。ただ、いまの最新のMySQL/PostgreSQLの採番の性能は十分すぎるほど高そうだけど、私はMySQL 5.0(innodb)を使っていたときにAuto Incrementの性能がボトルネックになって苦しんで採番テーブルに置き換えた苦い思い出があるので(MySQL5.1で大幅に性能向上した)、採番をINSERT時に同時にやりたくないという思い込みがある。過去の経験が足を引っ張っている悪い思い込みかもしれないとは思う。
-
Auto incrementは冪等な処理と相性が悪い。これは実装次第といわれそうだけどナイーブに作ったらそうなる。でも殆どの場合問題にならないといわれればそれはそう。
-
UUIDはディスク効率が悪いからパフォーマンスが悪いという意見もみたが、それがボトルネックになるケースにあたればそれはそうだと思う。あとはUUIDv7を使えば大幅に緩和するだろうという意見も同意だし、結局ボトルネックになるワークロードがどういうものかが予想できてそれがデータの格納効率なのであればそれはそうだろうけど、事前にボトルネックを予想できることは稀だし、そこがボトルネックになって選択を後悔するまでに至る確率はかなり低いと思っている。それ以外にUUIDを使うメリットも上述したとおりあるので、それぞれ検討してあとは決めの問題だと思う。