數據庫學習<一>數據庫基礎知識


數據庫設計的六個階段

系統需求分析階段

系統需求分析的兩種方式

  • 自頂向下
    從最頂層的系統組織機構入手,采用逐層分解的方式分析
  • 自底向上

概念結構設計階段

邏輯結構設計階段

物理結構設計階段

數據庫實施階段

數據庫運行與維護階段

數據庫的三范式

數據庫的設計范式(NF: Normal Form)是數據庫設計所需要滿足的規范,滿足這些規范的數據庫是簡潔的、結構明晰的,同時,不會發生插入(insert)、刪除(delete)和更新(update)操作異常。

第一范式:列不可再分

  • 每一列的屬性都是不可再分的屬性值,確保每一列的原子性
  • 兩列的屬性相近或相似或一樣,盡量合並屬性一樣的列,確保不產生冗余數據

第二范式:屬性完全依賴於主建

第二范式是在第一范式的基礎上建立起來的,即滿足第二范式必須先滿足第一范式。第二范式要求數據庫表中的每個實例或行必須可以被惟一地區分。為實現區分通常需要為表加上一個列,以存儲各個實例的惟一標識。這個惟一屬性列被稱為主鍵

第三范式:屬性直接依賴於主鍵,屬性不依賴於其它非主屬性

數據不能存在傳遞關系,即每個屬性都跟主鍵有直接關系而不是間接關系。像:a-->b-->c 屬性之間含有這樣的關系,是不符合第三范式的。

注意:數據庫設計最重要的是看需求跟性能,需求>性能>表結構;所以不能一味的去追求范式建立數據庫.

數據的事物

事物的四大特性(ACID)

  • 原子性(Atomicity)
    原子性是指事務是一個不可分割的工作單位,事務中的操作要么全部成功,要么全部失敗。比如在同一個事務中的SQL語句,要么全部執行成功,要么全部執行失敗
  • 一致性(Consistency)
    事務必須使數據庫從一個一致性狀態變換到另外一個一致性狀態
  • 隔離性(Isolation)
    事務的隔離性是多個用戶並發訪問數據庫時,數據庫為每一個用戶開啟的事務,不能被其他事務的操作數據所干擾,多個並發事務之間要相互隔離。
  • 持久性(Durability)
     持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即使數據庫發生故障也不應該對其有任何影響
    在事物的特性中,最困難的是事物的隔離性

事物的隔離級別

多個線程開啟各自事務操作數據庫中數據時,數據庫系統要負責隔離操作,以保證各個線程在獲取數據時的准確性。

如果不考慮事物的隔離性,將會引發的問題

  • 臟讀
臟讀是指一個事務讀取了另外一個事務未提交的數據
    這是非常危險的,假設A向B轉帳100元,對應sql語句如下所示
             update account set money=money+100 where name='B';    
          update account set money=money-100  where name='A';
    當第1條sql執行完,第2條還沒執行(A未提交時),如果此時B查詢自己的帳戶,就會發現自己多了100元錢。如果A等B走后再回滾,B就會損失100元。
  • 不可重復讀
不可重復讀指在一個事務內讀取表中的某一行數據,多次讀取結果不同。
  例如銀行想查詢A帳戶余額,第一次查詢A帳戶為200元,此時A向帳戶內存了100元並提交了,銀行接着又進行了一次查詢,此時A帳戶為300元了。銀行兩次查詢不一致,可能就會很困惑,不知道哪次查詢是准的。
不可重復讀和臟讀的區別是,臟讀是讀取前一事務未提交的臟數據,不可重復讀是重新讀取了前一事務已提交的數據。
  • 幻讀
幻讀是指在一個事務內讀取到了別的事務插入的數據,導致前后讀取不一致。
  如丙存款100元未提交,這時銀行做報表統計account表中所有用戶的總額為500元,然后丙提交了,這時銀行再統計發現帳戶為600元了,造成虛讀同樣會使銀行不知所措,到底以哪個為准。

為了解決這些問題,而出現了事物隔離級別

針對事物的隔離性而設置的四種隔離級別

  • Read uncommitted(讀未提交):最低級別,以上情況均無法保證
  • Read committed(讀已提交):可避免臟讀情況發生。
  • Repeatable read(可重復讀):可避免臟讀、不可重復讀情況的發生
  • Serializable(串行化):可避免臟讀、不可重復讀、幻讀情況的發生。
    主要是為了解決並發情況的事物問題,非並發情況下應該不會出現上述的事物問題

索引相關

什么是索引?

索引是對數據庫表中的一列或多列的值進行排序的一種結構。
索引是建立在表的基礎之上的,有助於無需檢查所有記錄而快速定位所需記錄的一種輔助存儲結構,由一系列存儲在磁盤上的索引項組成,每一種索引項由索引字段和行指針組成。

MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構。所以說索引的本質,就是一種數據結構
我們知道,數據庫查詢是數據庫的最主要功能之一。我們都希望查詢數據的速度能盡可能的快,因此數據庫系統的設計者會從查詢算法的角度進行優化。最基本的查詢算法當然是順序查找(linear search),這種復雜度為O(n)的算法在數據量很大時顯然是糟糕的,好在計算機科學的發展提供了很多更優秀的查找算法,例如二分查找(binary search)、二叉樹查找(binary tree search)等。如果稍微分析一下會發現,每種查找算法都只能應用於特定的數據結構之上,例如二分查找要求被檢索數據有序,而二叉樹查找只能應用於二叉查找樹上,但是數據本身的組織結構不可能完全滿足各種數據結構(例如,理論上不可能同時將兩列都按順序進行組織),所以,在數據之外,數據庫系統還維護着滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法。這種數據結構,就是索引

建立索引有什么好處?

  • 通過建立索引,可以在查詢的過程中,提高系統的性能。
  • 通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。
  • 在使用分組和排序自居進行數據兼續哦是,可以減少查詢中分組和排序的時間。
  • 建立數據庫索引,可以確保數據的唯一性。
  • 可以加快表和表之間的連接,實現表和表之間的參照完整性。

建立索引有什么壞處?

  • 創建和維護索引是需要耗費很多時間的,而且時間隨着數據量的增加而增大。
  • 索引需要占用物理空間,如果要建立聚簇索引,所需要的物理空間就會更大。
  • 建立索引后,在對表中的數據進行增加刪除和修改時需要耗費較多的時間,因為這個過程需要動態的維護索引。

索引的分類有哪些?

各類索引其實很多是具有交集的,聯合索引可以是覆蓋索引,主鍵索引可以是聚集索引也可以是非聚集索引,非聚集索引可以是聯合索引,它們並不是相互對立的,而是根據不同的應用情況有着不同的名稱。

索引按數據結構分類:
索引按索引的底層數據結構分類,分為B+索引和hash索引以及全文索引

  • 主建索引(PRIMARY KEY)
    某一個屬性組能唯一標識的一條記錄
    特點:
    最常見的索引類型
    確保數據記錄的唯一性
    確定特定數據記錄在數據庫中的位置
  • 唯一索引 (UNIQUE)
    作用:
    避免同一個表中某數據列種的值重復
    與主鍵索引的區別:
    主建索引只能有一個,唯一索引可有多個。
  • 普通索引(INDEX)
    作用:
    快速定位特定數據
    注意:
    不易添加太多常規索引,影響數據的插入,刪除和修改操作
  • 全文索引(FULLTEXT)
    作用:
    快速定位特定數據
    注意:
    只能用於MyISAM類型的數據表
    只能用於 CHAR, VARCHAR, TEXT 數據列類型
    使用大型數據集

索引分類

  • 根據存儲結構的不同可以分為聚集索引和非聚集索引
    聚集索引:
    指索引項的排序方式和表中數據記錄排序方式一致的索引也就是說聚集索引的順序就是數據的物理存儲順序。它會根據聚集索引鍵的順序來存儲表中的數據,即對表的數據按索引鍵的順序進行排序,然后重新存儲到磁盤上。由於數據在物理存放時只能有一種排序方式,所以一個表只能有一個聚集索引。

非聚集索引:
索引順序與物理存儲順序不同

非聚集索引必須是稠密索引

  • 根據索引的數量可以分為稠密索引和稀疏索引
    稠密索引:
    在稠密索引中,文件中的每個搜索碼值都對應一個索引值。也就是說,稠密索引為數據記錄文件的每一條記錄都設一個鍵-指針對。如下圖所示,索引項包括索引值以及指向該搜索碼的第一條數據記錄的指針,即我們所說的鍵-指針對。

稀疏索引:
在稀疏索引中,只為搜索碼的某些值建立索引項。也就是說,稀疏索引為數據記錄文件的每個存儲塊設一個鍵-指針對,存儲塊意味着塊內存儲單元連續。

  • 根據其他的分類方法有不同的划分。

索引的實現方式

  • B+樹
    B+索引是數據庫使用最多的索引,底層是B+樹。我們經常聽到B+樹就是這個概念,用這個樹的目的和紅黑樹差不多,也是為了盡量保持樹的平衡,當然紅黑樹是二叉樹,但B+樹就不是二叉樹了,節點下面可以有多個子節點,數據庫開發商會設置子節點數的一個最大值,這個值不會太小,所以B+樹一般來說比較矮胖,而紅黑樹就比較瘦高了。
    關於B+樹的插入,刪除,會涉及到一些算法以保持樹的平衡。ORACLE的默認索引就是這種結構的。
    如果經常需要同時對兩個字段進行AND查詢,那么使用兩個單獨索引不如建立一個復合索引,因為兩個單獨索引通常數據庫只能使用其中一個,而使用復合索引因為索引本身就對應到兩個字段上的,效率會有很大提高。

  • 散列索引

