Spring Data JPAでよく使われているIDの種類ついてご説明したいと思います。
1. AUTO_INCREMENT(Sequence)
新しい行が挿入されるたびにDBMSが自動的に次の一意の数値を生成し、その列に挿入します。
長所
- 数字型でインデックスの性能が良い
- 時間順ソートが可能
短所
- 外部からPKを予測することが可能(システム規模の予測、SQL Injection)
- データベースのスケールアウト時、既存データベースのPK設定では重複が発生する可能性
- データベース変更時の手数(Oracle→Mysql変更時、Sequence→AUTO_INCREMENTに変更が必要)
使い方
@Data @Entity /* Oracleの場合 @SequenceGenerator( name = "MEMBER_SEQ_GEN", sequenceName = "[SequenceName]", initialValue = 1, allocationSize = 1 ) */ public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) /* Oracleの場合 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GEN") */ private Long id; }
2. UUID
長所
- PKの予測が不可能
- データベースのスケールアウトが簡単
- スレッドセーフ
短所
- 128ビットの大きいサイズ
- 時間順ソートが不可能
- 文字列型の比較で数字型より速度が遅い
- B-Treeインデックスの場合、性能の低下が発生
使い方
@Data @Entity public class Member { @Id private String id; } //-----------使用時----------- public void someMethod() { Member member = new Member(); String uuid = UUID.randomUUID().toString(); member.setId(uuid); }
Spring Data JPAでは上記のように使います。(UUIDタイプの作成方法もあります。)
3. TSID
長所
- 64ビット整数もしくは13字のURLセーフな文字列型
- PKの予測が不可能
- 時間順ソートが可能でB-Treeインデックスの性能が良い
- スレッドセーフ
短所
- 最大139年間使用可能(符合がある場合69年、符合がない場合139年)
使い方
Hibernate6の場合
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-utils-hibernate-63</artifactId> <version>3.7.0</version> </dependency>
@Data @Entity public class Member { @Id @Tsid private Long id; }
Hibernate5の場合
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-utils-hibernate-55</artifactId> <version>${hypersistence-utils.version}</version> </dependency>
@Data @Entity public class Member { @Id @GeneratedValue(generator = "tsid") @GenericGenerator( name = "tsid", strategy = "io.hypersistence.utils.hibernate.id.TsidGenerator" ) private Long id; }
TSID tsid = TSID.fast(); // 例:605354157791117179 // Long型を返却 Long toLongVal = tsid.toLong(); // 例:0GSN6SAJ1R4RV // 文字列型(大文字)を返却 String toStrValUpper = tsid.toString(); // 例:0gsn6saj1r4rv // 文字列型(小文字)を返却 String toStrValLower = tsid.toLowerCase(); // TSID型に変換 TSID parsedTsid1 = TSID.from(toLongVal); TSID parsedTsid2 = TSID.from(toStrValUpper); TSID parsedTsid3 = TSID.from(toStrValLower);
まとめ
ㅤ | AUTO_INCREMENT | UUID | TSID |
時間順ソート | 可能 | 不可能 | 可能 |
インデクシング | 良い | 悪い | 良い |
セキュリティ | 悪い | 良い | 良い |
サイズ | 小さい | 大きい | 小さい |
スケールアウト | 難しい | 易しい | 易しい |