當前位置:首頁 » 數據倉庫 » mysql資料庫範式
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

mysql資料庫範式

發布時間: 2023-05-01 01:33:57

A. 資料庫第二範式和第三範式的區別的是什麼

第二範式(2NF)和第三範式(3NF)的概念很容易混淆,區分它們的關鍵點在於,2NF:非主鍵列是否完全依賴於主鍵,還是依賴於主鍵的一部分;3NF:非主鍵列是直接依賴於主鍵,還是直接依賴於非主鍵列。

第二範式(2NF):首先是 1NF,另外包含兩部分內容,一是表必須有一個主鍵;二是沒有包含在主鍵中的列必須完全依賴於主鍵,而不能只依賴於主鍵的一部分。考慮一個訂單明細表OrderDetail其屬性如下: (OrderID,ProctID,UnitPrice,Discount,Quantity,ProctName)。
因為我們知道在一個訂單中可以訂購多種產品,所以單單一個OrderID 是不足以成為主鍵的,主鍵應該是(OrderID,ProctID)。顯而易見 Discount(折扣),Quantity(數量)完全依賴(取決)於主鍵(OderID,ProctID),而 UnitPrice,ProctName 只依賴於 ProctID。所以 OrderDetail 表不符合 2NF。不符合 2NF的設計容易產生冗餘數據。

可以把OrderDetail表拆分為:

  • OrderDetail(OrderID,ProctID,Discount,Quantity)

  • Proct (ProctID,UnitPrice,ProctName)

