プライマリーキーのデータタイプはDBにどう影響するのか
ここで考えるべきことは大きくわけ二つ
- サーチコスト
- データタイプのサイズ
サーチコスト
サーチコストとは文字通りサーチする際にかかるコストのことです.
例えばこのようなランダムにジェネレイトされたアレーがあるとします.
int[] a = int[10]
for(int i = 0; i < a.length; i++){
a[i] = rand();
}
ここでaの中から最大の値をサーチする時,ここでのサーチコストは全ての値を一つ一つ調べなくてはいけないのでO(n)となります.
*nはアレーの長さ
ただ実際のDBはB+treeやHashMapまたそれにHash-based indexes 併用しているのでサーチ自体にかかるコストはO(1)つまりコンスタントな時間で処理することが可能です.本当はこのデータストラクチャーを作るコストも考えるべきなのですが今回は単純にサーチコストに絞って話していきましょう.
ではキーを探すコストがコンスタントであるのになぜキーのデータタイプがサーチコストに影響するのでしょうか.
ここは2つの点にフォーカスしてみましょう.
1. タイムコンプレキシティ
これは簡単にいうとどれだけの時間がかかるかということです.
int と Stringはどちらの方がキーとして適しているのか.単純に時間だけで比べてみましょう.
int a = 1;
int b = 2;
ここで a==b
とコールしたとしましょう.aとbはまずデータタイプが一致しています.これをリターンする際のオペレーションは全てのビットをXORゲートに通したのちNOTゲートに通し全てのビットから出たワイヤーをANDゲートで処理するという形になるので,intは4byte(32bit)と決まったサイズなのでここでのタイムコンプレキシティはO(1)となります.
ではこれがStringだった場合はどうでしょうか.
String a = "1";
String b = "2";
ここで a.equals(b)
をコールしたとしましょう.aとbはまずデータタイプが両方Stringで一致しています.ストリングはオブジェクトでありcharのアレーなので,一文字一文字先程のゲート処理を行なったのち全てが一致するかを調べることになるため,ここでのタイムコンプレキシティはO(n)となります.
つまり単純にタイムコンプレキシティで比較した場合intの方が優れているといえます.
2. スペースコンプレキシティ
これはどれだけのスペースを使うかということです.ここでのスペースはメモリー内のスペースと思っていただいて結構です.
ではintとbig int(他の言語ではlongという名の方が多い)を比べてみましょう.
intとbig intではタイムコンプレキシティは同じです.この二つの大きな違いはサイズです.
intは4byte(32bit)に対しbig intは8byte(64bit)あります.一見2倍だけの違いのように見えますが,実際は莫大な違いがあります.intのmaxは2ˆ32 ˜= 40億なのに対しbig intのmaxは2ˆ64 ˜= 2000京となります.
もちろんbig intを選べばオバーフローする可能性は減らせますが,その分倍のスペースを使うのでどれくらいの数のデータが保存させるのかをあらかじめ予想し選ぶことが必要です.
データタイプのサイズ
先述した通り,それぞれのデータタイプには与えられたサイズがあり,DBの使い方によって適したサイズのキーを選ぶことが大切になってきます.
いくつか例をあげておきます.
-char: 1 byte
-int: 4 byte
-big int: 8 byte
-varchar(max): 65,535 byte
他にも色々ありますし,もちろんvarcharのサイズを自分で指定することも可能です.
一番ここで恐るべきことはオバーフローなので,実際に予想されるサイズより少し大きいものを選ぶことが安全策かと思います.
まとめ
どのデータタイプがキーに適しているかというのは一概にはいえません.多くの場合intかbig intが使われることが多いですが,実際に自身のDBに適しているのはなんなのか考えてみると良いかと思います.
またこれはSQLのDBに限った話ではなく,どの言語においてもどのデータタイプが適しているのかタイム/スペースコンプレキシティをベースに考える癖をつけることは大切なことです.