最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL唯一索引和主鍵索引的區(qū)別有哪些(面試官常問)

 更新時間:2026年04月15日 08:55:06   作者:皮皮林551  
在數(shù)據(jù)庫設(shè)計中,索引的選擇與使用是優(yōu)化查詢性能的關(guān)鍵,下面這篇文章主要介紹了MySQL唯一索引和主鍵索引區(qū)別有哪些的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

面試考察點(diǎn)

  1. 索引類型理解:面試官不僅僅是想知道 "有什么區(qū)別",更是想考察你是否理解主鍵索引(聚簇索引)和唯一索引(二級索引)在存儲結(jié)構(gòu)上的根本差異。
  2. NULL 值處理:考察你是否清楚主鍵不允許 NULL,而唯一索引可以(但只能有一個),這是很多面試者容易忽略的細(xì)節(jié)。
  3. 性能優(yōu)化意識:理解聚簇索引和非聚簇索引的查詢效率差異,能否在設(shè)計表結(jié)構(gòu)時做出正確選擇。

核心答案

主鍵索引:一種特殊的唯一索引,每張表只能有一個,用于唯一標(biāo)識每一行記錄,InnoDB 中主鍵是 聚簇索引

唯一索引:保證索引列的值唯一,一張表可以有多個唯一索引,InnoDB 中唯一索引是 二級索引(非聚簇索引) 。

核心區(qū)別對比

對比維度主鍵索引(PRIMARY)唯一索引(UNIQUE)
數(shù)量限制每表 只能有 1 個每表 可以有多個
NULL 值不允許 NULL允許 NULL(但最多 1 個)
存儲結(jié)構(gòu)聚簇索引,葉子節(jié)點(diǎn)存完整數(shù)據(jù)二級索引,葉子節(jié)點(diǎn)存主鍵值
索引回表不需要回表需要回表(查詢非索引列時)
創(chuàng)建語法PRIMARY KEY (col)UNIQUE KEY uk_name (col)
是否必須建議有,但不強(qiáng)制按需創(chuàng)建

一句話總結(jié):主鍵是 唯一的聚簇索引,不允許 NULL;唯一索引是 可以有多個的非聚簇索引,允許 NULL。

深度解析

一、存儲結(jié)構(gòu)差異:聚簇索引 vs 二級索引

主鍵索引和唯一索引在 InnoDB 中的存儲結(jié)構(gòu)完全不同:

上圖對比了主鍵索引和唯一索引的存儲結(jié)構(gòu)。關(guān)鍵區(qū)別在于:

  • 主鍵索引(聚簇索引) :葉子節(jié)點(diǎn)直接存儲 完整的行數(shù)據(jù),通過主鍵查詢可以直接獲取所有字段,無需回表
  • 唯一索引(二級索引) :葉子節(jié)點(diǎn)只存儲 索引列的值 + 主鍵值,如果查詢其他字段,需要拿著主鍵值回表查詢聚簇索引

二、NULL 值處理差異

這是面試中的高頻考點(diǎn):

-- 創(chuàng)建測試表
CREATETABLEuser (
    idBIGINT PRIMARY KEY,           -- 主鍵,不允許 NULL
    email VARCHAR(50) UNIQUE,        -- 唯一索引,允許 NULL
    phone VARCHAR(20) UNIQUE         -- 唯一索引,允許 NULL
);
-- 主鍵測試:插入 NULL 會報錯
INSERTINTOuser (id, email) VALUES (NULL, 'test@qq.com');
-- ? ERROR 1048: Column 'id' cannot be null
-- 唯一索引測試:允許 NULL,且 MySQL 中可以插入多個 NULL
INSERTINTOuser (id, email) VALUES (1, NULL);      -- ? 成功
INSERTINTOuser (id, email) VALUES (2, NULL);      -- ? 成功(MySQL 認(rèn)為多個 NULL 不重復(fù))
INSERTINTOuser (id, email) VALUES (3, 'a@qq.com'); -- ? 成功
INSERTINTOuser (id, email) VALUES (4, 'a@qq.com'); -- ? Duplicate entry

關(guān)鍵結(jié)論

  • 主鍵:絕對不允許 NULL,這是主鍵的基本約束
  • 唯一索引:允許 NULL,且 MySQL 中可以插入多個 NULL 值(因?yàn)?nbsp;NULL != NULL

三、查詢性能差異:回表問題

通過主鍵查詢 vs 通過唯一索引查詢的性能差異:

