Why Using UUID as MySQL Primary Key Is Inefficient: A Performance Comparison with Auto‑Increment and Random Keys
This article investigates MySQL's recommendation against UUID primary keys by creating three tables—auto‑increment, UUID, and random (snowflake) keys—running insert and query benchmarks with SpringBoot/JdbcTemplate, analyzing index structures, and discussing the performance trade‑offs and security considerations of each key strategy.
The author, a senior architect, starts by questioning MySQL's official advice to avoid UUID or non‑sequential keys and to prefer auto_increment primary keys, then outlines the goal of analyzing why UUIDs may be problematic.
1. MySQL Experiment Setup
Three tables are created: user_auto_key (auto‑increment primary key), user_uuid (UUID primary key), and user_random_key (snowflake‑generated 18‑digit long key). All other columns remain identical to isolate the effect of the primary key generation strategy.
The test inserts a large volume of randomly generated data using SpringBoot, JdbcTemplate, JUnit, and Hutool, measuring insert time with StopWatch. The relevant Java test code is:
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<UserKeyAuto> 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<UserKeyUUID> insertData2 = uuidKeyTableService.getInsertData();
stopwatch.start("UUID的key表任务开始");
long begin = System.currentTimeMillis();
if (CollectionUtil.isNotEmpty(insertData)) {
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<UserKeyRandom> insertData3 = randomKeyTableService.getInsertData();
stopwatch.start("随机的long值key表任务开始");
Long start = System.currentTimeMillis();
if (CollectionUtil.isNotEmpty(insertData)) {
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);
}
}Result screenshots (auto‑increment, random key, UUID) are shown below:
When the table already contains about 1.3 million rows, inserting another 100 k rows shows that UUID insert speed drops dramatically, while auto‑increment remains fastest and random (snowflake) is intermediate.
2. Index Structure Comparison
2.1 Auto‑increment index – because the primary key values are sequential, InnoDB stores rows in order, minimizing page splits, reducing random I/O, and keeping the fill factor high.
2.2 UUID index – UUIDs are random, so new rows cannot be appended to the end of the clustered index. InnoDB must locate a suitable page, causing frequent page splits, random disk reads, and fragmentation.
The article lists the concrete drawbacks of UUID inserts: extra random I/O, frequent page splits (modifying three or more pages per insert), and eventual need for OPTIMIZE TABLE to rebuild the table.
3. Drawbacks of Auto‑Increment
Although auto‑increment performs best, it has security and concurrency issues: exposure of business growth through predictable IDs, lock contention on the primary‑key hotspot under high concurrency, and the overhead of the auto‑increment lock mode.
4. Conclusion
The benchmark demonstrates that for large‑scale data insertion, auto‑increment keys outperform UUID and random snowflake keys, while UUIDs suffer severe performance degradation as data volume grows. The recommendation is to follow MySQL's guidance and use monotonic, sequential primary keys for clustered tables, while being aware of the security and lock‑contention trade‑offs.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
