uuid作為主鍵,還是用自增呢?

我在網上找了好久,有的人說uuid比較好,就是在分庫分表,合併數據什麼的比較容易,也有的人說自增好,到了表的數據多的時候,性能比uuid好得多,到底那種比較好呢?有沒有在真實生產環境的大神,來給出一個完整的解答?


以默認的innodb存儲引擎為例:

做為主鍵時,uuid和自增相比較,自增更適合。

原因:

1 uuid是無序的, 插入數據時,頁的位置會發生變化,頁分裂,速度慢

2 uuid占的空間大,並且innodb中,別的索引還都要包含主鍵的值,那麼每個索引的空間也都會增大,占的空間大,需要讀數據時一般會認為需要的io次數多

自增也是有缺點的

可見my blog

http://blog.itpub.net/25099483/viewspace-1869361/

http://blog.itpub.net/25099483/viewspace-1869360/

http://blog.itpub.net/25099483/viewspace-1869362/

下面來一個模擬一個場景證明第二個觀點:

思路:

1 建表有三列(主鍵,姓名,性別), 一個表是uuid為主鍵,一個表是自增為主鍵

插入同樣的記錄數

2 對「性別」列加索引,對比索引大小。索引大的占的空間多

mysql&> create table song_auto_inc(id int primary key auto_increment,name varchar(10),sex char(1));
Query OK, 0 rows affected (0.01 sec)

mysql&> create table song_uuid(id varchar(36) primary key ,name varchar(10),sex char(1));
Query OK, 0 rows affected (0.00 sec)

cat insert_auto_inc.sh --插入自增表

#!/bin/bash
while true; do
mysql -h10.13.12.197 -P3306 -uroot -ptest -e "insert into test.song_auto_inc (name,sex) select "name1","1" ;"
done

cat insert_uuid.sh --插入uuid

#!/bin/bash
while true; do
mysql -h10.13.12.197 -P3306 -uroot -ptest -e "insert into test.song_uuid select uuid(),"name1","1" ;"
done

插入數據:

sh insert_auto_inc.sh
sh insert_uuid.sh

mysql&> select count(*) from song_auto_inc;
+----------+
| count(*) |
+----------+
| 197806 | --記錄數一樣
+----------+
1 row in set (0.03 sec)

mysql&> select count(*) from song_uuid;
+----------+
| count(*) |
+----------+
| 197806 | --記錄數一樣
+----------+
1 row in set (0.03 sec)

--去掉兩個表中的碎片

mysql&> optimize table song_auto_inc;
+--------------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------------+----------+----------+-------------------------------------------------------------------+
| test.song_auto_inc | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| test.song_auto_inc | optimize | status | OK |
+--------------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (4.32 sec)

mysql&> optimize table song_uuid;
+----------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+----------------+----------+----------+-------------------------------------------------------------------+
| test.song_uuid | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| test.song_uuid | optimize | status | OK |
+----------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (10.71 sec)

--查看數據文件大小:

-rw-rw---- 1 mysql mysql 8.5K Jul 23 23:10 song_auto_inc.frm
-rw-rw---- 1 mysql mysql 7.0M Jul 23 23:10 song_auto_inc.ibd
-rw-rw---- 1 mysql mysql 8.5K Jul 23 23:13 song_uuid.frm
-rw-rw---- 1 mysql mysql 14M Jul 23 23:13 song_uuid.ibd

加索引