-- 表結(jié)構(gòu)
CREATETABLEuser (
    idBIGINT PRIMARY KEY,
    email VARCHAR(50) UNIQUE,
    nameVARCHAR(50),
    age INT
);
-- 場景 1:通過主鍵查詢
SELECT * FROMuserWHEREid = 1;
-- ? 直接走聚簇索引,一次查詢即可獲取完整數(shù)據(jù)
-- 場景 2:通過唯一索引查詢所有字段
SELECT * FROMuserWHERE email = 'test@qq.com';
-- ?? 需要回表:先查唯一索引得到 id,再回表查聚簇索引
-- 場景 3:通過唯一索引查詢索引列(覆蓋索引)
SELECT email FROMuserWHERE email = 'test@qq.com';
-- ? 覆蓋索引,不需要回表

四、使用場景建議

場景推薦索引類型原因
標(biāo)識每一行記錄主鍵索引每表必須有唯一標(biāo)識,推薦自增 BIGINT
用戶郵箱不能重復(fù)唯一索引業(yè)務(wù)唯一性約束,允許未設(shè)置郵箱(NULL)
手機(jī)號唯一唯一索引允許用戶暫未綁定手機(jī)號
身份證號唯一唯一索引允許 NULL(可能未錄入)
聯(lián)合唯一(用戶 + 日期)聯(lián)合唯一索引UNIQUE KEY uk_user_date (user_id, date)

最佳實(shí)踐

-- 推薦:使用 BIGINT 自增主鍵
CREATETABLE orders (
    idBIGINTUNSIGNED AUTO_INCREMENT PRIMARY KEY,
    order_no VARCHAR(32) UNIQUENOTNULL,  -- 業(yè)務(wù)訂單號,不允許 NULL
    user_id BIGINTNOTNULL,
    INDEX idx_user (user_id)
);
-- 不推薦:沒有主鍵的表
-- MySQL 會自動選擇一個非空唯一索引作為聚簇索引
-- 如果沒有合適的,會生成一個隱藏的 6 字節(jié)主鍵

五、如果沒有主鍵會怎樣?

InnoDB 要求每張表必須有聚簇索引:

面試高頻追問

  1. 追問一:為什么推薦使用自增主鍵而不是 UUID?
    • 答:自增主鍵是順序插入的,B+ 樹葉子節(jié)點(diǎn)順序追加,不會產(chǎn)生頁分裂;UUID 是無序的,插入會導(dǎo)致頻繁頁分裂,影響性能。此外,UUID 占用空間大(36 字符 vs 8 字節(jié)),降低索引效率。
  2. 追問二:一張表可以沒有主鍵嗎?
    • 答:可以,但 InnoDB 會自動選擇一個非空唯一索引作為聚簇索引;如果沒有合適的,會生成隱藏的 6 字節(jié) ROW_ID。但強(qiáng)烈不建議這樣做,應(yīng)該顯式定義主鍵。
  3. 追問三:聯(lián)合主鍵和聯(lián)合唯一索引有什么區(qū)別?
    • 答:本質(zhì)區(qū)別和單列一樣——聯(lián)合主鍵是聚簇索引,不允許任何列為 NULL;聯(lián)合唯一索引是二級索引,允許列為 NULL。

常見面試變體

  • "主鍵索引和唯一索引有什么區(qū)別?"
  • "聚簇索引和非聚簇索引的區(qū)別是什么?"
  • "MySQL 查詢走唯一索引時為什么可能需要回表?"
  • "唯一索引允許 NULL 嗎?主鍵呢?"

記憶口訣

主鍵 vs 唯一索引

  1. 主鍵聚簇:葉子存完整數(shù)據(jù),查詢不回表
  2. 唯一二級:葉子存主鍵值,查詢需回表
  3. NULL 有別:主鍵不允許,唯一索引可以
  4. 數(shù)量不同:主鍵唯一一個,唯一索引多個

總結(jié)

主鍵索引是 聚簇索引,每表只能有一個,不允許 NULL,葉子節(jié)點(diǎn)存儲完整行數(shù)據(jù);唯一索引是 二級索引,可以有多個,允許 NULL(可多個),葉子節(jié)點(diǎn)存儲主鍵值。查詢時主鍵直接獲取數(shù)據(jù),唯一索引需要回表。推薦使用 BIGINT 自增主鍵,業(yè)務(wù)唯一約束用唯一索引。

