<table id="km2im"></table>
  • <bdo id="km2im"><center id="km2im"></center></bdo>
    • 自動秒收錄
    • 軟件:1973
    • 資訊:56292|
    • 收錄網站:186523|

    IT精英團

    MySQL為什么不能用uuid作為主鍵?

    MySQL為什么不能用uuid作為主鍵?

    瀏覽次數:
    評論次數:
    編輯: 陽煦
    信息來源: ITPUB
    更新日期: 2022-05-25 21:02:59
    摘要

    前言在mysql中設計表的時候,mysql官方推薦不要使用uuid或者不連續不重復的雪花id(long形且唯一,單機遞增),而是推薦連續自增的主鍵id,官方的推薦是auto_increment,那么為

    • 正文開始
    • 相關閱讀
    • 推薦作品

    前言

    在mysql中設計表的時候,mysql官方建議不要使用uuid或者不連續不重復的雪花id(長且唯一,單機遞增),而是推薦連續自增的主鍵id。官方推薦是auto_increment,那為什么不用uuid呢?使用uuid的缺點是什么?在這篇博客中,我們將分析這個問題,并討論其內在原因。這個博客目錄mysql程序的例子

    使用uuid和自增長id的索引結構的比較

    摘要

    一、mysql和程序實例

    1.1.要說明這個問題,我們首先來建立三張表

    分別是user _ auto _ key、user _ uuid、user _ random _ key,分別代表自動增長主鍵,uuid為主鍵,random key為主鍵。其余的完全沒變。按照控制變量法,我們只使用不同的策略生成每個表的主鍵,其他字段完全一樣,然后測試表的插入速度和查詢速度。注意:這里的隨機鍵其實指的是雪花算法。

    自動id生成表:

    用戶uuid表

    隨機主鍵表:

    1.2.光有理論不行,直接上程序,使用spring的jdbcTemplate來實現增查測試:

    技術框架:Spring Boot JDBC模板JUnit胡工具。程序的原理是連接你自己的測試數據庫,然后在同樣的環境下寫同樣的數據量分析插入時間來合成它的效率。為了達到最真實的效果,所有數據都是隨機生成的,比如姓名、郵箱、地址。package com . wyq . MySQL demo;

    import cn . Hu tool . core . collection . collection util;

    import com . wyq . MySQL demo . database object . userkeyauto;

    import com . wyq . MySQL demo . database object . userkeyrandom;

    import com . wyq . MySQL demo . database object . userkeyuuid;

    import com . wyq . MySQL demo . diffkeytest . autokeytableservice;

    import com . wyq . MySQL demo . diffkeytest . randomkeytableservice;

    進口nb

    sp;com.wyq.mysqldemo.diffkeytest.UUIDKeyTableService;
    import com.wyq.mysqldemo.util.JdbcTemplateService;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.util.StopWatch;
    import java.util.List;
    @SpringBootTest
    class MysqlDemoApplicationTests {

        @Autowired
        private JdbcTemplateService jdbcTemplateService;

        @Autowired
        private AutoKeyTableService autoKeyTableService;

        @Autowired
        private UUIDKeyTableService uuidKeyTableService;

        @Autowired
        private RandomKeyTableService randomKeyTableService;


        @Test
        void testDBTime() {

            StopWatch stopwatch = new StopWatch("執行sql時間消耗");


            /**
             * auto_increment key任務
             */
            final String insertSql = "INSERT INTO user_key_auto(user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?)";

            List<UserKeyAuto> insertData = autoKeyTableService.getInsertData();
            stopwatch.start("自動生成key表任務開始");
            long start1 = System.currentTimeMillis();
            if (CollectionUtil.isNotEmpty(insertData)) {
                boolean insertResult = jdbcTemplateService.insert(insertSql, insertData, false);
                System.out.println(insertResult);
            }
            long end1 = System.currentTimeMillis();
            System.out.println("auto key消耗的時間:" + (end1 - start1));

            stopwatch.stop();


            /**
             * uudID的key
             */
            final String insertSql2 = "INSERT INTO user_uuid(id,user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?,?)";

            List<UserKeyUUID> insertData2 = uuidKeyTableService.getInsertData();
            stopwatch.start("UUID的key表任務開始");
            long begin = System.currentTimeMillis();
            if (CollectionUtil.isNotEmpty(insertData)) {
                boolean insertResult = jdbcTemplateService.insert(insertSql2, insertData2, true);
                System.out.println(insertResult);
            }
            long over = System.currentTimeMillis();
            System.out.println("UUID key消耗的時間:" + (over - begin));

            stopwatch.stop();


            /**
             * 隨機的long值key
             */
            final String insertSql3 = "INSERT INTO user_random_key(id,user_id,user_name,sex,address,city,email,state) VALUES(?,?,?,?,?,?,?,?)";
            List<UserKeyRandom> insertData3 = randomKeyTableService.getInsertData();
            stopwatch.start("隨機的long值key表任務開始");
            Long start = System.currentTimeMillis();
            if (CollectionUtil.isNotEmpty(insertData)) {
                boolean insertResult = jdbcTemplateService.insert(insertSql3, insertData3, true);
                System.out.println(insertResult);
            }
            Long end = System.currentTimeMillis();
            System.out.println("隨機key任務消耗時間:" + (end - start));
            stopwatch.stop();


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

    1.3.程序寫入結果

    user_key_auto寫入結果:user_random_key寫入結果:user_uuid表寫入結果:

    1.4.效率測試結果

    在已有數據量為130W的時候:我們再來測試一下插入10w數據,看看會有什么結果:可以看出在數據量100W左右的時候,uuid的插入效率墊底,并且在后序增加了130W的數據,uudi的時間又直線下降。時間占用量總體可以打出的效率排名為:auto_key>random_key>uuid,uuid的效率最低,在數據量較大的情況下,效率直線下滑。那么為什么會出現這樣的現象呢?帶著疑問,我們來探討一下這個問題:


    二、使用uuid和自增id的索引結構對比

    2.1.使用自增id的內部結構

    自增的主鍵的值是順序的,所以Innodb把每一條記錄都存儲在一條記錄的后面。當達到頁面的最大填充因子時候(innodb默認的最大填充因子是頁大小的15/16,會留出1/16的空間留作以后的     修改):①下一條記錄就會寫入新的頁中,一旦數據按照這種順序的方式加載,主鍵頁就會近乎于順序的記錄填滿,提升了頁面的最大填充率,不會有頁的浪費②新插入的行一定會在原有的最大數據行下一行,mysql定位和尋址很快,不會為計算新行的位置而做出額外的消耗③減少了頁分裂和碎片的產生

    2.2.使用uuid的索引內部結構

    因為uuid相對順序的自增id來說是毫無規律可言的,新行的值不一定要比之前的主鍵的值要大,所以innodb無法做到總是把新行插入到索引的最后,而是需要為新行尋找新的合適的位置從而來分配新的空間。這個過程需要做很多額外的操作,數據的毫無順序會導致數據分布散亂,將會導致以下的問題:①寫入的目標頁很可能已經刷新到磁盤上并且從緩存上移除,或者還沒有被加載到緩存中,innodb在插入之前不得不先找到并從磁盤讀取目標頁到內存中,這將導致大量的隨機IO②因為寫入是亂序的,innodb不得不頻繁的做頁分裂操作,以便為新的行分配空間,頁分裂導致移動大量的數據,一次插入最少需要修改三個頁以上③由于頻繁的頁分裂,頁會變得稀疏并被不規則的填充,最終會導致數據會有碎片在把隨機值(uuid和雪花id)載入到聚簇索引(innodb默認的索引類型)以后,有時候會需要做一次OPTIMEIZE TABLE來重建表并優化頁的填充,這將又需要一定的時間消耗。結論:使用innodb應該盡可能的按主鍵的自增順序插入,并且盡可能使用單調的增加的聚簇鍵的值來插入新行

    2.3.使用自增id的缺點

    那么使用自增的id就完全沒有壞處了嗎?并不是,自增id也會存在以下幾點問題:①別人一旦爬取你的數據庫,就可以根據數據庫的自增id獲取到你的業務增長信息,很容易分析出你的經營情況②對于高并發的負載,innodb在按主鍵進行插入的時候會造成明顯的鎖爭用,主鍵的上界會成為爭搶的熱點,因為所有的插入都發生在這里,并發插入會導致間隙鎖競爭③Auto_Increment鎖機制會造成自增鎖的搶奪,有一定的性能損失
    附:Auto_increment的鎖爭搶問題,如果要改善需要調優innodb_autoinc_lock_mode的配置


    三、總結

    本篇博客首先從開篇的提出問題,建表到使用jdbcTemplate去測試不同id的生成策略在大數據量的數據插入表現,然后分析了id的機制不同在mysql的索引結構以及優缺點,深入的解釋了為何uuid和隨機不重復id在數據插入中的性能損耗,詳細的解釋了這個問題。在實際的開發中還是根據mysql的官方推薦最好使用自增id,mysql博大精深,內部還有很多值得優化的點需要我們學習。

    標簽:數據 主鍵 時間
    你知道為與為每一個的區別嗎?
    ? 上一篇 2022-05-25
    • 你知道為與為每一個的區別嗎?
      0閱讀 0條評論 個贊
      之前有一個同事突然我問了我一個問題,說在foreach當中能不能刪除list里面的元素,我當時大概說了一下是否能刪除,以及原因;接下來我們來探討一下是否能夠如此;(1)遍歷元素首先,我們一一段代碼為例……
    • 有效的數據治理 如何管理元數據?
      0閱讀 0條評論 個贊
      本期作者沈汪洋嗶哩嗶哩資深開發工程師負責B站數據平臺工具側元數據、數據運營、數據管理等業務方向,專注于元數據采集、血緣應用、數據地圖、建模工具、治理工具等工具或產品功能的落地和推廣。背景介紹元數據是數……
    • 為什么數據庫是無服務器最難的堡壘?
      0閱讀 0條評論 個贊
      星星之火、可以燎原它是站在海岸遙望海中已經看得見桅桿尖頭了的一只航船,它是立于高山之巔遠看東方已見光芒四射噴薄欲出的一輪朝日,它是躁動于母腹中的快要成熟了的一個嬰兒?!珴蓶|一、關于Serverle……
    • Python中6個堪稱不朽的內置函數
      1閱讀 0條評論 個贊
      以下文章來源于公眾號-快學Python,作者朱小五在很多計算機書籍中,它們也通常作為高階函數來介紹。而我自己在日常工作中,經常使用它們來使代碼更快,更易于理解。Lambda函數Lambda函數用于創……
    • 深度知識的六個維度:如何讓人工智能真正理解世界?
      1閱讀 0條評論 個贊
      智能的真正標志不是知識,而是想象力。作者|GadiSinger編譯|王玥編輯|陳彩嫻什么知識讓我們變得聰明?我們用來理解世界、解釋新體驗和做出深思熟慮的選擇的認知結構是什么?定義一個闡明……
    發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    • SQL中的三種重復數據刪除方法 還有誰不行?
      1閱讀 0條評論 個贊
      SQL去重是數據分析工作中比較常見的一個場景,今天給大家具體介紹3種去重的方法。在使用SQL提數的時候,常會遇到表內有重復值的時候,比如我們想得到uv(獨立訪客),就需要做去重。在MySQL中……
    • 系統數據治理的思考與實踐
      2閱讀 0條評論 個贊
      美團住宿數據治理團隊從事數據治理工作多年,從最初的被動、單點治理,發展到后來的主動、專項治理,再發展到現在的體系化、自動化治理。一路走來,他們不斷進行積累和沉淀,也在持續思考與實踐。目前該團隊取得了一……
    • 甲骨文(第11代)單實例-室內空調(第11代)遷移模擬測試
      1閱讀 0條評論 個贊
      Oracle11.2.0.4單實例----Oracle19C-RAC遷移模擬測試總體思想:通過RMAN物理備份在備庫恢復主庫數據,后續通過在主庫停業務后,將從備份后的所有日志都同步到新庫應用,重新配置……
    • Java處理異常的9個最佳實踐 你做得對嗎?
      1閱讀 0條評論 個贊
      原文:https://dzone.com/articles/9-best-practices-to-handle-exceptions-in-java譯者:颯然Hang譯文:http://www.r……
    • 有效的數據治理 如何管理元數據?
      0閱讀 0條評論 個贊
      本期作者沈汪洋嗶哩嗶哩資深開發工程師負責B站數據平臺工具側元數據、數據運營、數據管理等業務方向,專注于元數據采集、血緣應用、數據地圖、建模工具、治理工具等工具或產品功能的落地和推廣。背景介紹元數據是數……
    • 誤操作離線丟棄和恢復場景測試的業務影響——來自“血”的教訓
      0閱讀 0條評論 個贊
      在數據庫恢復過程中,比如我們用了第三方的備份工具,在實施恢復操作時會導出需要的某個表空間這樣可以大大減少恢復時間,是十分值得推薦的做法,這個過程中由于修改控制文件中數據文件的相關信息,需要執行alte……
    • 為什么NodeJS是構建微服務的最佳選擇?
      8閱讀 0條評論 個贊
      作者|RonFybish譯者|Sambodhi策劃|閆園園什么是微服務微服務是一種應用架構,它將每個應用功能都放在自己的服務中,與其他服務隔離。這些服務是松散耦合的,可獨立部署。這種架構……
    • 管理數百個Kubernetes集群需要什么?
      0閱讀 0條評論 個贊
      文章轉載:進擊云原生(版權歸原作者所有,侵刪)要點:部署一個具備生產就緒所需所有依賴關系的Kubernetes集群需要數天時間。如果不自動化這個過程,管理Kubernetes集群的浮動是非常困難的。在……
    • 運維數字化轉型的幾點思考
      1閱讀 0條評論 個贊
      這個月底要召開一個企業運維數字化轉型的研討會,昨天一個合作伙伴和我討論一些研討會的話題問題。數字化轉型是近期十分熱門的話題,各大國企央企也把數字化轉型作為未來幾年的工作重點。不過針對于IT運維,數字化……
    • 如何在K8S的Pod中連續執行容器?不要錯過這個方法
      1閱讀 0條評論 個贊
      出于某些目的,有時需要在Kubernetes的一個Pod中,連續依次運行多個Container。這種有明確結束預期的運行,即Kubernetes的Job。但是,雖然一個Job可以在……
    • Java原子變量中set()和lazySet()的區別
      1閱讀 0條評論 個贊
      來源|Java技術指北(ID:javanorth)在本教程中,我們將講講Javaatomic類(如AtomicInteger和AtomicReference)的方法set()和l……
    • 服務器端高并發分布式架構的演進之路
      1閱讀 0條評論 個贊
      1.概述本文以淘寶作為例子,介紹從一百個到千萬級并發情況下服務端的架構的演進過程。同時列舉出每個演進階段會遇到的相關技術,讓大家對架構的演進有一個整體的認知。文章最后匯總了一些架構設計的原則。特別說……
    • 你可能不知道PostgreSQL能做的8件有趣的事!
      0閱讀 0條評論 個贊
      1整行引用您是否嘗試過運行以下語句?SELECTmy_tableFROMmy_table;這可能看起來很奇怪,但它所做的是將所有列作為行類型返回到單個列中?,F在你為什么要這樣做?好吧,您很可……
    • 卡夫卡3.0新功能全暴露 好香??!
      1閱讀 0條評論 個贊
      以下文章來源于云加社區,作者屈志平導語|kafka3.0的版本已經試推行去zk的kafka架構了,如果去掉了zk,那么在kafka新的版本當中使用什么技術來代替了zk的位置呢,接下來我們一起來一探究竟……
    • MySQL批量插入數據 一次插入多少行數據效率最高?
      7閱讀 0條評論 個贊
      一、前言我們在操作大型數據表或者日志文件的時候經常會需要寫入數據到數據庫,那么最合適的方案就是數據庫的批量插入。只是我們在執行批量操作的時候,一次插入多少數據才合適呢?假如需要插入的數據有百萬條,那……
    • 臉書數據庫項目負責人:我從做基礎設施中學到的42件事
      2閱讀 0條評論 個贊
      最近讀到了分布式系統研究者MaheshBalakrishnan的一篇博客《42thingsIlearnedfrombuildingaproductiondatabase》。同樣做……
    • MySQL查詢語句的limit offset是如何實現的?
      1閱讀 0條評論 個贊
      在寫select語句的時候,使用limit,offset可能就像是我們吃飯喝水一樣自然了。剛開始工作的時候也經常聽前輩們教導:使用limit,offset,當offset變大的時候執……
    • Python字符串深度摘要
      2閱讀 0條評論 個贊
      以下文章來源于公眾號-蘿卜大雜燴,作者周蘿卜今天我們來學習字符串數據類型相關知識,將討論如何聲明字符串數據類型,字符串數據類型與ASCII表的關系,字符串數據類型的屬性,以及一些重要的字符串方法和……
    • MYSQL VS POLARDB唯一索引死鎖及應用設計
      1閱讀 0條評論 個贊
      #issue68021MySQLuniquecheck問題-知乎(zhihu.com)事情的開始是這樣的,最近和阿里云密切聯系,也成為他們的大客戶,(我們當然是大客戶,BIGBIG……
    • 嵌入式系統登錄的簡單方法
      3閱讀 0條評論 個贊
      來源|我姓梁很多場景都需要記錄日志,在嵌入式系統中,特別是單片機這種存儲資源有限的環境下,就需要一種輕量級的存儲方法。系統日志在嵌入式設備應用場景中,系統日志時??梢员O控設備軟件的運行狀態,及時記錄……
    最近發布資訊
    更多
    国产H视频在线播放,国产毛多水多的老女人,国产成人午夜福利电影在线播放
    <table id="km2im"></table>
  • <bdo id="km2im"><center id="km2im"></center></bdo>