91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

id的機(jī)制不同在mysql的索引結(jié)構(gòu)以及優(yōu)缺點(diǎn)

jf_ro2CN3Fa ? 來(lái)源:芋道源碼 ? 2023-06-30 10:19 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

一、mysql和程序?qū)嵗?/p>

1.1.要說明這個(gè)問題,我們首先來(lái)建立三張表

1.2.光有理論不行,直接上程序,使用spring的jdbcTemplate來(lái)實(shí)現(xiàn)增查測(cè)試:

1.3.程序?qū)懭虢Y(jié)果

1.4.效率測(cè)試結(jié)果

二、使用uuid和自增id的索引結(jié)構(gòu)對(duì)比

2.1.使用自增id的內(nèi)部結(jié)構(gòu)

2.2.使用uuid的索引內(nèi)部結(jié)構(gòu)

2.3.使用自增id的缺點(diǎn)

三、總結(jié)

65b32dc2-16e6-11ee-962d-dac502259ad0.jpg

前言

在mysql中設(shè)計(jì)表的時(shí)候,mysql官方推薦不要使用uuid或者不連續(xù)不重復(fù)的雪花id(long形且唯一,單機(jī)遞增),而是推薦連續(xù)自增的主鍵id,官方的推薦是auto_increment,那么為什么不建議采用uuid,使用uuid究竟有什么壞處?

本篇博客我們就來(lái)分析這個(gè)問題,探討一下內(nèi)部的原因。

本篇博客的目錄

mysql程序?qū)嵗?使用uuid和自增id的索引結(jié)構(gòu)對(duì)比 總結(jié)

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

一、mysql和程序?qū)嵗?/p>

1.1.要說明這個(gè)問題,我們首先來(lái)建立三張表

分別是user_auto_key,user_uuid,user_random_key,分別表示自動(dòng)增長(zhǎng)的主鍵,uuid作為主鍵,隨機(jī)key作為主鍵,其它我們完全保持不變.

根據(jù)控制變量法,我們只把每個(gè)表的主鍵使用不同的策略生成,而其他的字段完全一樣,然后測(cè)試一下表的插入速度和查詢速度:

注:這里的隨機(jī)key其實(shí)是指用雪花算法算出來(lái)的前后不連續(xù)不重復(fù)無(wú)規(guī)律的id:一串18位長(zhǎng)度的long值

id自動(dòng)生成表:

65d4119a-16e6-11ee-962d-dac502259ad0.jpg

用戶uuid表

65ef7ba6-16e6-11ee-962d-dac502259ad0.jpg

隨機(jī)主鍵表:

66043e56-16e6-11ee-962d-dac502259ad0.png

1.2.光有理論不行,直接上程序,使用spring的jdbcTemplate來(lái)實(shí)現(xiàn)增查測(cè)試:

技術(shù)框架:springboot+jdbcTemplate+junit+hutool,程序的原理就是連接自己的測(cè)試數(shù)據(jù)庫(kù),然后在相同的環(huán)境下寫入同等數(shù)量的數(shù)據(jù),來(lái)分析一下insert插入的時(shí)間來(lái)進(jìn)行綜合其效率,為了做到最真實(shí)的效果,所有的數(shù)據(jù)采用隨機(jī)生成,比如名字、郵箱、地址都是隨機(jī)生成。

