UUID 作为数据库主键的 Insert 性能测试记录 #
在之前一篇 《Laravel使用UUID作为用户表主键并使用自定义用户表字段》发布之后和一个朋友的朋友聊了聊,讲到了一个我没有考虑到的UUID作为主键的问题——Insert性能问题。
朋友的朋友看法如下(有删改):
如果非要用 UUID 的话,完全可以用一个列来单独存放 UUID 的,没有必要把 UUID 设置为主键。自增主键的作用是 insert 的时候是顺序插入到磁盘里的,这样 innodb 直接插入就好了,因为索引插入要进行排序等一系列操作的,涉及到 innodb 索引的具体知识了,所以为了性能考虑,基本都是自增主键,保证顺序 而不是随机
Naïve Insert Time Test #
从一个小的测试开始:
硬件环境:
- Core i7-8560U
- 16GiB LPDDR3
- SAMSUNG PM981
软件环境:
- Laravel 5.6
- MySQL 5.6
有兩個數據表,一個是使用 UUID 作爲主鍵的 users
表,一個是使用自增 id
作爲主鍵的 tickets
表,串行同步的方式插入 1000 條數據,相關 seed
函數和運行時間如下:
User Table with UUID as PK #
for ($i=0; $i < 1000; $i++) {
DB::table('users')->insert(\[
'user\_uuid' => (string) Uuid::generate(4),
'user\_name' => str\_random(10),
'user\_password' => bcrypt('secret'),
\]);
}
用時 62.20 秒
php artisan db:seed --class=UsersTableSeeder 62.20s user 0.18s system 94% cpu 1:06.03 total
Ticket Table with increment id as PK #
for ($i=0; $i < 1000; $i++) {
DB::table('tickets')->insert(\[
'ticket\_from\_uuid' => (string) Uuid::generate(4),
'tieket\_type' => str\_random(10),
'ticket\_content' => bcrypt(str\_random(10)),
\]);
}
用時 61.53 秒
php artisan db:seed --class=TicketsTableSeeder 61.53s user 0.11s system 94% cpu 1:05.09 total
看上去時間差別不是很大?懷疑是 bcrypt
函數導致的,換個方法,將 bcrypt
函數全部換爲 str_random
並將數據量提升到 5000 後重新測試:
php artisan db:seed --class=UsersTableSeeder 1.58s user 0.78s system 11% cpu 19.808 total
php artisan db:seed –class=TicketsTableSeeder 1.80s user 0.86s system 12% cpu 20.915 total
從這個小的測試我們可以看出如果不考慮容量和其他速度,單純測試單庫插入性能的話,可能對比不是很明顯,文章至此,偶然搜索了一下發現互聯網上已經有了一些非常成熟的測試對比,本着不重複發明輪子的思想,以下給出鏈接:
1. [MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)](https://blog.csdn.net/mchdba/article/details/52336203)
2. [UUID or GUID as Primary Keys? Be Careful!](https://tomharrisonjr.com/uuid-or-guid-as-primary-keys-be-careful-7b2aa3dcb439)