两个datatable合并 主键一样覆盖_MySQL 建表为啥还设置个自增 id ?用流水号当主键不正好么?...
我:吧啦吧啦吧啦 ……
老大:這個(gè)建表為啥還設(shè)置個(gè)自增 id ?直接用流水號(hào)(用戶(hù)號(hào)/產(chǎn)品號(hào))當(dāng)主鍵不就行了?
我:這個(gè)是 DBA 規(guī)定的,創(chuàng)建表 id、createtime、updatetime 這三個(gè)字段都要有。《Java 開(kāi)發(fā)規(guī)范》也是這么規(guī)定的。
小伙伴:(附和)是的,規(guī)定的是這樣的!
老大:流水號(hào)在你這是唯一索引吧?設(shè)置成主鍵,這樣就不用 id 了,還減少一次回表查詢(xún)?
我:…… (說(shuō)的好像很有道理,咱也不敢說(shuō)話(huà)。)
老大:既然他們規(guī)定了,那你回去查一下為什么要設(shè)計(jì)個(gè)自增 id ?
我:掏出小本本(回去查資料~)。
公眾號(hào):liuzhihangs,記錄工作學(xué)習(xí)中的技術(shù)、開(kāi)發(fā)及源碼筆記;時(shí)不時(shí)分享一些生活中的見(jiàn)聞感悟。歡迎大佬來(lái)指導(dǎo)!
建表規(guī)約
在工作中,創(chuàng)建表的時(shí)候,DBA 也會(huì)審核一下建表 SQL,檢查是否符合規(guī)范以及常用字段是否設(shè)置索引。
CREATE TABLE `xxxx` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
`create_time` datetime(3) NOT NULL DEFAULT current_timestamp(3) COMMENT '創(chuàng)建時(shí)間',
`update_time` datetime(3) NOT NULL DEFAULT current_timestamp(3) ON UPDATE current_timestamp(3) COMMENT '更新時(shí)間',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_create_time` (`create_time`) USING BTREE,
KEY `idx_update_time` (`update_time`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='表注釋';
所以在我使用的過(guò)程中,流水號(hào)都是單獨(dú)設(shè)置了一個(gè)字段,比如叫 transno,但是這次就遇到了疑問(wèn):transno 既然是唯一的,那為什么不直接用 trans_no 當(dāng)做 id 呢?
下面開(kāi)始通過(guò)查閱相關(guān)資料,一步一步的了解是為什么?
主鍵
什么是主鍵
https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glosprimarykey
這段定義咱們主要關(guān)注最后一句:
When choosing primary key values, consider using arbitrary values (a synthetic key) rather than relying on values derived from some other source (a natural key).意思是創(chuàng)建主鍵的時(shí)候盡量使用 MySQL 自增主鍵而不是使用業(yè)務(wù)生成的值當(dāng)做主鍵。
主鍵的特征
簡(jiǎn)而言之:
非空、唯一、少更改或不更改 。
如何添加主鍵
可以在 create 創(chuàng)建表的時(shí)候指定,也可以使用 alter 語(yǔ)句后面添加主鍵,不過(guò)官方建議在創(chuàng)建表時(shí)就指定。
為什么要添加主鍵
1. 聲明主鍵,InnoDB 會(huì)將主鍵作為聚簇索引。
2. 未聲明時(shí),會(huì)在 UNIQUE 所有鍵列所在位置找到第一個(gè)索引,NOT NULL 并將其作為聚簇索引
3. 未聲明且找不到合適的 UNIQUE 索引,則內(nèi)部生成一個(gè)隱藏的聚簇索引 GENCLUSTINDEX,這個(gè)隱藏的行 ID 是 6 字節(jié)且單調(diào)增加。
索引
這里僅介紹 InnoDB 引擎,具體可以參考官方文檔,并且介紹的相對(duì)比較簡(jiǎn)單。
索引分類(lèi)
>補(bǔ)充:
>
>回表:先在二級(jí)索引查詢(xún)到對(duì)應(yīng)的主鍵值,然后根據(jù)主鍵再去聚簇索引里面取查詢(xún)。
>索引覆蓋:二級(jí)索引記錄了主鍵列和二級(jí)索引列,如果我只查詢(xún)主鍵列的值和二級(jí)索引列的值,那就不需要回表了。
索引的物理結(jié)構(gòu)
InnoDB 使用的 B+ 數(shù)數(shù)據(jù)結(jié)構(gòu),根據(jù)聚簇索引值(主鍵/UNQIUE/或者自己生成)構(gòu)建一顆 B+ 樹(shù),葉子節(jié)點(diǎn)中存放行記錄數(shù)據(jù),所以每個(gè)葉子節(jié)點(diǎn)也可以叫數(shù)據(jù)頁(yè)。每個(gè)數(shù)據(jù)頁(yè)大小默認(rèn)為 16k,支持自定義。
數(shù)據(jù)的插入
當(dāng)數(shù)據(jù)插入時(shí),InnoDB 會(huì)使頁(yè)面 1/16 空閑,以備將來(lái)插入和更新索引記錄。
在隨機(jī)插入中,會(huì)頻繁的移動(dòng)、分頁(yè),從而造成大量的碎片,并且使索引樹(shù)不夠緊湊。而使用順序插入的方式,則數(shù)據(jù)比較緊湊,有更高的空間利用率。
總結(jié)
Q&A
Q: 什么是回表和索引覆蓋?
A:
Q: 為什么要設(shè)置自增主鍵 id ?
A:
結(jié)束語(yǔ)
本文主要通過(guò)查閱資料,了解為什么要設(shè)置一個(gè)和業(yè)務(wù)無(wú)關(guān)的自增 id 用來(lái)當(dāng)做主鍵,很多內(nèi)容比較淺顯,比如 InnoDB 的 B+ 樹(shù),頁(yè)分裂及頁(yè)合并,插入過(guò)程等都沒(méi)有進(jìn)行深入研究,有興趣的小伙伴可以更深入的研究下。
同時(shí)在建表時(shí)除了要設(shè)置一個(gè)自增 id 用來(lái)當(dāng)做主鍵,小伙伴們?cè)跇I(yè)務(wù)開(kāi)發(fā)過(guò)程中是否也會(huì)遇到一種情況:用戶(hù)的注銷(xiāo),數(shù)據(jù)的刪除等都是進(jìn)行的邏輯刪除,而不是物理刪除。
總結(jié)
以上是生活随笔為你收集整理的两个datatable合并 主键一样覆盖_MySQL 建表为啥还设置个自增 id ?用流水号当主键不正好么?...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Python】判断是否为 None
- 下一篇: mysql 5.7.17 rpm安装_M