packagecom.wyq.mysqldemo;
importcn.hutool.core.collection.CollectionUtil;
importcom.wyq.mysqldemo.databaseobject.UserKeyAuto;
importcom.wyq.mysqldemo.databaseobject.UserKeyRandom;
importcom.wyq.mysqldemo.databaseobject.UserKeyUUID;
importcom.wyq.mysqldemo.diffkeytest.AutoKeyTableService;
importcom.wyq.mysqldemo.diffkeytest.RandomKeyTableService;
importcom.wyq.mysqldemo.diffkeytest.UUIDKeyTableService;
importcom.wyq.mysqldemo.util.JdbcTemplateService;
importorg.junit.jupiter.api.Test;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.util.StopWatch;
importjava.util.List;
@SpringBootTest
classMysqlDemoApplicationTests{

@Autowired
privateJdbcTemplateServicejdbcTemplateService;

@Autowired
privateAutoKeyTableServiceautoKeyTableService;

@Autowired
privateUUIDKeyTableServiceuuidKeyTableService;

@Autowired
privateRandomKeyTableServicerandomKeyTableService;


@Test
voidtestDBTime(){

StopWatchstopwatch=newStopWatch("執(zhí)行sql時(shí)間消耗");


/**
*auto_incrementkey任務(wù)
*/
finalStringinsertSql="INSERTINTOuser_key_auto(user_id,user_name,sex,address,city,email,state)VALUES(?,?,?,?,?,?,?)";

ListinsertData=autoKeyTableService.getInsertData();
stopwatch.start("自動(dòng)生成key表任務(wù)開始");
longstart1=System.currentTimeMillis();
if(CollectionUtil.isNotEmpty(insertData)){
booleaninsertResult=jdbcTemplateService.insert(insertSql,insertData,false);
System.out.println(insertResult);
}
longend1=System.currentTimeMillis();
System.out.println("autokey消耗的時(shí)間:"+(end1-start1));

stopwatch.stop();


/**
*uudID的key
*/
finalStringinsertSql2="INSERTINTOuser_uuid(id,user_id,user_name,sex,address,city,email,state)VALUES(?,?,?,?,?,?,?,?)";

ListinsertData2=uuidKeyTableService.getInsertData();
stopwatch.start("UUID的key表任務(wù)開始");
longbegin=System.currentTimeMillis();
if(CollectionUtil.isNotEmpty(insertData)){
booleaninsertResult=jdbcTemplateService.insert(insertSql2,insertData2,true);
System.out.println(insertResult);
}
longover=System.currentTimeMillis();
System.out.println("UUIDkey消耗的時(shí)間:"+(over-begin));

stopwatch.stop();


/**
*隨機(jī)的long值key
*/
finalStringinsertSql3="INSERTINTOuser_random_key(id,user_id,user_name,sex,address,city,email,state)VALUES(?,?,?,?,?,?,?,?)";
ListinsertData3=randomKeyTableService.getInsertData();
stopwatch.start("隨機(jī)的long值key表任務(wù)開始");
Longstart=System.currentTimeMillis();
if(CollectionUtil.isNotEmpty(insertData)){
booleaninsertResult=jdbcTemplateService.insert(insertSql3,insertData3,true);
System.out.println(insertResult);
}
Longend=System.currentTimeMillis();
System.out.println("隨機(jī)key任務(wù)消耗時(shí)間:"+(end-start));
stopwatch.stop();


Stringresult=stopwatch.prettyPrint();
System.out.println(result);
}

1.3.程序?qū)懭虢Y(jié)果

user_key_auto寫入結(jié)果:

661f2fd6-16e6-11ee-962d-dac502259ad0.png

user_random_key寫入結(jié)果:

66459d6a-16e6-11ee-962d-dac502259ad0.png

user_uuid表寫入結(jié)果:

66989fc4-16e6-11ee-962d-dac502259ad0.png

1.4.效率測(cè)試結(jié)果

66f5c6e0-16e6-11ee-962d-dac502259ad0.png

在已有數(shù)據(jù)量為130W的時(shí)候:我們?cè)賮?lái)測(cè)試一下插入10w數(shù)據(jù),看看會(huì)有什么結(jié)果:

670c64a4-16e6-11ee-962d-dac502259ad0.png

可以看出在數(shù)據(jù)量100W左右的時(shí)候,uuid的插入效率墊底,并且在后序增加了130W的數(shù)據(jù),uudi的時(shí)間又直線下降。