mysql&> create index idx_song_uuid_sex on song_uuid(sex);
Query OK, 0 rows affected (5.51 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql&> create index idx_song_auto_inc_sex on song_auto_inc(sex);
Query OK, 0 rows affected (0.91 sec)
Records: 0 Duplicates: 0 Warnings: 0

再次查看數據文件大小:

-rw-rw---- 1 mysql mysql 8.5K Jul 23 23:19 song_auto_inc.frm
-rw-rw---- 1 mysql mysql 13M Jul 23 23:19 song_auto_inc.ibd
-rw-rw---- 1 mysql mysql 8.5K Jul 23 23:19 song_uuid.frm
-rw-rw---- 1 mysql mysql 24M Jul 23 23:19 song_uuid.ibd

自增主鍵的表大小是 7M

uuid主鍵的表大小是14M

自增主鍵二級索引大小是 13-7=6M

uuid主鍵二級索引大小是 24-14=10M

可以證明第二個觀點。

第一個觀點留給讀者自己驗證

上面的測試是在ucloud(UCloud – 專業雲計算服務商)的mysql5.6的普通udb上完成的,如果對比插入時的性能不滿意,可以使用ssd的udb,ssd的性能非常高。在網上看到https://linux.cn/article-7596-1.html這個文章,裡面用ucloud ssd mysql和別的雲服務商進行對比,可以參考下。

QQ 273002188 歡迎一起學習

QQ 群 236941212

oracle,mysql,PG 相互交流


innodb 中的主鍵是聚簇索引,會把相鄰主鍵的數據安放在相鄰的物理存儲上。如果主鍵不是自增,而是隨機的,那麼頻繁的插入會使 innodb 頻繁地移動磁碟塊,而影響寫入性能。


需要看你索引適應的形式,如果使用 b-tree 索引形式,有序 id 比無需 id 好,如果是 hash 索引,兩個差別不大。

主要原因是索引在磁碟上存儲的形式,常用的 b-tree 索引如果 id 是連續的,那麼數據存儲在相鄰的磁碟上,如果查詢和寫入操作的 id 連續,那麼減少隨機讀寫硬碟的幾率,提升讀寫效率。

所以看你的實際情況,如果你用的是 b-tree 索引,同時記錄比較多,那麼用有序 id 作為索引效率會高很多。具體情況題主可以自己測試一下,差距明顯。


1、如果需要分庫分表,往往是海量數據,這個時候使用UUID不是一個好的選擇。

2、主鍵一般情況下追求短整型,確定好你的整型類型。


自增更好,因為主鍵索引是有序的。


UUID好是好 但是太大了,尤其是針對UUID做索引的時候。我們都推薦用bigint的數字id。

在我們DRDS的實踐中( 分散式關係型資料庫DRDS_水平拆分)的實現方式有比較多種,最高性能的亂序數字方案,和能夠保序的自增方案


http://www.cnblogs.com/ELMND/p/4863577.html 之前寫的一篇文章。 sharding 的id生成方式。 mac 時間 原子自增。


幹嘛不一起用,ID作為索引,UUID作為擴展


總體來說,一定是自增優於UUID。

目前使用的 MySQL 主要以InnoDB類存儲引擎為主,整個表的存儲其實很類似於一個索引組織表。所有的其他B-Tree索引鍵上都需要存儲主鍵信息,所以主鍵的欄位大小會對所有的索引性能都造成較大影響。

而且UUID本身無序,這也會嚴重影響到InnoDB這類存儲結構的表的插入性能。當然,即使不是InnoDB,只是普通的B-Tree類型主鍵索引,同樣會因為主鍵插入位置處於索引的隨機位置,也會對插入性能造成影響。

而自增類型本身是有序的,所以插入的時候位置很容易找到新鍵值的插入位置。


講個不是性能方面的,如果是自增的,爬蟲拿到 api, 一個 for 循環就可以把數據全部拿到了,uuid 會相對費勁些 /(ㄒoㄒ)/~~


使用UUID作為主鍵最大的問題是大表性能問題和索引較大問題,目前手頭有幾個大表正在為此問題頭疼。


謝邀。

在實踐中,是任何時候,都應該使用一個獨立的(自增)整形ID主鍵。


這其實就是一個磁碟的順序IO與隨機IO的差別


使用UUID作為主鍵由於每次插入主鍵的值近似於隨機, 因此每次新紀錄都要被插到現有索引頁得中間某個位置, 此時MySQL不得不為了將新記錄插到合適位置而移動數據, 甚至目

標頁面可能已經被回寫到磁碟上而從緩存中清掉, 此時又要從磁碟上讀回來, 這增加了很多開銷, 同時頻繁的移動、 分頁操作造成了大量的碎片, 得到了不夠緊湊的索引結構, 後續不得不通過OPTIMIZE TABLE來重建表並優化填充頁面。

總結: 如果InnoDB表的數據寫入順序能和B+樹索引的葉子節點順序一致的話, 這時候存取效率是最高的, 也就是下面這幾種情況的存取效率最高:

a、 使用自增列(INT/BIGINT類型)做主鍵, 這時候寫入順序是自增的, 和B+數葉子節點分裂順序一致;

b、 該表不指定自增列做主鍵, 同時也沒有可以被選為主鍵的唯一索引(上面的條件), 這時候InnoDB會選擇內置的ROWID作為主鍵, 寫入順序和ROWID增長順

序一致;

c、 如果一個InnoDB表又沒有顯示主鍵, 又有可以被選擇為主鍵的唯一索引, 但該唯一索引可能不是遞增關係時(例如字元串、 UUID、 多欄位聯合唯一索引的情

況), 該表的存取效率就會比較差。


mysql innodb引擎用自增


以你給出的信息量沒法回答,隨便選一個吧。


UUID作為主鍵主要有兩個問題:

  1. UUID的長度太長了,
  2. UUDI不是自增的,插入的時候的主鍵索引需要調整和分裂,容易造成聚簇索引碎片


建議不用uuid生成

1.長度太長,不利於索引查詢

2.沒有時間趨勢,對於應用影響比較大


數據量大的話主鍵自增也不是一個好選擇吧。大量數據灌入的情況下自增也是一筆不小的消耗


推薦閱讀:

兩個800萬條目的表,相同主鍵,總數差了1個,如何高效的將其找出來?
考OCP做DBA的職業規劃路線是否具有以下優勢或者特質?歡迎拍磚。
為什麼我在Sql Server上創建的索引用不上?
學習 Oracle 資料庫成為 DBA 有什麼好的方法嗎?需要什麼樣的基礎?
學習Oracle,有什麼好的中文網站或論壇?

TAG:後端技術 | MySQL | Java | 資料庫管理員DBA |