Databases 10 min read

Performance Comparison of UUID vs Auto-Increment IDs in MySQL

Benchmarking three MySQL tables—auto_increment, UUID, and random long keys—shows that sequential auto_increment inserts are fastest, random keys are slower, and UUIDs dramatically lag due to random I/O and fragmentation, so use auto_increment for most workloads and reserve UUIDs only for required global uniqueness.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Performance Comparison of UUID vs Auto-Increment IDs in MySQL

MySQL recommends using sequential auto_increment primary keys instead of UUIDs or other non‑sequential identifiers. This article investigates the reasons by creating three tables—one with an auto_increment key, one with a UUID key, and one with a random (snowflake) key—and benchmarking insert and query performance using Spring Boot's JdbcTemplate.

Three tables (user_auto_key, user_uuid, user_random_key) are populated with randomly generated data. A JUnit test inserts the same amount of data into each table while measuring execution time with Spring's StopWatch. The Java test code is shown below.

package com.wyq.mysqldemo;

import cn.hutool.core.collection.CollectionUtil;
import com.wyq.mysqldemo.databaseobject.UserKeyAuto;
import com.wyq.mysqldemo.databaseobject.UserKeyRandom;
import com.wyq.mysqldemo.databaseobject.UserKeyUUID;
import com.wyq.mysqldemo.diffkeytest.AutoKeyTableService;
import com.wyq.mysqldemo.diffkeytest.RandomKeyTableService;
import com.wyq.mysqldemo.diffkeytest.UUIDKeyTableService;
import com.wyq.mysqldemo.util.JdbcTemplateService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.StopWatch;
import java.util.List;

@SpringBootTest
class MysqlDemoApplicationTests {

    @Autowired
    private JdbcTemplateService jdbcTemplateService;

    @Autowired
    private AutoKeyTableService autoKeyTableService;

    @Autowired
    private UUIDKeyTableService uuidKeyTableService;

    @Autowired
    private RandomKeyTableService randomKeyTableService;

    @Test
    void testDBTime() {
        StopWatch stopwatch = new StopWatch("执行sql时间消耗");
        // auto_increment key task
        final String insertSql = "INSERT INTO user_key_auto(user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?)";
        List
insertData = autoKeyTableService.getInsertData();
        stopwatch.start("自动生成key表任务开始");
        long start1 = System.currentTimeMillis();
        if (CollectionUtil.isNotEmpty(insertData)) {
            boolean insertResult = jdbcTemplateService.insert(insertSql, insertData, false);
            System.out.println(insertResult);
        }
        long end1 = System.currentTimeMillis();
        System.out.println("auto key消耗的时间:" + (end1 - start1));
        stopwatch.stop();
        // UUID key task
        final String insertSql2 = "INSERT INTO user_uuid(id,user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?,?)";
        List
insertData2 = uuidKeyTableService.getInsertData();
        stopwatch.start("UUID的key表任务开始");
        long begin = System.currentTimeMillis();
        if (CollectionUtil.isNotEmpty(insertData2)) {
            boolean insertResult = jdbcTemplateService.insert(insertSql2, insertData2, true);
            System.out.println(insertResult);
        }
        long over = System.currentTimeMillis();
        System.out.println("UUID key消耗的时间:" + (over - begin));
        stopwatch.stop();
        // Random long key task
        final String insertSql3 = "INSERT INTO user_random_key(id,user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?,?)";
        List
insertData3 = randomKeyTableService.getInsertData();
        stopwatch.start("随机的long值key表任务开始");
        Long start = System.currentTimeMillis();
        if (CollectionUtil.isNotEmpty(insertData3)) {
            boolean insertResult = jdbcTemplateService.insert(insertSql3, insertData3, true);
            System.out.println(insertResult);
        }
        Long end = System.currentTimeMillis();
        System.out.println("随机key任务消耗时间:" + (end - start));
        stopwatch.stop();
        String result = stopwatch.prettyPrint();
        System.out.println(result);
    }
}

The benchmark results show that with about 1.3 million existing rows, inserting an additional 100 k rows yields the following order of speed: auto_increment > random > UUID. UUID performance drops dramatically as the table grows because its non‑sequential values cause InnoDB to perform random I/O, frequent page splits, and increased fragmentation.

Internally, auto_increment keys are sequential, allowing InnoDB to append new rows to the end of the clustered index, achieve high page fill factors, and avoid page splits. UUIDs, being random, force InnoDB to locate free space for each insert, leading to page splits, extra I/O, and fragmented pages. The article also notes drawbacks of auto_increment keys: they expose business growth patterns and can become a contention point under high concurrency due to lock competition.

Conclusion: for most MySQL workloads, prefer sequential auto_increment primary keys for optimal performance. UUIDs should be used only when global uniqueness is essential, accepting the associated performance penalties.

performanceIndexingMySQLJDBCSpringBootauto-incrementUUID
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.