時(shí)間占用量總體可以打出的效率排名為:auto_key>random_key>uuid,uuid的效率最低,在數(shù)據(jù)量較大的情況下,效率直線下滑。那么為什么會(huì)出現(xiàn)這樣的現(xiàn)象呢?帶著疑問,我們來(lái)探討一下這個(gè)問題:

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

二、使用uuid和自增id的索引結(jié)構(gòu)對(duì)比

2.1.使用自增id的內(nèi)部結(jié)構(gòu)

67213ca8-16e6-11ee-962d-dac502259ad0.png

自增的主鍵的值是順序的,所以Innodb把每一條記錄都存儲(chǔ)在一條記錄的后面。當(dāng)達(dá)到頁(yè)面的最大填充因子時(shí)候(innodb默認(rèn)的最大填充因子是頁(yè)大小的15/16,會(huì)留出1/16的空間留作以后的 修改):

①下一條記錄就會(huì)寫入新的頁(yè)中,一旦數(shù)據(jù)按照這種順序的方式加載,主鍵頁(yè)就會(huì)近乎于順序的記錄填滿,提升了頁(yè)面的最大填充率,不會(huì)有頁(yè)的浪費(fèi)

②新插入的行一定會(huì)在原有的最大數(shù)據(jù)行下一行,mysql定位和尋址很快,不會(huì)為計(jì)算新行的位置而做出額外的消耗

③減少了頁(yè)分裂和碎片的產(chǎn)生

2.2.使用uuid的索引內(nèi)部結(jié)構(gòu)

67332436-16e6-11ee-962d-dac502259ad0.jpg

因?yàn)閡uid相對(duì)順序的自增id來(lái)說是毫無(wú)規(guī)律可言的,新行的值不一定要比之前的主鍵的值要大,所以innodb無(wú)法做到總是把新行插入到索引的最后,而是需要為新行尋找新的合適的位置從而來(lái)分配新的空間。

這個(gè)過程需要做很多額外的操作,數(shù)據(jù)的毫無(wú)順序會(huì)導(dǎo)致數(shù)據(jù)分布散亂,將會(huì)導(dǎo)致以下的問題:

①寫入的目標(biāo)頁(yè)很可能已經(jīng)刷新到磁盤上并且從緩存上移除,或者還沒有被加載到緩存中,innodb在插入之前不得不先找到并從磁盤讀取目標(biāo)頁(yè)到內(nèi)存中,這將導(dǎo)致大量的隨機(jī)IO

②因?yàn)閷懭胧莵y序的,innodb不得不頻繁的做頁(yè)分裂操作,以便為新的行分配空間,頁(yè)分裂導(dǎo)致移動(dòng)大量的數(shù)據(jù),一次插入最少需要修改三個(gè)頁(yè)以上

③由于頻繁的頁(yè)分裂,頁(yè)會(huì)變得稀疏并被不規(guī)則的填充,最終會(huì)導(dǎo)致數(shù)據(jù)會(huì)有碎片

在把隨機(jī)值(uuid和雪花id)載入到聚簇索引(innodb默認(rèn)的索引類型)以后,有時(shí)候會(huì)需要做一次OPTIMEIZE TABLE來(lái)重建表并優(yōu)化頁(yè)的填充,這將又需要一定的時(shí)間消耗。

結(jié)論:使用innodb應(yīng)該盡可能的按主鍵的自增順序插入,并且盡可能使用單調(diào)的增加的聚簇鍵的值來(lái)插入新行

2.3.使用自增id的缺點(diǎn)

那么使用自增的id就完全沒有壞處了嗎?并不是,自增id也會(huì)存在以下幾點(diǎn)問題:

①別人一旦爬取你的數(shù)據(jù)庫(kù),就可以根據(jù)數(shù)據(jù)庫(kù)的自增id獲取到你的業(yè)務(wù)增長(zhǎng)信息,很容易分析出你的經(jīng)營(yíng)情況

