1. 程式人生 > 其它 >如何實現掃碼登入功能?

如何實現掃碼登入功能?

目錄

mysql索引總結

https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484721&idx=1&sn=410dea1863ba823bec802769e1e6fe8a&chksm=ebd74430dca0cd265a9a91dcb2059e368f43a25f3de578c9dbb105e1fba0947e1fd0b9c2f4ef&token=1676899695&lang=zh_CN###rd

mysql理解總結

作業系統背景:磁碟I/O是非常高昂代價的操作,計算機系統做了一些優化,當一次I/O時,不光會把當前磁碟地址的資料讀取到記憶體中,而且會把相鄰的資料也讀取到記憶體緩衝區中,因為區域性預讀性原理告訴我們,當計算機訪問一個地址的資料的時候,與其相鄰的資料也會很快訪問到。每一次I/O讀取的資料我們稱之為一頁(Page)。也就是我們讀取一頁資料的時候,實際上才發生了一次I/O,這個理論對於索引的資料結構設計很有幫助。

Mysql的基本儲存結構是(記錄都存在頁裡邊):

  • 各個資料頁可以組成一個雙向連結串列

  • 每個資料頁中的記錄又可以組成一個單向連結串列

    • 每個資料頁都會為儲存在它裡邊兒的記錄生成一個頁目錄,在通過主鍵查詢某條記錄的時候可以在頁目錄中使用二分法快速定位到對應的槽,然後再遍歷該槽對應分組中的記錄即可快速找到指定的記錄
    • 其他列(非主鍵)作為搜尋條件:只能從最小記錄開始依次遍歷單鏈表中的每條記錄

所以說,如果我們寫 select*fromuserwhereusername='Java3y'這樣沒有進行任何優化的sql語句,預設會這樣做:

  • 定位到記錄所在的頁

    • 需要遍歷雙向連結串列,找到所在的頁
  • 從所在的頁內中查詢相應的記錄

    • 由於不是根據主鍵查詢,只能遍歷所在頁的單鏈表了

索引將無序的資料變成有序(相對)

要找到id為8的記錄簡要步驟:

很明顯的是:沒有用索引我們是需要遍歷雙向連結串列來定位對應的頁,現在通過“目錄”就可以很快地定位到對應的頁上了!

其實底層結構就是B+樹,B+樹作為樹的一種實現,能夠讓我們很快地查找出對應的記錄。

上述的目錄項其實就是索引B+樹(主鍵索引),目錄項裡存放的是表示範圍分組的索引的資料和對應不同範圍的索引所在的下一級節點的目錄(也叫作指標)葉子結點就是表資料組成的頁

  • B+樹是一顆平衡樹,如果我們對這顆樹增刪改的話,那肯定會破壞它的原有結構
  • 要維持平衡樹,就必須做額外的工作。正因為這些額外的工作開銷,導致索引會降低增刪改的速度

圖中淺藍色的塊,我們稱之為一個磁碟,可以看到,每個磁碟塊包含幾個資料項(深藍色)和指標(黃色)。如:磁碟塊1包含資料17和資料35,包含指標P1,P2,P3,P1指向資料小於17的磁碟塊,P2指向資料在17到35之間的資料所在磁碟塊,P3指向資料大於35的資料所在的磁碟塊。真實資料存在於葉子節點,即3,5,9,10,13,15,28,29,36,60,75,79,90,99 。 非葉子節點不儲存真實資料,只儲存指引搜尋方向的資料項,如17、35並不真實存在於資料表中。

假設,我們要查詢資料項29,那麼我們首先會把磁碟塊1由磁碟載入到記憶體中,此時進行了一次I/O,在記憶體中用二分查詢確定29在17和35之間,鎖定磁碟塊1的P2指標,記憶體計算時間由於非常短(對比於I/O)可以忽略不計,通過磁碟塊1的P2指標的磁碟地址指向磁碟塊3,由磁碟載入到記憶體,此時進行了第二次I/O,29在26和30之間,鎖定磁碟塊3的P2指標,通過指標載入磁碟塊8到記憶體,此時進行了第三次I/O,同時記憶體中計算二分查詢找到29,查詢結束。這一過程,一共進行了3次I/O。在真實使用場景中,三層的B+樹可以表示上百萬的資料,如果上百萬的資料查詢只需要三次I/O,效能提高將會是巨大的。B+樹就是一種索引資料結構,如果沒有這樣的索引,每個資料項發生一次I/O,那麼成本將會大大提升。