到此這篇關(guān)于MySQL唯一索引和主鍵索引的區(qū)別有哪些的文章就介紹到這了,更多相關(guān)MySQL唯一索引和主鍵索引區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL數(shù)據(jù)庫觸發(fā)器從小白到精通

    MySQL數(shù)據(jù)庫觸發(fā)器從小白到精通

    觸發(fā)器是SQLserver提供給程序員和數(shù)據(jù)分析員來保證數(shù)據(jù)完整性的一種方法,它是與表事件相關(guān)的特殊的存儲過程,它的執(zhí)行不是由程序調(diào)用,也不是手工啟動,而是由事件來觸發(fā),比如當(dāng)對一個表進(jìn)行操作時就會激活它執(zhí)行。觸發(fā)器經(jīng)常用于加強(qiáng)數(shù)據(jù)的完整性約束和業(yè)務(wù)規(guī)則等
    2022-03-03
  • 淺談Mysql主鍵索引與非主鍵索引區(qū)別

    淺談Mysql主鍵索引與非主鍵索引區(qū)別

    本文主要介紹了ysql主鍵索引與非主鍵索引區(qū)別,文中介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09
  • MYSQL 解鎖與鎖表介紹

    MYSQL 解鎖與鎖表介紹

    相對其他數(shù)據(jù)庫而言,MySQL的鎖機(jī)制比較簡單,其最顯著的特點(diǎn)是不同的存儲引擎支持不同的鎖機(jī)制
    2017-04-04
  • MySQL字段自增自減的SQL語句示例介紹

    MySQL字段自增自減的SQL語句示例介紹

    MySQL的自增語句大家應(yīng)該都很熟悉,本文為大家介紹下MySQL字段自增自減的SQL語句,需要的朋友可以參考下
    2014-02-02
  • 解決mysql ERROR 1017:Can''t find file: ''/xxx.frm'' 錯誤

    解決mysql ERROR 1017:Can''t find file: ''/xxx.frm'' 錯誤

    如果重啟服務(wù)器前沒有關(guān)閉mysql,MySql的MyiSAM表很有可能會出現(xiàn) ERROR #1017 :Can't find file: '/xxx.frm' 的錯誤
    2011-08-08
  • 一文詳解MySQL在Docker中的部署與數(shù)據(jù)持久化指南

    一文詳解MySQL在Docker中的部署與數(shù)據(jù)持久化指南

    這篇文章主要為大家詳細(xì)介紹了在Docker中運(yùn)行MySQL時確保數(shù)據(jù)持久化的關(guān)鍵方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2026-02-02
  • mysql?中的備份恢復(fù),分區(qū)分表,主從復(fù)制,讀寫分離

    mysql?中的備份恢復(fù),分區(qū)分表,主從復(fù)制,讀寫分離

    這篇文章主要介紹了mysql?中的備份恢復(fù),分區(qū)分表,主從復(fù)制,讀寫分離,文章圍繞主題展開詳細(xì)的內(nèi)容戒殺,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • MySQL的InnoDB引擎入門學(xué)習(xí)教程

    MySQL的InnoDB引擎入門學(xué)習(xí)教程

    這篇文章主要介紹了MySQL的InnoDB引擎入門學(xué)習(xí)教程,對InnoDB的存儲結(jié)構(gòu)有一個較好的總結(jié),需要的朋友可以參考下
    2015-11-11
  • MySQL WorkBench管理操作MySQL教程

    MySQL WorkBench管理操作MySQL教程

    MySQL Workbench提供DBAs和developers一個集成工具環(huán)境,方便管理mysql數(shù)據(jù)庫,這里簡單介紹下MySQL Workbench使用方法,需要的朋友可以參考下
    2014-03-03
  • mysql居然還能實(shí)現(xiàn)分布式鎖的方法

    mysql居然還能實(shí)現(xiàn)分布式鎖的方法

    這篇文章主要介紹了mysql居然還能實(shí)現(xiàn)分布式鎖的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論

玉林市| 长岭县| 获嘉县| 满洲里市| 绵阳市| 新余市| 宿州市| 威信县| 双流县| 霍州市| 怀安县| 辰溪县| 吉安县| 托克托县| 司法| 咸丰县| 玛纳斯县| 顺昌县| 田东县| 江油市| 长白| 都兰县| 盐边县| 眉山市| 修武县| 南汇区| 余江县| 霍州市| 壤塘县| 通榆县| 始兴县| 开阳县| 甘南县| 庆阳市| 东明县| 错那县| 柳江县| 吉木萨尔县| 微山县| 固始县| 铁力市|