uuid作為主鍵,還是用自增呢?
我在網上找了好久,有的人說uuid比較好,就是在分庫分表,合併數據什麼的比較容易,也有的人說自增好,到了表的數據多的時候,性能比uuid好得多,到底那種比較好呢?有沒有在真實生產環境的大神,來給出一個完整的解答?
以默認的innodb存儲引擎為例:
做為主鍵時,uuid和自增相比較,自增更適合。原因:1 uuid是無序的, 插入數據時,頁的位置會發生變化,頁分裂,速度慢。2 uuid占的空間大,並且innodb中,別的索引還都要包含主鍵的值,那麼每個索引的空間也都會增大,占的空間大,需要讀數據時一般會認為需要的io次數多。
自增也是有缺點的
可見my bloghttp://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)
#!/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
#!/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 群 236941212oracle,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作為主鍵主要有兩個問題:
- UUID的長度太長了,
- UUDI不是自增的,插入的時候的主鍵索引需要調整和分裂,容易造成聚簇索引碎片
建議不用uuid生成1.長度太長,不利於索引查詢2.沒有時間趨勢,對於應用影響比較大
數據量大的話主鍵自增也不是一個好選擇吧。大量數據灌入的情況下自增也是一筆不小的消耗
推薦閱讀:
※兩個800萬條目的表,相同主鍵,總數差了1個,如何高效的將其找出來?
※考OCP做DBA的職業規劃路線是否具有以下優勢或者特質?歡迎拍磚。
※為什麼我在Sql Server上創建的索引用不上?
※學習 Oracle 資料庫成為 DBA 有什麼好的方法嗎?需要什麼樣的基礎?
※學習Oracle,有什麼好的中文網站或論壇?