Hash索引的底層是hash表,運用某種哈希算法對索引值進行運算,獲得hash值,再通過hash值映射到特定的位置,查找速度及其快。但它只能用於等值查詢,無法進行數據庫常用的操作-范圍查找和排序,而且當記錄變多或者索引值重復過多時,容易產生hash碰撞,因此主流的存儲引擎都使用B+索引。InnoDB支持自適應Hash索引,也就是說我們不能人為創建hash索引,而是InnoDB引擎進行優化創建hash索引,當InnoDB引擎監視到某個二級索引在頻繁的使用時,經常訪問的二級索引數據會自動被生成到hash索引里面去(最近連續被訪問三次的數據),自適應哈希索引通過緩沖池的B+樹構造而來,因此建立的速度很快。

就是通過散列函數來定位的一種索引,不過很少有單獨使用散列索引的,反而是散列文件組織用的比較多。
散列文件組織就是根據一個鍵通過散列計算把對應的記錄都放到同一個槽中,這樣的話相同的鍵值對應的記錄就一定是放在同一個文件里了,也就減少了文件讀取的次數,提高了效率。
散列索引呢就是根據對應鍵的散列碼來找到最終的索引項的技術,其實和B樹就差不多了,也就是一種索引之上的二級輔助索引,我理解散列索引都是二級或更高級的稀疏索引,否則桶就太多了,效率也不會很高。

  • 位圖索引
    位圖索引是一種針對多個字段的簡單查詢設計一種特殊的索引,適用范圍比較小,只適用於字段值固定並且值的種類很少的情況,比如性別,只能有男和女,或者級別,狀態等等,並且只有在同時對多個這樣的字段查詢時才能體現出位圖的優勢。
    位圖的基本思想就是對每一個條件都用0或者1來表示,如有5條記錄,性別分別是男,女,男,男,女,那么如果使用位圖索引就會建立兩個位圖,對應男的10110和對應女的01001,這樣做有什么好處呢,就是如果同時對多個這種類型的字段進行and或or查詢時,可以使用按位與和按位或來直接得到結果了。

B+樹最常用,性能也不差,用於范圍查詢和單值查詢都可以。特別是范圍查詢,非得用B+樹這種順序的才可以了。
HASH的如果只是對單值查詢的話速度會比B+樹快一點,但是ORACLE好像不支持HASH索引,只支持HASH表空間。
位圖的使用情況很局限,只有很少的情況才能用,一定要確定真正適合使用這種索引才用(值的類型很少並且需要復合查詢),否則建立一大堆位圖就一點意義都沒有了。

注意:
索引並不總是最好的工具。總的來說,只有當索引幫助存儲引擎快速查找到記錄帶來的好處大於其他帶來的額外工作時,索引才是有效的。

  • 對於非常小的表,大部分情況下簡單的全表掃描更有效
  • 對於中到大型表,索引就非常有效
  • 對於特大型表,建立和使用索引的代價隨之增長

對於特大型表的情況下,需要一種技術可以直接區分出查詢需要的一組數據,而不是一條一條記錄地匹配。例如: 分區技術。 如果表的數據特別多,可以建立一個元數據信息表,用來查詢需要用到的某些特性。對於TB級別的數據,定位單條記錄的意義不大,所以經常會使用塊級別元數據技術代替索引。

索引命中:

like
模糊查詢以%開頭,會導致索引失效
即使不以%開頭,使用like也會降低查詢效率
如果用戶量很大的話,不使用like 而會導入第三方工具處理文字
避免使用函數
例如使用reverse(email) 會導致索引失效
盡量將類似的功能在代碼中完成
or
當or條件中有未建立的索引列會失效
例: SELECT * FROM TB WHERE 索引列 or 非索引列 則在此 索引失效
但是 SELECT * FROM TB WHERE 索引列 or 非索引列 and 索引列 則會只用首尾的索引列
類型不一致
即傳入的數據類型要與列類型相符 不然索引失效
例如列類型為字符 而傳入數
!= >
普通索引使用 != 索引失效 但主鍵有效
普通索引字符型 > 索引失效 數字或者主鍵有效
order by
當根據索引排序時,選擇的映射如果不是索引,則失效
例如: select name from tb where email='123@' email是索引,但映射name 索引失效
但是對主鍵排序,索引有效
最左前綴
如果組合索引為(name,email)
name and email 有效
name 有效
email 失效
一個表建的索引盡量不要超過5個。
盡量使用覆蓋索引。
盡量不要在重復數據多的列上建索引。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM