自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

老大問我:“建表為啥還設(shè)置個自增 id ?用流水號當(dāng)主鍵不正好么?”

運維 數(shù)據(jù)庫運維
在工作中,創(chuàng)建表的時候,DBA 也會審核一下建表 SQL,檢查是否符合規(guī)范以及常用字段是否設(shè)置索引。

[[345532]]

前言

" 又要開始新項目了,一頓操作猛如虎,梳理流程加畫圖。這不,開始對流程及表結(jié)構(gòu)了。

我:吧啦吧啦吧啦 ……

老大:這個建表為啥還設(shè)置個自增 id ?直接用流水號(用戶號/產(chǎn)品號)當(dāng)主鍵不就行了?

我:這個是 DBA 規(guī)定的,創(chuàng)建表 id、create_time、update_time 這三個字段都要有。《Java 開發(fā)規(guī)范》也是這么規(guī)定的。

小伙伴:(附和)是的,規(guī)定的是這樣的!

老大:流水號在你這是唯一索引吧?設(shè)置成主鍵,這樣就不用 id 了,還減少一次回表查詢?

我:…… (說的好像很有道理,咱也不敢說話。)

老大:既然他們規(guī)定了,那你回去查一下為什么要設(shè)計個自增 id ?

我:掏出小本本(回去查資料~)。"

 

1.建表規(guī)約

Java 開發(fā)手冊-嵩山版

 

在工作中,創(chuàng)建表的時候,DBA 也會審核一下建表 SQL,檢查是否符合規(guī)范以及常用字段是否設(shè)置索引。

  1. CREATE TABLE `xxxx` ( 
  2.   `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主鍵'
  3.   `create_time` datetime(3) NOT NULL DEFAULT current_timestamp(3) COMMENT '創(chuàng)建時間'
  4.   `update_time` datetime(3) NOT NULL DEFAULT current_timestamp(3) ON UPDATE current_timestamp(3) COMMENT '更新時間'
  5.   PRIMARY KEY (`id`) USING BTREE, 
  6.   KEY `idx_create_time` (`create_time`) USING BTREE, 
  7.   KEY `idx_update_time` (`update_time`) USING BTREE 
  8. ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='表注釋'

所以在我使用的過程中,流水號都是單獨設(shè)置了一個字段,比如叫 trans_no,但是這次就遇到了疑問:trans_no 既然是唯一的,那為什么不直接用 trans_no 當(dāng)做 id 呢?

下面開始通過查閱相關(guān)資料,一步一步的了解是為什么?

 

2.主鍵

什么是主鍵?

MySQL primary key

 

這段定義咱們主要關(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)建主鍵的時候盡量使用 MySQL 自增主鍵而不是使用業(yè)務(wù)生成的值當(dāng)做主鍵。

主鍵的特征

 

簡而言之:

非空、唯一、少更改或不更改 。

如何添加主鍵

 

可以在 create 創(chuàng)建表的時候指定,也可以使用 alter 語句后面添加主鍵,不過官方建議在創(chuàng)建表時就指定。

為什么要添加主鍵

  1. 主鍵可以唯一標(biāo)識這一行數(shù)據(jù),從而保證在刪除更新操作時,只是操作這一行數(shù)據(jù)。
  2. 索引需要,每個 InnoDB 表又有一個特殊的索引,即聚簇索引,用來存儲行數(shù)據(jù)。通常,聚簇索引和主鍵同義。
  • 聲明主鍵,InnoDB 會將主鍵作為聚簇索引。
  • 未聲明時,會在 UNIQUE 所有鍵列所在位置找到第一個索引,NOT NULL 并將其作為聚簇索引
  • 未聲明且找不到合適的 UNIQUE 索引,則內(nèi)部生成一個隱藏的聚簇索引 GEN_CLUST_INDEX,這個隱藏的行 ID 是 6 字節(jié)且單調(diào)增加。

 

3.索引

這里僅介紹 InnoDB 引擎,具體可以參考官方文檔,并且介紹的相對比較簡單。

索引的分類

聚簇索引:表存儲是根據(jù)主鍵列的值組織的,以加快涉及主鍵列的查詢和排序。在介紹主鍵時也對聚簇索引進(jìn)行了介紹。

二級索引:也可以叫輔助索引,在輔助索引中會記錄對應(yīng)的主鍵列以及輔助索引列。根據(jù)輔助索引進(jìn)行搜索的時候,會先根據(jù)輔助索引獲取到對應(yīng)的主鍵列,然后再根據(jù)主鍵去聚簇索引里面搜索。一般不建議主鍵很長,因為主鍵很長輔助索引就會使用更多的空間。

" 補充:

回表:先在二級索引查詢到對應(yīng)的主鍵值,然后根據(jù)主鍵再去聚簇索引里面取查詢。

索引覆蓋:二級索引記錄了主鍵列和二級索引列,如果我只查詢主鍵列的值和二級索引列的值,那就不需要回表了。 "

索引的物理結(jié)構(gòu)

InnoDB 使用的 B+ 數(shù)數(shù)據(jù)結(jié)構(gòu),根據(jù)聚簇索引值(主鍵/UNQIUE/或者自己生成)構(gòu)建一顆 B+ 樹,葉子節(jié)點中存放行記錄數(shù)據(jù),所以每個葉子節(jié)點也可以叫數(shù)據(jù)頁。每個數(shù)據(jù)頁大小默認(rèn)為 16k,支持自定義。

圖:《MySQL 技術(shù)內(nèi)幕 InnoDB 存儲引擎》

 

數(shù)據(jù)的插入

當(dāng)數(shù)據(jù)插入時,InnoDB 會使頁面 1/16 空閑,以備將來插入和更新索引記錄。

  1. 順序插入(升序或降序):會將索引頁剩余的大約 15/16 裝滿
  2. 隨機插入:只會使用容量的 1/2 到 15/16

在隨機插入中,會頻繁的移動、分頁,從而造成大量的碎片,并且使索引樹不夠緊湊。而使用順序插入的方式,則數(shù)據(jù)比較緊湊,有更高的空間利用率。

4.總結(jié)

Q&A

Q: 什么是回表和索引覆蓋?

A:

回表:先在二級索引查詢到對應(yīng)的主鍵值,然后根據(jù)主鍵再去聚簇索引里面取查詢。

索引覆蓋:二級索引記錄了主鍵列和二級索引列,如果我只查詢主鍵列的值和二級索引列的值,那就不需要回表了。

Q: 為什么要設(shè)置自增主鍵 id ?

A:

可以唯一標(biāo)識一行數(shù)據(jù),在 InnoDB 構(gòu)建索引樹的時候會使用主鍵。

自增 id 是順序的,可以保證索引樹上的數(shù)據(jù)比較緊湊,有更高的空間利用率以及減少數(shù)據(jù)頁的分裂合并等操作,提高效率。

一般使用手機號、身份證號作為主鍵等并不能保證順序性。

流水號一般相對較長,比如 28 位,32 位等,過長的話會二級索引占用空間較多。同時為了業(yè)務(wù)需求,流水號具有一定的隨機性。

結(jié)束語

本文主要通過查閱資料,了解為什么要設(shè)置一個和業(yè)務(wù)無關(guān)的自增 id 用來當(dāng)做主鍵,很多內(nèi)容比較淺顯,比如 InnoDB 的 B+ 樹,頁分裂及頁合并,插入過程等都沒有進(jìn)行深入研究,有興趣的小伙伴可以更深入的研究下。

同時在建表時除了要設(shè)置一個自增 id 用來當(dāng)做主鍵,小伙伴們在業(yè)務(wù)開發(fā)過程中是否也會遇到一種情況:用戶的注銷,數(shù)據(jù)的刪除等都是進(jìn)行的邏輯刪除,而不是物理刪除。

本篇文章介紹比較簡陋,不足之處,希望大家多多指正。

相關(guān)資料

[1] MySQL 官方文檔:

https://dev.mysql.com/doc/refman/8.0/en/

 

[2] 《MySQL 技術(shù)內(nèi)幕 InnoDB 存儲引擎》第二版

本文轉(zhuǎn)載自微信公眾號「劉志航」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系劉志航公眾號。

 

責(zé)任編輯:武曉燕 來源: 劉志航
相關(guān)推薦

2024-12-25 15:32:29

2009-09-24 13:49:31

Hibernate自增

2023-12-26 01:09:28

MySQL存儲釋放鎖

2024-12-04 09:36:37

2023-10-24 15:27:33

Mysql自增主鍵

2024-05-29 09:05:17

2011-08-19 09:45:02

DB4O設(shè)置自增ID

2022-11-08 19:30:52

DjangoID自增

2022-06-14 08:01:43

數(shù)據(jù)庫MySQL

2020-08-24 07:19:13

主鍵自增數(shù)據(jù)庫

2018-12-14 15:35:20

MySQL索引數(shù)據(jù)庫

2024-10-24 09:22:30

2010-03-29 14:09:12

Oracle ID 自

2011-08-22 10:47:09

SQL Server流水號

2021-08-04 10:34:00

MySQL主鍵int32

2021-09-28 17:48:20

MySQL主鍵索引

2024-06-14 08:34:36

2024-11-11 00:00:06

MySQLID數(shù)據(jù)類型

2022-06-03 08:12:52

InnoDB插入MySQL

2022-12-06 09:00:11

MySQL自增主鍵查詢
點贊
收藏

51CTO技術(shù)棧公眾號