②對(duì)于高并發(fā)的負(fù)載,innodb在按主鍵進(jìn)行插入的時(shí)候會(huì)造成明顯的鎖爭(zhēng)用,主鍵的上界會(huì)成為爭(zhēng)搶的熱點(diǎn),因?yàn)樗械牟迦攵及l(fā)生在這里,并發(fā)插入會(huì)導(dǎo)致間隙鎖競(jìng)爭(zhēng)

③Auto_Increment鎖機(jī)制會(huì)造成自增鎖的搶奪,有一定的性能損失

附:Auto_increment的鎖爭(zhēng)搶問題,如果要改善需要調(diào)優(yōu)innodb_autoinc_lock_mode的配置

三、總結(jié)

本篇博客首先從開篇的提出問題,建表到使用jdbcTemplate去測(cè)試不同id的生成策略在大數(shù)據(jù)量的數(shù)據(jù)插入表現(xiàn),然后分析了id的機(jī)制不同在mysql的索引結(jié)構(gòu)以及優(yōu)缺點(diǎn),深入的解釋了為何uuid和隨機(jī)不重復(fù)id在數(shù)據(jù)插入中的性能損耗,詳細(xì)的解釋了這個(gè)問題。

在實(shí)際的開發(fā)中還是根據(jù)mysql的官方推薦最好使用自增id,mysql博大精深,內(nèi)部還有很多值得優(yōu)化的點(diǎn)需要我們學(xué)習(xí)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 磁盤
    +關(guān)注

    關(guān)注

    1

    文章

    398

    瀏覽量

    26489
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    4020

    瀏覽量

    68365
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    906

    瀏覽量

    29554