來消除原訂單表中UnitPrice,ProctName多次重復的情況。
第三範式(3NF):首先是 2NF,另外非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴。即不能存在:非主鍵列 A 依賴於非主鍵列 B,非主鍵列 B 依賴於主鍵的情況。茄蘆考慮一個訂單表Order: (OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主鍵是(OrderID)。凱正
其中OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity
等非主鍵列都完全依賴於主鍵(OrderID),所以符合 2NF。

不過問題是CustomerName,CustomerAddr,CustomerCity 直接依賴的是
CustomerID(非主鍵列),而不是直接依賴於主鍵,它是通顫孫帶過傳遞才依賴於主鍵,所以不符合 3NF。
通過拆分Order為Order(OrderID,OrderDate,CustomerID)和Customer(CustomerID,CustomerName,CustomerAddr,CustomerCity)從而達到 3NF。

B. 關於資料庫三大設計範式淺析

為了建立冗餘較小、結構合理的資料庫,設計資料庫時必須遵循一定的規則。在關系型資料庫中這種規則就稱為範式。範式是符合某一種設計要求的總結。要想設計一個結構合理的關系型資料庫,必須滿足一定的範式。

真正要明白」範式(NF)」是什麼意思,首先看下教材中的定義,範式是「符合某一種級別的關系模式的集合,表示一個關系內部各屬性之間的聯系的合理化程度」。實際上可以把它粗略地理解為一張數據表的表結構所符合的某種設計標準的級別。就像家裡裝修買建材,最環保的是E0級,其次是E1級,還有E2級等等。資料庫範式也分為1NF,2NF,3NF,BCNF,4NF,5NF。一般在我們設計關系型資料庫的時候,最多考慮到BCNF就夠。符合高一級範式的設計,必定符合低一級範式,例如符合2NF的關系模式,必定符合1NF。

在實際開發中最為常見的設計範式有三個:

首先是第一範式(1NF)。

符合1NF的關系(你可以理解為數據表。「關系」和「關系模式」的區別,類似於面向對象程序設計中」類「與」對象「的區別。」關系「是」關系模式「的一個實例,你可以把」關系」理解為一張帶數據的表,而「關系模式」是這張數據表的表結構。1NF的定義為:符合1NF的關系中的每個屬性都不可再分。表1所示的情況,就不符合1NF的要求。

這樣在查詢訂單信息的時候,就可以使用客戶編號來引用客戶信息表中的記錄,也不必在訂單信息表中多次輸入客戶信息的內容,減小了數據冗餘。

由此可見,符合3NF要求的資料庫設計,基本上解決了數據冗餘過大,插入異常,修改異常,刪除異常的問題。當然,在實際中,往往為了性能上或者應對擴展的需要,經常 做到2NF或者1NF,但是作為資料庫設計人員,至少應該知道,3NF的要求是怎樣的。

C. Mysql資料庫性能優化之分區分表分庫

分表是分散資料庫壓力的好方法。

分表,最直白的意思,就是將一個表結構分為多個表,然後,可以再同一個庫里,也可以放到不同的庫。

當然,首先要知道什麼情況下,才需要分表。個人覺得單表記錄條數達到百萬到千萬級別時就要使用分表了。

分表的分類

**1、縱向分表**

將本來可以在同一個表的內容,人為劃分為多個表。(所謂的本來,是指按照關系型資料庫的第三範式要求,是應該在同一個表的。)

分表理由:根據數據的活躍度進行分離,(因為不同活躍的數據,處理方式是不同的)

案例:

對於一個博客系統,文章標題,作者,分類,創建時間等,是變化頻率慢,查詢次數多,而且最好有很好的實時性的數據,我們把它叫做冷數據。而博客的瀏覽量,回復數等,類似的統計信息,或者別的變化頻率比較高的數據,我們把它叫做活躍數據。所以,在進行資料庫結構設計的時候,就應該考慮分表,首先是縱向分表的處理。

這樣縱向分表後:

首先存儲引擎的使用不同,冷數據使用MyIsam 可以有更好的查詢數據。活躍數據,可以使用Innodb ,可以有更好的更新速度。

其次,對冷數據進行更多的從庫配置,因為更多的操作時查詢,這樣來加快查詢速度。對熱數據,可以相對有更多的主庫的橫向分表處理。

其實,對於一些特殊的活躍數據,也可以考慮使用memcache ,redis之類的緩存,等累計到一定量再去更新資料庫。或者mongodb 一類的nosql 資料庫,這里只是舉例,就先不說這個。

**2、橫向分表**

字面意思,就可以看出來,是把大的表結構,橫向切割為同樣結構的不同表,如,用戶信息表,user_1,user_2等。表結構是完全一樣,但是,根據某些特定的規則來劃分的表,如根據用戶ID來取模劃分。

分表理由:根據數據量的規模來劃分,保證單表的容量不會太大,從而來保證單表的查詢等處理能力。

案例:同上面的例子,博客系統。當博客的量達到很大時候,就應該採取橫向分割來降低每個單表的壓力,來提升性能。例如博客的冷數據表,假如分為100個表,當同時有100萬個用戶在瀏覽時,如果是單表的話,會進行100萬次請求,而現在分表後,就可能是每個表進行1萬個數據的請求(因為,不可能絕對的平均,只是假設),這樣壓力就降低了很多很多。

延伸:為什麼要分表和分區?

日常開發中我們經常會遇到大表的情況,所謂的大表是指存儲了百萬級乃至千萬級條記錄的表。這樣的表過於龐大,導致資料庫在查詢和插入的時候耗時太長,性能低下,如果涉及聯合查詢的情況,性能會更加糟糕。分表和表分區的目的就是減少資料庫的負擔,提高資料庫的效率,通常點來講就是提高表的增刪改查效率。

什麼是分表?

分表是將一個大表按照一定的規則分解成多張具有獨立存儲空間的實體表,我們可以稱為子表,每個表都對應三個文件,MYD數據文件,.MYI索引文件,.frm表結構文件。這些子表可以分布在同一塊磁碟上,也可以在不同的機器上。app讀寫的時候根據事先定義好的規則得到對應的子表名,然後去操作它。

什麼是分區?

分區和分表相似,都是按照規則分解表。不同在於分表將大表分解為若干個獨立的實體表,而分區是將數據分段劃分在多個位置存放,可以是同一塊磁碟也可以在不同的機器。分區後,表面上還是一張表,但數據散列到多個位置了。app讀寫的時候操作的還是大表名字,db自動去組織分區的數據。

**MySQL分表和分區有什麼聯系呢?**

1、都能提高mysql的性高,在高並發狀態下都有一個良好的表現。

2、分表和分區不矛盾,可以相互配合的,對於那些大訪問量,並且表數據比較多的表,我們可以採取分表和分區結合的方式(如果merge這種分表方式,不能和分區配合的話,可以用其他的分表試),訪問量不大,但是表數據很多的表,我們可以採取分區的方式等。

3、分表技術是比較麻煩的,需要手動去創建子表,app服務端讀寫時候需要計運算元表名。採用merge好一些,但也要創建子表和配置子表間的union關系。

4、表分區相對於分表,操作方便,不需要創建子表。

我們知道對於大型的互聯網應用,資料庫單表的數據量可能達到千萬甚至上億級別,同時面臨這高並發的壓力。Master-Slave結構只能對資料庫的讀能力進行擴展,寫操作還是集中在Master中,Master並不能無限制的掛接Slave庫,如果需要對資料庫的吞吐能力進行進一步的擴展,可以考慮採用分庫分表的策略。

**1、分表**

在分表之前,首先要選中合適的分表策略(以哪個字典為分表欄位,需要將數據分為多少張表),使數據能夠均衡的分布在多張表中,並且不影響正常的查詢。在企業級應用中,往往使用org_id(組織主鍵)做為分表欄位,在互聯網應用中往往是userid。在確定分表策略後,當數據進行存儲及查詢時,需要確定到哪張表裡去查找數據,

數據存放的數據表 = 分表欄位的內容 % 分表數量

**2、分庫**

分表能夠解決單表數據量過大帶來的查詢效率下降的問題,但是不能給資料庫的並發訪問帶來質的提升,面對高並發的寫訪問,當Master無法承擔高並發的寫入請求時,不管如何擴展Slave伺服器,都沒有意義了。我們通過對資料庫進行拆分,來提高資料庫的寫入能力,即所謂的分庫。分庫採用對關鍵字取模的方式,對資料庫進行路由。

數據存放的資料庫=分庫欄位的內容%資料庫的數量

**3、即分表又分庫**

資料庫分表可以解決單表海量數據的查詢性能問題,分庫可以解決單台資料庫的並發訪問壓力問題。

當資料庫同時面臨海量數據存儲和高並發訪問的時候,需要同時採取分表和分庫策略。一般分表分庫策略如下:

中間變數 = 關鍵字%(資料庫數量*單庫數據表數量)

庫 = 取整(中間變數/單庫數據表數量)

表 = (中間變數%單庫數據表數量)

實例:

1、分庫分表

很明顯,一個主表(也就是很重要的表,例如用戶表)無限制的增長勢必嚴重影響性能,分庫與分表是一個很不錯的解決途徑,也就是性能優化途徑,現在的案例是我們有一個1000多萬條記錄的用戶表members,查詢起來非常之慢,同事的做法是將其散列到100個表中,分別從members0到members99,然後根據mid分發記錄到這些表中,牛逼的代碼大概是這樣子:

復制代碼 代碼如下:

<?php

for($i=0;$i< 100; $i++ ){

//echo "CREATE TABLE db2.members{$i} LIKE db1.members
";

echo "INSERT INTO members{$i} SELECT * FROM members WHERE mid%100={$i}
";

}

?>

2、不停機修改mysql表結構

同樣還是members表,前期設計的表結構不盡合理,隨著資料庫不斷運行,其冗餘數據也是增長巨大,同事使用了下面的方法來處理:

先創建一個臨時表:

/*創建臨時表*/

CREATE TABLE members_tmp LIKE members

然後修改members_tmp的表結構為新結構,接著使用上面那個for循環來導出數據,因為1000萬的數據一次性導出是不對的,mid是主鍵,一個區間一個區間的導,基本是一次導出5萬條吧,這里略去了

接著重命名將新表替換上去:

/*這是個頗為經典的語句哈*/

RENAME TABLE members TO members_bak,members_tmp TO members;

就是這樣,基本可以做到無損失,無需停機更新表結構,但實際上RENAME期間表是被鎖死的,所以選擇在線少的時候操作是一個技巧。經過這個操作,使得原先8G多的表,一下子變成了2G多。

D. 資料庫(mysql)關鍵知識

Mysql是目前互聯網使用最廣的關系資料庫,關系資料庫的本質是將問題分解為多個分類然後通過關系來查詢。 一個經典的問題是用戶借書,三張表,一個用戶,一個書,一個借書的關系表。當需要查詢某個用戶借書情況或者是書被那些人借了,就用關系查詢來實現。

關系資料庫範式

來自英文Normal form,簡稱NF。要想設計—個好的關系,必須使關系滿足一定的約束條件,滿足這些規范的資料庫是簡潔的、結構明晰的,同時,不會發生插入(insert)、刪除(delete)和更新(update)操作異常。總共有六種範式:第一範式(1NF)、第二範式(2NF)、 第三範式 (3NF)、巴斯-科德範式(BCNF)、 第四範式 (4NF)和 第五範式 (5NF,又稱完美範式)。

1NF是指資料庫表的每一列都是不可分割的原子數據項。2NF必須滿足1NF,要求資料庫表中的每行記錄必須可以被唯一地區分。3NF在2NF基礎上,任何非主 屬性 不依賴於其它非主屬性(在2NF基礎上消除傳遞依賴)。BCNF是在3NF基礎上,任何非主屬性不能對主鍵子集依賴(在3NF基礎上消除對主碼子集的依賴), 滿足BCNF不再會有任何由於函數依賴導致的異常,但是我們還可能會遇到由於多值依賴導致的異常。4NF的定義很簡單:已經是BC範式,並且不包含多值依賴關系。5NF處理的是無損連接問題,這個範式基本沒有實際意義,因為無損連接很少出現,而且難以察覺。而域鍵範式試圖定義一個終極範式,該範式考慮所有的依賴和約束類型,但是實用價值也是最小的,只存在理論研究中。

Catalog和Schema

是資料庫對象命名空間中的層次,主要用來解決命名沖突的問題。從概念上說,一個資料庫系統包含多個Catalog,每個Catalog又包含多個Schema,而每個Schema又包含多個資料庫對象(表、視圖、欄位等)。但是Mysql的資料庫名就是Schema,不支持Catalog。

Mysql的資料庫引擎主要有兩種MyISAM和InnoDB,MyISAM支持全文檢索,InnoDB支持事務。

SQL中的通配符『%』代表任意字元出現任意次數。『_』代表任意字元出現一次。SQL與正則表達式結合查詢一般用在WHERE table_name REGEXP '^12.34'。子查詢是從里到外執行。

資料庫聯結(join)涉及到外鍵,外鍵是指一個表的列是另一個表的主鍵,那麼它就是外鍵。笛卡爾積聯結(不指定聯結條件時)生成的記錄條目是單純的第一個表的行乘以第二個表的列數。用得最多的是等值聯結也叫內部聯結。

高級聯結還有自連接,是指查詢中的兩張表是同一張表,它通常作為外部語句用來代替從相同表中檢索數據時使用的子查詢。自然聯結使每個列只返回一次。外部聯結是指聯結包含了那些在相關表中沒有關聯行的行。例如列出所有產品及其訂購數量,包括沒有人訂購的產品。LEFT OUTER JOIN指選擇左邊表的所有行。

組合查詢是指採用UNION等將兩個查詢結果取並集。

視圖是查看存儲在別處的數據的一種工具,它本身並不包含數據,因此表的數據修改了,視圖返回的數據也將隨之修改,因此如果使用了復雜或嵌套視圖會對性能有較大的影響。視圖的作用之一是隱藏復雜的SQL通常會涉及到聯結查詢。

存儲過程類似於批處理,包含了一條或多條SQL語句。語法:

CREATE PROCEDURE name()
BEGIN
SQL
END
-------------------------
CALL name()//來調用存儲過程

游標有DECLARE定義,游標與存儲過程是綁定的,存儲過程處理完成,游標就會消失。游標被打開後可以使用FETCH語句訪問每一行。

觸發器是在某個時間發生時自動執行某條SQL語句。語法:
CREATE TRIGGER name AFTER INSERT ON talbe_name FOR EACH ROW

事務處理可以維護資料庫的完整性,保證批量的操作要麼完全執行,要麼完全不執行。包括事務、回退、提交、保留點幾個關鍵術語。ROLLBACK只能在一個事務處理內使用。他不能回退CREATE和DROP操作。使用COMMIT保證事務提交。復雜的事務處理需要部分提交或回退,因此我們需要使用保留點SAVEPOINT。可以使用ROLLBACK TO savepoint_name。保留點越多越好。保留點在事務執行完成後自動釋放。

E. 如何保證數據安全性 MySQL資料庫設計優化技巧

1、優化設計的技巧
(1) 如果一個欄位需要經常更改,則採用以空間換時間的設計方法
最常見的例子是用戶積分登錄次數的累加,按照範式設計,在users表中建立一個欄位us_scores,以後需要在用戶積分改變時採用update的語句進行修改。但是知道 update語句的執行速度是很慢的,為了避免大量重復使用它,優化的設計方案是建立us_scores表,存儲每次增加的積分,在查詢是採用SQL語句的sum方法來計算之。
(2) 關聯欄位類型盡可能定義為數字類型
(3) 表的序列欄位必須是數字類型
(4) 若資料庫有移植的可能性,不使用存儲過程及觸發器
(5) 建立恰當的索引
索引的建立是加快資料庫查詢的基本技巧之一,通常的建議是,只有百萬級的記錄的表格才應該建立索引。
,命名都應該作為非常重要的事情來看待,表、序列、欄位、索引的命名技巧可以歸結如下:
(1) 關聯欄位名稱必須相同,名稱以基礎表的欄位名稱為准
(2) 序列名字跟表欄位名字相同
(3) 關聯表的名稱應該是被關聯的表用「_」連接起來組成的
(4) 欄位定義的前兩位是表名的縮寫,第三位是下劃線
一,保證規范,序列名稱必須是唯一的,而且,一般的序列就是這個表的id欄位。如果不加前綴,那麼欄位都叫做id就會違背惟一性原則。
第二,為了將來關聯查詢語句的書寫方便。
(5) 索引的名字和表的名字相同
(6) 常用欄位採用固定定義
為了提高大數據量的表格的查詢速度,可以採用建立適當的索引方式。如果一個表只有一個索引,建議索引的名字跟表相同,如果有多個索引,則為表名稱加下劃線加索引列名稱。
最安全的設計方案是,Web資料庫和測試資料庫分離。Web資料庫許可權只被管理員一個人掌握。
關於MySQL資料庫設計
的優化措施還需要經過資料庫設計人員的不斷發掘,從資料庫設計中不斷的發現問題,提出解決問題的方法,才能將資料庫的性能優化的更好更全面。

F. 資料庫表結構設計,常見的資料庫管理系統

一、數據場景 1、表結構簡介 任何工具類的東西都是為了解決某個場景下的問題,比如Redis緩存系統熱點數據,ClickHouse解決海量數據的實時分析,MySQL關系型資料庫存儲結構化數據。數據的存儲則需要設計對應的表結構,清楚的表結構,有助於快速開發業務,和理解系統。表結構的設計通常從下面幾個方面考慮:業務場景、設計規范、表結構、欄位屬性、數據管理。
2、用戶場景
例如存儲用戶基礎信息數據,通常都會下面幾個相關表結構:用戶信息表、單點登錄表、狀態管理表、支付賬戶表等。
用戶信息表
存儲用戶三要素相關信息:姓名,手機號,身份證,登錄密碼,郵箱等。
CREATE TABLE `ms_user_center` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶ID', `user_name` varchar(20) NOT NULL COMMENT '用戶名', `real_name` varchar(20) DEFAULT NULL COMMENT '真實姓名', `pass_word` varchar(32) NOT NULL COMMENT '密碼', `phone` varchar(20) NOT NULL COMMENT '手機號', `email` varchar(32) DEFAULT NULL COMMENT '郵箱', `head_url` varchar(100) DEFAULT NULL COMMENT '用戶頭像URL', `card_id` varchar(32) DEFAULT NULL COMMENT '身份證號', `user_sex` int(1) DEFAULT '1' COMMENT '用戶性別:0-女,1-男', `create_time` datetime DEFAULT NULL COMMENT '創建時間', `update_time` datetime DEFAULT NULL COMMENT '更新時間', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶表'; 單點登錄表
用意是在多個業務系統中,用戶登錄一次就可以訪問所有相互信任的業務子系統,是聚合業務平台常用的解決方案。
CREATE TABLE `ms_user_sso` ( `user_id` int(11) NOT NULL COMMENT '用戶ID', `sso_id` varchar(32) NOT NULL COMMENT '單點信息編號ID', `sso_code` varchar(32) NOT NULL COMMENT '單點登錄碼,唯一核心標識', `log_ip` varchar(32) DEFAULT NULL COMMENT '登錄IP地址', `create_time` datetime DEFAULT NULL COMMENT '創建時間', `update_time` datetime DEFAULT NULL COMMENT '更新時間', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶單點登錄表'; 狀態管理表
系統用戶在使用時候可能出現多個狀態,例如賬戶凍結、密碼鎖定等,把狀態聚合到一起,可以更加方便的管理和驗證。
CREATE TABLE `ms_user_status` ( `user_id` int(11) NOT NULL COMMENT '用戶ID', `account_status` int(1) DEFAULT '1' COMMENT '賬戶狀態:0-凍結,1-未凍結', `real_name_status` int(1) DEFAULT '0' COMMENT '實名認證狀態:0-未實名,1-已實名', `pay_pass_status` int(1) DEFAULT '0' COMMENT '支付密碼是否設置:0-未設置,1-設置', `wallet_pass_status` int(1) DEFAULT '0' COMMENT '錢包密碼是否設置:0-未設置,1-設置', `wallet_status` int(1) DEFAULT '1' COMMENT '錢包是否凍結:0-凍結,1-未凍結', `email_status` int(1) DEFAULT '0' COMMENT '郵箱狀態:0-未激活,1-激活', `message_status` int(1) DEFAULT '1' COMMENT '簡訊提醒開啟:0-未開啟,1-開啟', `letter_status` int(1) DEFAULT '1' COMMENT '站內信提醒開啟:0-未開啟,1-開啟', `emailmsg_status` int(1) DEFAULT '0' COMMENT '郵件提醒開啟:0-未開啟,1-開啟', `create_time` datetime DEFAULT NULL COMMENT '創建時間', `update_time` datetime DEFAULT NULL COMMENT '更新時間', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶狀態表'; 支付賬戶表
用戶交易的核心表,存儲用戶相關的賬戶資金信息。
CREATE TABLE `ms_user_wallet` ( `wallet_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '錢包ID', `user_id` int(11) NOT NULL COMMENT '用戶ID', `wallet_pwd` varchar(32) DEFAULT NULL COMMENT '錢包密碼', `total_account` decimal(20,2) DEFAULT '0.00' COMMENT '賬戶總額', `usable_money` decimal(20,2) DEFAULT '0.00' COMMENT '可用余額', `freeze_money` decimal(20,2) DEFAULT '0.00' COMMENT '凍結金額', `freeze_time` datetime DEFAULT NULL COMMENT '凍結時間', `thaw_time` datetime DEFAULT NULL COMMENT '解凍時間', `create_time` datetime DEFAULT NULL COMMENT '創建時間', `update_time` datetime DEFAULT NULL COMMENT '更新時間', `state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用', PRIMARY KEY (`wallet_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶錢包'; 二、設計規范 1、涉及模塊
通過上面幾個表設計的案例,可以看到表設計關聯到資料庫的各個方面知識:數據類型,索引,編碼,存儲引擎等。表設計是一個很大的命題,不過也遵循一個基本規范:三範式。
2、三範式 基礎概念
一範式

表的列的具有原子性,不可再分解,即列的信息,不能分解,關系型資料庫MySQL、Oracle等自動的滿足。

二範式

每個事實的數據記錄只會出現一次, 不會冗餘, 通常設計一個主鍵來實現。

三範式

要求一個表中不包含已經存在於其它表的非主鍵信息,例如部門和員工的信息,員工表包含部門表的主鍵ID,則可以關聯獲取相關信息,沒必要在員工表保存相關信息。
優缺點對比
範式化設計

範式化結構設計通常更新快,因為冗餘數據較少,表結構輕巧,也更好的寫入內存中。但是查詢起來涉及到關聯,代價非常高,非常損耗查詢性能。

反範式化設計

所有的數據都在一張表中,避免關聯查詢,索引的有效性更高,但是數據的冗餘性極高。
建議結論
上述的兩種設計方式在實際開發中都是不存在的,在實際開發中都是混合使用。比如匯總統計,緩存數據,都會基於反範式化的設計。
三、欄位屬性
合適的欄位類型對於高性能來說非常重要,基本原則如下:簡單的類型佔用資源更少;在可以正確存儲數據的情況下,選最小的數據類型。
1、數據類型選擇 整數類型
TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,根據數據類型範圍合理選擇即可。
實數類型
FLOAT、DOUBLE、DECIMAL,建議資金貨幣相關類型使用高精度DECIMAL存儲,或者把數據成倍擴大為整數,採用BIGINT存儲,不過處理相對麻煩。
字元類型
CHAR、VARCHAR,長度不確定建議採用VARCHAR存儲,不過VARCHAR類型需要額外開銷記錄字元串長度。CHAR適合存儲短字元,或者定長字元串,例如MD5的加密結構。
時間類型
DATETIME、TIMESTAMP,DATETIME保存大范圍的值,精度秒。TIMESTAMP以時間戳的格式,范圍相對較小,效率也相對較高,所以通常情況建議使用。

MySQL的欄位類型有很多種,可以根據數據特性選擇合適的,這里只描述常見的幾種類型。
2、基礎用法操作 數據類型
修改欄位類型
ALTER TABLE ms_user_sso MODIFY state CHAR(1) DEFAULT '0' ; ALTER TABLE ms_user_sso MODIFY state INT(1) DEFAULT '1' COMMENT '狀態:0不可用,1可用';
修改名稱位置
ALTER TABLE ms_user_sso CHANGE log_ip login_ip VARCHAR(32) AFTER update_time ; 索引使用
索引類型:主鍵索引,普通索引,唯一索引,組合索引,全文索引。這里演示普通索引的操作。MySQL的核心模塊,後續詳說。

添加索引
ALTER TABLE ms_user_wallet ADD INDEX user_id_index(user_id) ; CREATE INDEX state_index ON ms_user_wallet(state) ;
查看索引
SHOW INDEX FROM ms_user_wallet;
刪除索引
DROP INDEX state_index ON ms_user_wallet ;
修改索引

不具有真正意義上的修改,可以把原有的索引刪除之後,再次添加索引。
外鍵關聯
用處:外鍵關聯的作用保證多個數據表的數據一致性和完整性,建表時先有主表,後有從表;刪除數據表,需要先刪從表,再刪主表。復雜場景不建議使用,實際開發中用的也不多。

添加外鍵
ALTER TABLE ms_user_wallet ADD CONSTRAINT user_id_out_key FOREIGN KEY(user_id) REFERENCES ms_user_center(id) ;
刪除外鍵
ALTER TABLE ms_user_wallet DROP FOREIGN KEY user_id_out_key ; 四、表結構管理 1、查看結構 DESC ms_user_status ; SHOW CREATE TABLE ms_user_status ; 2、欄位結構 添加欄位 ALTER TABLE ms_user_status ADD `delete_time` datetime DEFAULT NULL COMMENT '刪除時間' ; 刪除欄位 ALTER TABLE ms_user_status DROP COLUMN delete_time ; 3、修改表名 ALTER TABLE ms_user_center RENAME ms_user_info ; 4、存儲引擎 存儲引擎 SELECT VERSION() ; SHOW ENGINES ;
MySQL 5.6 支持的存儲引擎有InnoDB、MyISAM、Memory、Archive、CSV、BLACKHOLE等。一般默認使用InnoDB,支持事務管理。該模塊MySQL核心,後續詳解。
修改引擎
數據量大的場景下,存儲引擎修改是一個難度極大的操作,容易會導致表的特性變動,引起各種後續反應,後續會詳說。
ALTER TABLE ms_user_sso ENGINE = MyISAM ; 5、修改編碼
表字元集默認使用utf8,通用,無亂碼風險,漢字3位元組,英文1位元組,utf8mb4是utf8的超集,有存儲4位元組例如表情符號時使用。
查看編碼 SHOW VARIABLES LIKE 'character%'; 修改編碼 ALTER TABLE ms_user_sso DEFAULT CHARACTER SET utf8mb4; 五、數據管理 1、增刪改查
添加數據
INSERT INTO ms_user_sso ( user_id,sso_id,sso_code,create_time,update_time,login_ip,state ) VALUES ( '1','SSO7637267','SSO78631273612', '2019-12-24 11:56:57','2019-12-24 11:57:01','127.0.0.1','1' );
更新數據
UPDATE ms_user_sso SET user_id = '1',sso_id = 'SSO20191224',sso_code = 'SSO20191224', create_time = '2019-11-24 11:56:57',update_time = '2019-11-24 11:57:01', login_ip = '127.0.0.1',state = '1' WHERE user_id = '1';
查詢數據

一般情況下都是禁止使用 select* 操作。
SELECT user_id,sso_id,sso_code,create_time,update_time,login_ip,state FROM ms_user_sso WHERE user_id = '1';
刪除數據
DELETE FROM ms_user_sso WHERE user_id = '2' ;
不帶where條件,就是刪除全部數據。原則上不允許該操作,優化篇會詳解。TRUNCATE TABLE也是清空表數據,但是佔用的資源相對較少。
2、數據安全 不可逆加密
這類加密演算法,多用來做數據驗證操作,比如常見的密碼驗證。
SELECT MD5('cicada')='' ; SELECT SHA('cicada')=''; SELECT PASSWORD('smile')='*' ; 可逆加密
安全性要求高的系統,需要做三級等保,對數據的安全性極高,數據在存儲時必須加密入庫,取出時候需要解密,這些就需要可逆加密。
SELECT DECODE(ENCODE('123456','key_salt'),'key_salt') ; SELECT AES_DECRYPT(AES_ENCRYPT('cicada','salt123'),'salt123');
上述數據安全的管理,也可以基於應用系統的服務(代碼)層進行處理,相對專業的流程是從數據生成源頭處理,規避數據傳遞過程泄露,造成不必要的風險。

G. MySQL知識點總結

只要欄位值還可以繼續拆分,就不滿足第一範式。

範式設計得越詳細,對某些實際操作可能會更好,但並非都有好處,需要對項目的實際情況進行設定。

在滿足第一範式的前提下,其他列都必須完全依賴於主鍵列。 如果出現不完全依賴,只可能發生在聯合主鍵的情況下:

實際上,在這張訂單表中,proct_name 只依賴於 proct_id ,customer_name 只依賴於 customer_id。也就是說,proct_name 和 customer_id 是沒用關系的,customer_name 和 proct_id 也是沒有關系的。

這就不滿足第二範式:其他列都必須完全依賴於主鍵列!

拆分之後,myorder 表中的 proct_id 和 customer_id 完全依賴於 order_id 主鍵,而 proct 和 customer 表中的其他欄位又完全依賴於主鍵。滿足了第二範式的設計!

在滿足第二範式的前提下,除了主鍵列之外,其他列之間不能有傳遞依賴關系。

表中的 customer_phone 有可能依賴於 order_id 、 customer_id 兩列,也就不滿足了第三範式的設計:其他列之間不能有傳遞依賴關系。

修改後就不存在其他列之間的傳遞依賴關系,其他列都只依賴於主鍵列,滿足了第三範式的設計!

查詢每門課的平均成績。

查詢 score 表中至少有 2 名學生選修,並以 3 開頭的課程的平均分數。

分析表發現,至少有 2 名學生選修的課程是 3-105 、3-245 、6-166 ,以 3 開頭的課程是 3-105 、3-245。也就是說,我們要查詢所有 3-105 和 3-245 的 degree 平均分。

查詢所有學生的 name,以及該學生在 score 表中對應的 c_no 和 degree 。

通過分析可以發現,只要把 score 表中的 s_no 欄位值替換成 student 表中對應的 name 欄位值就可以了,如何做呢?

查詢所有學生的 no 、課程名稱 ( course 表中的 name ) 和成績 ( score 表中的 degree ) 列。

只有 score 關聯學生的 no ,因此只要查詢 score 表,就能找出所有和學生相關的 no 和 degree :

然後查詢 course 表:

只要把 score 表中的 c_no 替換成 course 表中對應的 name 欄位值就可以了。

查詢所有學生的 name 、課程名 ( course 表中的 name ) 和 degree 。

只有 score 表中關聯學生的學號和課堂號,我們只要圍繞著 score 這張表查詢就好了。

只要把 s_no 和 c_no 替換成 student 和 srouse 表中對應的 name 欄位值就好了。

首先把 s_no 替換成 student 表中的 name 欄位:

再把 c_no 替換成 course 表中的 name 欄位:

查詢 95031 班學生每門課程的平均成績。

在 score 表中根據 student 表的學生編號篩選出學生的課堂號和成績:

這時只要將 c_no 分組一下就能得出 95031 班學生每門課的平均成績:

查詢在 3-105 課程中,所有成績高於 109 號同學的記錄。

首先篩選出課堂號為 3-105 ,在找出所有成績高於 109 號同學的的行。

查詢所有成績高於 109 號同學的 3-105 課程成績記錄。

查詢所有和 101 、108 號學生同年出生的 no 、name 、birthday 列。游御

查詢 '張旭' 教師任課的學生成績表。

首先找到教師編號悔中:

通過 sourse 表找到該神前岩教師課程號:

通過篩選出的課程號查詢成績表:

查詢某選修課程多於5個同學的教師姓名。

首先在 teacher 表中,根據 no 欄位來判斷該教師的同一門課程是否有至少5名學員選修:

查看和教師編號有有關的表的信息:

我們已經找到和教師編號有關的欄位就在 course 表中,但是還無法知道哪門課程至少有5名學生選修,所以還需要根據 score 表來查詢:

根據篩選出來的課程號,找出在某課程中,擁有至少5名學員的教師編號:

在 teacher 表中,根據篩選出來的教師編號找到教師姓名:

查詢 「計算機系」 課程的成績表。

思路是,先找出 course 表中所有 計算機系 課程的編號,然後根據這個編號查詢 score 表。

查詢 計算機系 與 電子工程系 中的不同職稱的教師。

查詢課程 3-105 且成績 至少 高於 3-245 的 score 表。

查詢課程 3-105 且成績高於 3-245 的 score 表。

查詢某課程成績比該課程平均成績低的 score 表。

查詢所有任課 ( 在 course 表裡有課程 ) 教師的 name 和 department

查詢 student 表中至少有 2 名男生的 class 。

查詢 student 表中不姓 "王" 的同學記錄。

查詢 student 表中每個學生的姓名和年齡。

查詢 student 表中最大和最小的 birthday 值。

以 class 和 birthday 從大到小的順序查詢 student 表。

查詢 "男" 教師及其所上的課程。

查詢最高分同學的 score 表。

查詢和 "李軍" 同性別的所有同學 name 。

查詢和 "李軍" 同性別且同班的同學 name 。

查詢所有選修 "計算機導論" 課程的 "男" 同學成績表。

需要的 "計算機導論" 和性別為 "男" 的編號可以在 course 和 student 表中找到。

建立一個 grade 表代表學生的成績等級,並插入數據:

查詢所有學生的 s_no 、c_no 和 grade 列。

思路是,使用區間 ( BETWEEN ) 查詢,判斷學生的成績 ( degree ) 在 grade 表的 low 和 upp 之間。

准備用於測試連接查詢的數據:

分析兩張表發現,person 表並沒有為 cardId 欄位設置一個在 card 表中對應的 id 外鍵。如果設置了的話,person 中 cardId 欄位值為 6 的行就插不進去,因為該 cardId 值在 card 表中並沒有。

要查詢這兩張表中有關系的數據,可以使用 INNER JOIN ( 內連接 ) 將它們連接在一起。

完整顯示左邊的表 ( person ) ,右邊的表如果符合條件就顯示,不符合則補 NULL 。

完整顯示右邊的表 ( card ) ,左邊的表如果符合條件就顯示,不符合則補 NULL 。

完整顯示兩張表的全部數據。

在 MySQL 中,事務其實是一個最小的不可分割的工作單元。事務能夠 保證一個業務的完整性

比如我們的銀行轉賬:

在實際項目中,假設只有一條 SQL 語句執行成功,而另外一條執行失敗了,就會出現數據前後不一致。

因此,在執行多條有關聯 SQL 語句時, 事務 可能會要求這些 SQL 語句要麼同時執行成功,要麼就都執行失敗。

在 MySQL 中,事務的 自動提交 狀態默認是開啟的。

自動提交的作用 :當我們執行一條 SQL 語句的時候,其產生的效果就會立即體現出來,且不能 回滾

什麼是回滾?舉個例子:

可以看到,在執行插入語句後數據立刻生效,原因是 MySQL 中的事務自動將它 提交 到了資料庫中。那麼所謂 回滾 的意思就是,撤銷執行過的所有 SQL 語句,使其回滾到 最後一次提交 數據時的狀態。

在 MySQL 中使用 ROLLBACK 執行回滾:

由於所有執行過的 SQL 語句都已經被提交過了,所以數據並沒有發生回滾。那如何讓數據可以發生回滾?

將自動提交關閉後,測試數據回滾:

那如何將虛擬的數據真正提交到資料庫中?使用 COMMIT :

事務的實際應用 ,讓我們再回到銀行轉賬項目:

這時假設在轉賬時發生了意外,就可以使用 ROLLBACK 回滾到最後一次提交的狀態:

這時我們又回到了發生意外之前的狀態,也就是說,事務給我們提供了一個可以反悔的機會。假設數據沒有發生意外,這時可以手動將數據真正提交到數據表中:COMMIT 。

事務的默認提交被開啟 ( @@AUTOCOMMIT = 1 ) 後,此時就不能使用事務回滾了。但是我們還可以手動開啟一個事務處理事件,使其可以發生回滾:

仍然使用 COMMIT 提交數據,提交後無法再發生本次事務的回滾。

事務的四大特徵:

事務的隔離性可分為四種 ( 性能從低到高 )

查看當前資料庫的默認隔離級別:

修改隔離級別:

測試 READ UNCOMMITTED ( 讀取未提交 ) 的隔離性:

由於小明的轉賬是在新開啟的事務上進行操作的,而該操作的結果是可以被其他事務(另一方的淘寶店)看見的,因此淘寶店的查詢結果是正確的,淘寶店確認到賬。但就在這時,如果小明在它所處的事務上又執行了 ROLLBACK 命令,會發生什麼?

這就是所謂的 臟讀 ,一個事務讀取到另外一個事務還未提交的數據。這在實際開發中是不允許出現的。

把隔離級別設置為 READ COMMITTED

這樣,再有新的事務連接進來時,它們就只能查詢到已經提交過的事務數據了。但是對於當前事務來說,它們看到的還是未提交的數據,例如:

但是這樣還有問題,那就是假設一個事務在操作數據時,其他事務干擾了這個事務的數據。例如:

雖然 READ COMMITTED 讓我們只能讀取到其他事務已經提交的數據,但還是會出現問題,就是 在讀取同一個表的數據時,可能會發生前後不一致的情況。* 這被稱為* 不可重復讀現象 ( READ COMMITTED )

將隔離級別設置為 REPEATABLE READ ( 可被重復讀取 ) :

測試 REPEATABLE READ ,假設在兩個不同的連接上分別執行 START TRANSACTION :

當前事務開啟後,沒提交之前,查詢不到,提交後可以被查詢到。但是,在提交之前其他事務被開啟了,那麼在這條事務線上,就不會查詢到當前有操作事務的連接。相當於開辟出一條單獨的線程。

無論小張是否執行過 COMMIT ,在小王這邊,都不會查詢到小張的事務記錄,而是只會查詢到自己所處事務的記錄:

這是 因為小王在此之前開啟了一個新的事務 ( START TRANSACTION ) * ,那麼* 在他的這條新事務的線上,跟其他事務是沒有聯系的 ,也就是說,此時如果其他事務正在操作數據,它是不知道的。

然而事實是,在真實的數據表中,小張已經插入了一條數據。但是小王此時並不知道,也插入了同一條數據,會發生什麼呢?

報錯了,操作被告知已存在主鍵為 6 的欄位。這種現象也被稱為 幻讀,一個事務提交的數據,不能被其他事務讀取到

顧名思義,就是所有事務的 寫入操作 全都是串列化的。什麼意思?把隔離級別修改成 SERIALIZABLE :

還是拿小張和小王來舉例:

此時會發生什麼呢?由於現在的隔離級別是 SERIALIZABLE ( 串列化 ) ,串列化的意思就是:假設把所有的事務都放在一個串列的隊列中,那麼所有的事務都會按照 固定順序執行 ,執行完一個事務後再繼續執行下一個事務的 寫入操作 ( 這意味著隊列中同時只能執行一個事務的寫入操作 ) 。

根據這個解釋,小王在插入數據時,會出現等待狀態,直到小張執行 COMMIT 結束它所處的事務,或者出現等待超時。

轉載: https://github.com/baa-god/sql_node/blob/master/mysql/

H. 如何用mysql設計表

選中某個表,然後右鍵點擊,選擇「設計表」即可。
也可以左鍵點擊某個表(即選中某表),在上面輔助菜單欄里有「打開表」、「設計表」、「新建表」等按鈕可點擊,點擊「設計表」按鈕即可。
進入後,會彈出新的操作窗口,新窗口的菜單欄里有常用的修改表結構的按鈕,右鍵點擊某列欄位也可以彈出相應的修改表的操作按鈕。
其它摸索著看提示操作即可,還是很簡單的。
修改好表後點擊菜單欄上的「保存」按鈕即可。
註:若要查看修改表的sql語句,必須在「保存」之前點擊「SQL預覽」按鈕。

I. 第一範式第二範式第三範式怎麼區分

滿足第一範式 就是每個屬性都不可在拆分,滿足第二範式,非屬性值要完全依賴主編碼 非碼屬性不相互依賴,滿足第三範式,不存在傳遞依賴。

J. 什麼是資料庫中的規范化

規范化理論把關系應滿足的規范要求分為幾級,滿足最低要求的一級叫做第一範式(1NF),在第一範式的基礎上提出了第二範式(2NF),在第二範式的基礎上又提出了第三範式(3NF),以後又提出了BCNF範式,4NF,5NF。範式的等級越高,應滿足的約束集條件也越嚴格。

第一範式(1NF)
在關系模式R中中,如果每個屬性值都是不可再分的原子屬性,則稱R是第一範式的關系[2]。例如:關系R(職工號,姓名,電話號碼)中一個人可能有一個辦公室電話和一個住宅電話號碼,規范成為1NF的方法一般是將電話號碼分為單位電話和住宅電話兩個屬性,即 R(職工號,姓名,辦公電話,住宅電話)。1NF是關系模式的最低要求。

第二範式(2NF)
如果關系模式R是1NF且其中的所有非主屬性都完全函數依賴於關鍵字,則稱關系R 是屬於第二範式的[2]。例:選課關系 SC(SNO,CNO,GRADE,CREDIT)其中SNO為學號, CNO為課程號,GRADEGE 為成績,CREDIT 為學分。 由以上條件,關鍵字為組合關鍵字(SNO,CNO)。在應用中使用以上關系模式有以下問題: (1)數據冗餘,假設同一門課由40個學生選修,學分就重復40次;(2)更新復雜,若調整了某課程的學分,相應元組的CREDIT值都要更新,有可能會出現同一門課學分不同;(3)插入異常,如計劃開新課,由於沒人選修,沒有學號關鍵字,只能等有人選修才能把課程和學分存入;(4).刪除異常,若學生已經結業,從當前資料庫刪除選修記錄,而某些課程新生尚未選修,則此門課程及學分記錄無法保存。以上問題產生的原因是非主屬性CREDIT僅函數依賴於CNO,也就是CREDIT部分依賴組合關鍵字(SNO,CNO)而不是完全依賴。解決方法是將以上關系分解成兩個關系模式 SC(SNO,CNO,GRADE)和C(CNO,CREDIT)。新關系包括兩個關系模式,它們之間通過SC中的外鍵CNO相聯系,需要時再進行自然聯接,恢復原來的關系

第三範式(3NF)
如果關系模式R是2NF且其中的所有非主屬性都不傳遞依賴於碼,則稱關系R是屬於第三範式的[1]。例如關系模式S(SNO,SNAME,DNO,DNAME,LOCATION)中各屬性分別代表學號、姓名、所在系、系名稱、系地址。關鍵字SNO決定各個屬性。由於是單個關鍵字,沒有部分依賴的問題,肯定是2NF。但關系S肯定有大量的冗餘,有關學生所在系的幾個屬性DNO,DNAME,LOCATION將重復存儲,插入、刪除和修改時也將產生類似以上例的情況。原因在於關系中存在傳遞依賴,即SNO -> DNO,DNO -> LOCATION, 因此關鍵字SNO對LOCATION函數決定是通過傳遞依賴SNO -> LOCATION 實現的。也就是說,SNO不直接決定非主屬性LOCATION。解決方法是將該關系模式分解為兩個關系S(SNO,SNAME,DNO)和D(DNO,DNAME,LOCATION),兩個關系通過S中的外鍵DNO聯系。

BC範式(BCNF)
如果關系模式R的所有屬性(包括主屬性和非主屬性)都不傳遞依賴於R的任何候選關鍵字,那麼稱關系R是屬於BCNF的。或者說關系模式R中,如果每個決定因素都包含關鍵字(而不是被關鍵字所包含),則R是BCNF[3]。 通常認為BCNF是修正的第三範式,有時也稱為擴充的第三範式。