1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

mysql系でUUIDを処理するための戦略

Posted at

MySQLでUUIDをPrimary Keyとして使用する際の問題と解決方法

1. UUIDをPKとして使用した場合の問題

  • UUIDの特性: UUIDは時間とランダム性に基づいて生成されるため、無作為に分布します。このため、インデックス構造上、データがB-Treeに挿入される際に、データがソートされる必要があり、多くのディスクI/Oが発生します。

    • ディスクI/Oの非効率性: MySQLでは、PKは基本的にクラスター化インデックスを使用するため、データ挿入時にソートが維持される必要があります。UUIDの無作為性が、クラスター化インデックスの効率を低下させます。その結果、挿入パフォーマンスが低下し、ディスクI/Oのコストが増加します。

    • パフォーマンス問題: UUIDをPKとして使用した場合、ディスクI/Oの増加によりパフォーマンスが大幅に低下し、挿入速度が遅くなり、テーブルサイズが不必要に大きくなります。

UUIDパフォーマンス問題図

UUIDパフォーマンス比較表

2. UUIDをPKとして使用しない解決方法

UUIDの一意性を保ちながら挿入パフォーマンスを向上させるための解決策は、自動増加するBIGINTタイプのPKを使用することです。

修正されたテーブル構造の例

CREATE TABLE `users` (
    `pk` BIGINT NOT NULL AUTO_INCREMENT,
    `uuid` BINARY(16) NOT NULL,
    `name` VARCHAR(20) NOT NULL COLLATE 'utf8mb4_general_ci',
    `email` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
    `password` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_bin',
    `is_delete` TINYINT(1) NOT NULL,
    `create_data_at` TIMESTAMP NOT NULL,
    `update_data_at` TIMESTAMP NOT NULL,
    PRIMARY KEY (`pk`) USING BTREE,
    INDEX `uuid` (`uuid`) USING BTREE,
    INDEX `idx_users_name` (`name`) USING BTREE
)
COMMENT='users'
COLLATE='utf8mb4_bin'
ENGINE=InnoDB;

  • PKとしてBIGINTを使用: 自動増加するBIGINTをPKとして使用し、データ挿入時のソートを容易にします。
  • UUIDは補助インデックスとして使用: UUIDフィールドは補助インデックスとして使用され、データの検索や関係性を保つために使用されます。
    この方法により、挿入パフォーマンスを改善しながらUUIDの一意性を保つことができます。

3. KotlinでのUUID処理

KotlinでUUIDを簡単に使用できるようにした例は以下の通りです。

@EntityListeners(AuditingEntityListener::class)
abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    var uuid: UUID? = null

    @Column(name = "create_data_at", updatable = false)
    @CreatedDate
    lateinit var createdAt: Instant
        protected set

    @LastModifiedDate
    @Column(name = "update_data_at")
    lateinit var updatedAt: Instant
        protected set

    @Column(name = "is_delete")
    var isDelete: Boolean = false
}

@Entity(name = "users")
class UsersEntity(
    @Column
    var name: String = "",

    @Column
    var email: String = "",

    @Column
    var password: String = ""
): BaseEntity()

BaseEntityクラスではUUIDを使用し、UsersEntityクラスはこのクラスを継承して、作成日時、更新日時、削除フラグを管理します。
これにより、プログラム上でUUIDを簡単に扱える環境が提供されます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?