B+樹的一些性質:

  • 如果資料項佔的空間越小,資料項的數量越多,樹的高度也就越低。這也就是為什麼每個資料項,即索引欄位要儘量的小,比如int佔4個位元組,要比bigint的8個位元組小一半。這也是為什麼B+樹要求把真實資料放在葉子節點內而不是內層節點內,一旦放到內層節點內,磁碟塊的資料項會大幅度的下降,導致樹層級的增高。
  • B+樹的資料項是複合性資料結構,比如(name,age,gender)的時候,B+樹是按照從左到右的順序來建立搜尋樹的,比如當(小張,22,女)這樣的資料來檢索的時候,B+樹會優先比較name來確定下一步的搜尋方向,如果name相同再依次比較age和gender,最後得到檢索的資料。但是,當(22,女)這樣沒有name的資料來的時候,B+樹就不知道下一步該查哪個節點,因為建立搜尋樹的時候,name就是第一個比較因子,必須根據name來搜尋才知道下一步去哪裡查詢。比如,當(小張,男)這樣的資料來檢索時,B+樹就可以根據name來指定搜尋方向,但下一欄位age缺失,所以只能把名字是“小張”的所有資料都找到,然後再匹配性別是“男”的資料了。這個是非常重要的一條性質,即索引的最左匹配特性。
雜湊索引

雜湊索引就是採用一定的雜湊演算法,把鍵值換算成新的雜湊值,檢索時不需要類似B+樹那樣從根節點到葉子節點逐級查詢,只需一次雜湊演算法即可立刻定位到相應的位置,速度非常快

  • 本質上就是把鍵值換算成新的雜湊值,根據這個雜湊值來定位

雜湊索引有好幾個侷限(根據他本質的原理可得):

  • 雜湊索引也沒辦法利用索引完成排序
  • 不支援最左匹配原則
  • 在有大量重複鍵值情況下,雜湊索引的效率也是極低的---->雜湊碰撞問題。
  • 不支援範圍查詢
聚集和非聚集索引

簡單概括:

  • 聚集索引就是以主鍵建立的索引
  • 非聚集索引就是以非主鍵建立的索引

區別:

  • 聚集索引在葉子節點儲存的是表中的資料
  • 非聚集索引在葉子節點儲存的是主鍵和索引列
  • 使用非聚集索引查詢出資料時,拿到葉子上的主鍵再去查到想要查詢的資料。(拿到主鍵再查詢這個過程叫做回表)

非聚集索引在建立的時候也未必是單列的,可以多個列來建立索引。

  • 此時就涉及到了哪個列會走索引,哪個列不走索引的問題了(最左匹配原則-->後面有說)
  • 建立多個單列(非聚集)索引的時候,會生成多個索引樹(所以過多建立索引會佔用磁碟空間)
  • 覆蓋索引就是把要查詢出的列和索引是對應的,不做回表操作!
索引最左匹配原則
  • 如果是聯合索引,那麼key也由多個列組成,同時,索引只能用於查詢key是否存在(相等),遇到範圍查詢 (>、<、between、like左匹配)等就不能進一步匹配了,後續退化為線性查詢。
  • 因此,列的排列順序決定了可命中索引的列數

例子:

  • 如有索引 (a,b,c,d),查詢條件 a=1andb=2andc>3andd=4,則會在每個節點依次命中a、b、c,無法命中d。(c已經是範圍查詢了,d肯定是排不了序了)
  • a = 1 AND b = 2 AND c > 3 AND d = 4,如果建立 (a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引,則都可以用到,a,b,d的順序可以任意調整。
  • 如有索引 (a,b,c,d),查詢條件 c>3andb=2anda=1andd<4a=1andc>3andb=2andd<4等順序都是可以的,MySQL會自動優化為 a=1andb=2andc>3andd<4,依次命中a、b、c。

不需要考慮=、in等的順序,mysql會自動優化這些條件的順序,以匹配儘可能多的索引列。

索引優化
  • 索引不會包含有NULL值的列:只要列中包含有NULL值,都將不會被包含在索引中,組合索引中只要有一列有NULL值,那麼這一列對於此條組合索引就是無效的。所以我們在資料庫設計時,不要讓索引欄位的預設值為NULL。
  • 使用短索引:假設,如果有一個數據型別為CHAR(255)的列,在前10個或20個字元內,絕大部分資料的值是唯一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省I/O操作(索引樹每一個磁碟資料項可以容納更多的資料,高度降低,當然降低了I/O次數)。
  • 索引列排序:MySQL查詢只使用一個索引,因此如果WHERE子句中已經使用了索引的話,那麼ORDER BY中的列是不會使用索引的。因此資料庫預設排序可以符合要求的情況下,不要使用排序操作;儘量不要包含多個列的排序,如果需要,最好給這些列也建立組合索引。
  • LIKE "%aaaaa%"不會使用索引,但是LIKE "aaa%"卻可以使用索引。
  • 不要在索引列上進行運算:在建立索引的原則中,提到了索引列不能進行運算