binary型のカラムへのデータ保存について
|
binary型のメリットとカラムへデータを保存する方法についてのメモです。
Table of Contents
なぜbinary型を使うのか
ストレージの効率化とパフォーマンスの向上、そしてデータ整合性を保つメリットがあります。
パフォーマンスの向上
- ストレージの効率化: 例えばUUIDを文字列形式で格納する場合に比べて、バイナリ形式で格納するとデータサイズが半分になります(文字列が32byteなのに対して、binary(16)だと16byte)。これにより、ディスク容量の節約ができます。
- インデックスの効率化: バイナリデータは、文字列よりも比較演算が速く、インデックスの作成や検索時のパフォーマンスが向上することがあります。特に、UUIDなどの固定長のデータに対して、文字列の比較よりもバイナリ比較の方が効率的です。
データの一貫性
BINARY
型は固定長のデータを保持するため、格納するデータの長さが常に一定であることが保証されます。これにより、データが予期しない形で変更されることを防ぐことができます(例:文字列型でのトリムやパディングの問題)。
binary型のデータを保存する方法
UUIDなどの16進数で表現された値。これをbinary(size)のカラムにを保存するケースを考えてみます。
a34e5f1d-60f7-4230-9b74-7885e4558c76
ならsize=16。UUIDですね。
101001-27482797-3e59-7c18-a761-7b54a3c4c9ee
UUIDとは異なる16進数で表現された値。size=19に対応します。
SQLの場合
16進数の文字列をUNHEX
関数やX'...'
構文でバイトに変換してINSERTします。ハイフンなどを含んでいる場合は除外しておきます(SQLならREPLACE関数などで除外できます)。
1INSERT INTO sample_table(column_size16, column_size19)
2VALUES(X'a34e5f1d60f742309b747885e4558c76', X'101001274827973e597c18a7617b54a3c4c9ee';
↓取得する際はHEX
関数で16進数に戻します。
1SELECT HEX(column_size16) AS original_size16, HEX(column_size19) AS oritinal_size19 FROM sample_table;
2+----------------------------------+----------------------------------------+
3| original_size16 | oritinal_size19 |
4+----------------------------------+----------------------------------------+
5| A34E5F1D60F742309B747885E4558C76 | 101001274827973E597C18A7617B54A3C4C9EE |
6+----------------------------------+----------------------------------------+
UUIDに特化した関数も用意されていますが、それらの関数はbinary(16)にしか使えないため注意。
Golangの場合
プログラミング言語でDBに値を保存する場合もSQLの場合と同様に、16進数からバイトに変換してSQLを実行してあげればOKです。
Goには encoding/hex
という16進数を扱うパッケージがあるのでそれを使います。
1// GORMの場合
2
3type sampleTable struct {
4 Column16 []byte `gorm:"primaryKey;column:column16;size:16"`
5 Column19 []byte `gorm:"column:column19;size:19"`
6}
7
8func Create(tx *gorm.DB) error {
9 size16 := "a34e5f1d-60f7-4230-9b74-7885e4558c76"
10 size16Bytes, size16HexDecodeErr := hex.DecodeString(strings.ReplaceAll(size16, "-", ""))
11 if size16HexDecodeErr != nil {
12 return size16HexDecodeErr
13 }
14
15 size19 := "101000-f64d0ffb-5c7b-1a65-aef6-b4aee892ef56"
16 size19Bytes, size19HexDecodeErr := hex.DecodeString(strings.ReplaceAll(size19, "-", ""))
17 if size19HexDecodeErr != nil {
18 return size19HexDecodeErr
19 }
20
21 result := tx.Create(&sampleTable{Column16: size16Bytes, Column19: size19Bytes})
22 if result.Error != nil {
23 return result.Error
24 }
25
26 return nil
27}