原文標(biāo)題:用雪花 id 和 uuid 做 MySQL 主鍵,被領(lǐng)導(dǎo)懟了

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    MySQL索引的創(chuàng)建與刪除

    MySQL——索引技巧以及注意事項(xiàng)
    發(fā)表于 10-31 09:27

    mysql索引使用技巧有哪些?

    mysql索引使用技巧
    發(fā)表于 05-20 06:09

    Oracle與MySQL優(yōu)缺點(diǎn)和使用區(qū)別

    關(guān)系型數(shù)據(jù)庫(kù)(Oracle與MySQL優(yōu)缺點(diǎn)、使用區(qū)別)
    發(fā)表于 06-04 16:48

    MySQL索引使用優(yōu)化和規(guī)范

    MySQL - 索引使用優(yōu)化和規(guī)范
    發(fā)表于 06-15 16:01

    闡述FreeRTOS系統(tǒng)中的機(jī)制及在應(yīng)用中的優(yōu)缺點(diǎn)

    :FreeRTOS是一個(gè)源碼公開的免費(fèi)的嵌入式實(shí)時(shí)操作系統(tǒng),通過研究其內(nèi)核可以更好地理解嵌入式操作系統(tǒng)的實(shí)現(xiàn)原理.本文主要闡述FreeRTOS系統(tǒng)中的任務(wù)調(diào)度機(jī)制、時(shí)間管理機(jī)制、任務(wù)管理機(jī)制
    發(fā)表于 12-20 06:34

    DMA的傳輸過程與優(yōu)缺點(diǎn)

    系列索引:《嵌入式系統(tǒng)原理與應(yīng)用》 | 嵌入式系統(tǒng) 重點(diǎn)知識(shí)梳理目錄DMA的定義及傳輸要素DMA的傳輸過程DMA的優(yōu)缺點(diǎn)及其適用場(chǎng)景STM32中DMA的特點(diǎn)STM32中DMA的優(yōu)先級(jí)機(jī)制STM32中
    發(fā)表于 12-22 06:15

    開關(guān)電源拓?fù)?b class='flag-5'>結(jié)構(gòu)優(yōu)缺點(diǎn)

    開關(guān)電源的相關(guān)知識(shí)學(xué)習(xí)教材資料——開關(guān)電源拓?fù)?b class='flag-5'>結(jié)構(gòu)優(yōu)缺點(diǎn)
    發(fā)表于 09-20 16:10 ?0次下載

    MySQL索引使用原則

    一般來(lái)說, MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的結(jié)構(gòu)來(lái)存儲(chǔ)的,也就是所有實(shí)際需要的數(shù)據(jù)都存放于 Tree 的 Leaf Node(葉子節(jié)點(diǎn)) ,而且
    的頭像 發(fā)表于 02-11 15:17 ?3292次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>索引</b>使用原則

    MySQL索引的使用問題

    一、前言 在MySQL中進(jìn)行SQL優(yōu)化的時(shí)候,經(jīng)常會(huì)在一些情況下,對(duì)MySQL能否利用索引有一些迷惑。譬如:1、MySQL 在遇到范圍查詢條件的時(shí)候就停止匹配了,那么到底是哪些范圍條件
    的頭像 發(fā)表于 01-06 16:13 ?2141次閱讀

    MySQL高級(jí)進(jìn)階:索引優(yōu)化

    MySQL官方對(duì)于索引的定義:索引是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
    的頭像 發(fā)表于 06-11 11:13 ?1322次閱讀
    <b class='flag-5'>MySQL</b>高級(jí)進(jìn)階:<b class='flag-5'>索引</b>優(yōu)化

    MySQL為什么選擇B+樹作為索引結(jié)構(gòu)?

    MySQL中,無(wú)論是Innodb還是MyIsam,都使用了B+樹作索引結(jié)構(gòu)(這里不考慮hash等其他索引)。本文將從最普通的二叉查找樹開始,逐步說明各種樹解決的問題
    的頭像 發(fā)表于 07-20 11:28 ?1727次閱讀
    <b class='flag-5'>MySQL</b>為什么選擇B+樹作為<b class='flag-5'>索引</b><b class='flag-5'>結(jié)構(gòu)</b>?

    MySQL索引的常用知識(shí)點(diǎn)

    索引結(jié)構(gòu):B+樹 索引其實(shí)是一種數(shù)據(jù)結(jié)構(gòu) 注意B+樹是MySQL,索引默認(rèn)的
    的頭像 發(fā)表于 09-30 16:43 ?1050次閱讀

    索引是什么意思 優(yōu)缺點(diǎn)有哪些

    的數(shù)據(jù)結(jié)構(gòu),以協(xié)助快速查詢、更新數(shù)據(jù)庫(kù)表中數(shù)據(jù)。索引的實(shí)現(xiàn)通常使用B樹及其變種B+樹。更通俗的說,索引就相當(dāng)于目錄。為了方便查找書中的內(nèi)容,通過對(duì)內(nèi)容建立索引形成目錄。而且
    的頭像 發(fā)表于 10-09 10:19 ?4814次閱讀

    導(dǎo)致MySQL索引失效的情況以及相應(yīng)的解決方法

    導(dǎo)致MySQL索引失效的情況以及相應(yīng)的解決方法? MySQL索引的目的是提高查詢效率,但有些情況下索引
    的頭像 發(fā)表于 12-28 10:01 ?1762次閱讀

    一文了解MySQL索引機(jī)制

    的呢?一起靜下心來(lái),耐心看完這篇文章吧,干貨不啰嗦,相信你一定會(huì)有所收獲。 一、索引模型 模型也就是數(shù)據(jù)結(jié)構(gòu),常見的三種模型分別是哈希表、有序數(shù)組和搜索樹。 了解MySQL的朋友已經(jīng)知道,現(xiàn)在
    的頭像 發(fā)表于 07-25 14:05 ?945次閱讀
    一文了解<b class='flag-5'>MySQL</b><b class='flag-5'>索引</b><b class='flag-5'>機(jī)制</b>