MySQL 一 基礎知識
文章目錄
- 資料庫三大正規化?
- MySQLmysql有關許可權的表都有哪幾個?
- mysql有哪些資料型別?
- 超鍵、候選鍵、主鍵、外來鍵分別是什麼?
- SQL語句主要分為哪幾類?
- 說一說SQL欄位有哪幾種約束?
- 說一說SQL的關聯查詢?
- 說一說SQL的子查詢?
- mysql中 in 和 exists 的區別?
- varchar與char的區別?如何選擇?
- mysql中int(10)和char(10)以及varchar(10)的區別?
- MySQL中delete,drop,truncate的區別?
- MySQL的binlog有有幾種錄入格式?分別有什麼區別?
- MySQL有哪幾種日誌?
資料庫三大正規化?
轉載於:https://zhuanlan.zhihu.com/p/72197799
設計關係資料庫時,遵從不同的規範要求,設計出合理的關係型資料庫,這些不同的規範要求被稱為不同的正規化,各種正規化呈遞次規範,越高的正規化資料庫冗餘越小。但是有些時候一昧的追求正規化減少冗餘,反而會降低資料讀寫的效率,這個時候就要反正規化,利用空間來換時間。 目前關係資料庫有六種正規化:第一正規化(1NF)、第二正規化(2NF)、第三正規化(3NF)、巴斯-科德正規化(BCNF)、第四正規化(4NF)和第五正規化(5NF,又稱完美正規化)。滿足最低要求的正規化是第一正規化(1NF)。在第一正規化的基礎上進一步滿足更多規範要求的稱為第二正規化(2NF),其餘正規化以次類推。一般說來,資料庫只需滿足第三正規化(3NF)就行了。所以這裡就只記錄三正規化相關的知識。
1. 第一正規化:保證每列的原子性
也可以說每個列都不可以再拆分。舉個例子,看下錶:
住址這一列可拆為省份、城市和地址,拆完如下:
2. 在第一正規化的基礎上,非主鍵列完全依賴於主鍵,而不能是依賴於主鍵的一部分
舉個例子,看下錶:
上表滿足第一正規化,即每個欄位不可再分,但是學分依賴於非主鍵課程,所以不滿足第二正規化,會造成資料冗餘、更新異常、插入異常和刪除異常。修改後:
3. 在第二正規化的基礎上,非主鍵列只依賴於主鍵,不依賴於其他非主鍵
第三正規化又和第二正規化相關,用第三正規化的定義描述第三正規化就是,資料庫表中如果不存在非關鍵欄位任一候選關鍵欄位的傳遞函式依賴則符合第三正規化,所謂傳遞函式依賴指的是如果存在"A–>B–>C"的決定關係,則C傳遞函式依賴於A。也就是說表中的欄位和主鍵直接對應不依靠其他中間欄位,說白了就是,決定某欄位值的必須是主鍵。
舉個例子,看下錶:
第三正規化和第二正規化有點像,從這張資料庫表結構中可以看出,“姓名”、“年齡”、“學院"和主鍵"學號"直接關聯,但是"學院地點”、“學院電話"卻不直接和主鍵"學號"相關聯,和"學院電話"直接相關聯的是"學院”,如果表結構這麼設計,同樣會造成和第二正規化一樣的資料冗餘、更新異常、插入異常、刪除異常的問題。更改後:
MySQLmysql有關許可權的表都有哪幾個?
MySQL伺服器通過許可權表來控制使用者對資料庫的訪問,許可權表存放在mysql資料庫裡,由mysql_install_db指令碼初始化。這些許可權表分別user,db,table_priv,columns_priv和host。
下面分別介紹一下這些表的結構和內容:
- user許可權表:記錄允許連線到伺服器的使用者帳號資訊,裡面的許可權是全域性級的。
- db許可權表:記錄各個帳號在各個資料庫上的操作許可權。
- table_priv許可權表:記錄資料表級的操作許可權。
- columns_priv許可權表:記錄資料列級的操作許可權。
- host許可權表:配合db許可權表對給定主機上資料庫級操作許可權作更細緻的控制。這個許可權表不受GRANT和REVOKE語句的影響。
mysql有哪些資料型別?
分類 | 型別名稱 | 說明 |
---|---|---|
整數型別 | tinyInt | 很小的整數(8位二進位制) |
smallint | 小的整數(16位二進位制) | |
mediumint | 中等大小的整數(24位二進位制) | |
int(integer) | 普通大小的整數(32位二進位制) | |
小數型別 | float | 單精度浮點數 |
double | 雙精度浮點數 | |
decimal(m,d) | 壓縮嚴格的定點數 | |
日期型別 | year | YYYY 1901~2155 |
time | HH:MM:SS -838:59:59~838:59:59 | |
date | YYYY-MM-DD 1000-01-01~9999-12-3 | |
datetime | YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~ 9999-12-31 23:59:59 | |
timestamp | YYYY-MM-DD HH:MM:SS 19700101 00:00:01 UTC~2038-01-19 03:14:07UTC | |
文字、二進位制型別 | CHAR(M) | M為0~255之間的整數 |
VARCHAR(M) | M為0~65535之間的整數 | |
TINYBLOB | 允許長度0~255位元組 | |
BLOB | 允許長度0~65535位元組 | |
MEDIUMBLOB | 允許長度0~167772150位元組 | |
LONGBLOB | 允許長度0~4294967295位元組 | |
TINYTEXT | 允許長度0~255位元組 | |
TEXT | 允許長度0~65535位元組 | |
MEDIUMTEXT | 允許長度0~167772150位元組 | |
LONGTEXT | 允許長度0~4294967295位元組 | |
VARBINARY(M) | 允許長度0~M個位元組的變長位元組字串 | |
BINARY(M) | 允許長度0~M個位元組的定長位元組字串 |
超鍵、候選鍵、主鍵、外來鍵分別是什麼?
超鍵(super key): 在關係中能唯一標識元組的屬性集稱為關係模式的超鍵
候選鍵(candidate key): 不含有多餘屬性的超鍵稱為候選鍵。也就是在候選鍵中,若再刪除屬性,就不是超鍵了!
主鍵(primary key): 使用者選作元組標識的一個候選鍵程式主鍵
外來鍵(foreign key):如果關係模式R中屬性K是其它模式的主鍵,那麼k在模式R中稱為外來鍵。
舉個例子:
兩張表:
學生資訊(學號 身份證號 性別 年齡 身高 體重 宿舍號)
宿舍資訊(宿舍號 樓號)
- 超鍵:只要含有“學號”或者“身份證號”兩個屬性的集合就叫超鍵,例如R1(學號 性別)、R2(身份證號 身高)、R3(學號 身份證號)等等都可以稱為超鍵!
- 候選鍵:不含有多餘的屬性的超鍵,比如(學號)、(身份證號)都是候選鍵,又比如R1中學號這一個屬性就可以唯一標識元組了,而有沒有性別這一屬性對是否唯一標識元組沒有任何的影響!
- 主鍵:就是使用者從很多候選鍵選出來的一個鍵就是主鍵,比如你要求學號是主鍵,那麼身份證號就不可以是主鍵了!
- 宿舍號就是學生資訊表的外來鍵
SQL語句主要分為哪幾類?
-
資料定義語言DDL(Data Ddefinition Language)
主要為CREATE,DROP,ALTER等操作 即對邏輯結構等有操作的,其中包括表結構,檢視和索引。
-
資料查詢語言DQL(Data Query Language)SELECT
這個較為好理解 即查詢操作,以select關鍵字。各種簡單查詢,連線查詢等 都屬於DQL。
-
資料操縱語言DML(Data Manipulation Language)
主要為INSERT,UPDATE,DELETE等操作 即對資料進行操作的,對應上面所說的查詢操作 DQL與DML共同構建了多數初級程式設計師常用的增刪改查操作。而查詢是較為特殊的一種 被劃分到DQL中。
-
資料控制功能DCL(Data Control Language)
主要為GRANT,REVOKE,COMMIT,ROLLBACK等操作 即對資料庫安全性完整性等有操作的,可以簡單的理解為許可權控制等。
說一說SQL欄位有哪幾種約束?
- NOT NULL: 用於控制欄位的內容一定不能為空(NULL)。
- UNIQUE: 控制元件欄位內容不能重複,一個表允許有多個 Unique 約束。
- PRIMARY KEY: 也是用於控制元件欄位內容不能重複,但它在一個表只允許出現一個。
- FOREIGN KEY: 用於預防破壞表之間連線的動作,也能防止非法資料插入外來鍵列,因為它必須是它指向的那個表中的值之一。
- CHECK: 用於控制欄位的值範圍。
說一說SQL的關聯查詢?
- 內連線(INNER JOIN)
內連線分為三類: 1. 等值連線:ON A.id=B.id 2. 不等值連線:ON A.id > B.id 3. 自連線:SELECT * FROM A T1 INNER JOIN A T2 ON T1.id=T2.pid
- 外連線(LEFT JOIN/RIGHT JOIN)
左外連線:LEFT OUTER JOIN, 以左表為主,先查詢出左表,按照ON後的關聯條件匹配右表,沒有匹配到的用NULL填充,可以簡寫成LEFT JOIN 右外連線:RIGHT OUTER JOIN, 以右表為主,先查詢出右表,按照ON後的關聯條件匹配左表,沒有匹配到的用NULL填充,可以簡寫成RIGHT JOIN
- 聯合查詢(UNION與UNION ALL)
SELECT * FROM A UNION SELECT * FROM B UNION ... 1. 就是把多個結果集集中在一起,UNION前的結果為基準,需要注意的是聯合查詢的列數要相等,相同的記錄行會合並 2. 如果使用UNION ALL,不會合並重復的記錄行 3. 效率 UNION 高於 UNION ALL
- 全連線(FULL JOIN)
MySQL不支援全連線可以使用LEFT JOIN 和UNION和RIGHT JOIN聯合使用 SELECT * FROM A LEFT JOIN B ON A.id=B.id UNIONSELECT * FROM A RIGHT JOIN B ON A.id=B.id
- 交叉連線(CROSS JOIN)
說一說SQL的子查詢?
條件:一條SQL語句的查詢結果做為另一條查詢語句的條件或查詢結果
巢狀:多條SQL語句巢狀使用,內部的SQL查詢語句稱為子查詢。
三種情況:
子查詢是單行單列的情況:結果集是一個值,父查詢使用:=、 <、 > 等運算子
// 查詢工資最高的員工是誰?
select * from employee where salary=(select max(salary) from employee);
子查詢是多行單列的情況:結果集類似於一個數組,父查詢使用:in 運算子
// 查詢工資最高的員工是誰?
select * from employee where salary=(select max(salary) from employee);
子查詢是多行多列的情況:結果集類似於一張虛擬表,不能用於where條件,用於select子句中做為子表
// 1) 查詢出2011年以後入職的員工資訊
// 2) 查詢所有的部門資訊,與上面的虛擬表中的資訊比對,找出所有部門ID相等的員工。
select * from dept d, (select * from employee where join_date > '2011-1-1') e where e.dept_id = d.id;
// 使用表連線:
select d.*, e.* from dept d inner join employee e on d.id = e.dept_id where e.join_date > '2011-1-1'
mysql中 in 和 exists 的區別?
https://cloud.tencent.com/developer/article/1144244
https://www.jianshu.com/p/f212527d76ff
select * from A where id in (select id from B);
select * from A where exists (select 1 from B where A.id=B.id);
-
in() 語句內部原理
IN()只執行一次,它查出B表中的所有id欄位並快取起來。之後,檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結果集中,直到遍歷完A表的所有記錄。
可以看出,當B表資料較大時不適合使用in(),因為它會把B表資料全部遍歷一次
舉例:A表有10000條記錄,B表有1000000條記錄,那麼最多有可能遍歷10000*1000000次,效率很差。
-
EXISTS() 語句內部工作原理
exists對外表用loop逐條查詢,每次查詢都會檢視exists的條件語句,當exists裡的條件語句能夠返回記錄行時(無論記錄行是的多少,只要能返回),條件就為真,返回當前loop到的這條記錄;反之,如果exists裡的條件語句不能返回記錄行,則當前loop到的這條記錄被丟棄,exists的條件就像一個bool條件,當能返回結果集則為true,不能返回結果集則為false
當B表比A表資料大時適合使用exists(),因為它沒有那麼多遍歷操作,只需要再執行一次查詢就行。
舉例: A表有10000條記錄,B表有1000000條記錄,那麼exists()會執行10000次去判斷A表中的id是否與B表中的id相等。
varchar與char的區別?如何選擇?
char的特點:
1. char表示定長字串,長度是固定的;
2. 如果插入資料的長度小於char的固定長度時,則用空格填充;
3. 因為長度固定,所以存取速度要比varchar快很多,甚至能快50%,但正因為其長度固定,所以會佔據多餘的空間,是空間換時間的做法;
4. 對於char來說,最多能存放的字元個數為255,和編碼無關
varchar的特點:
1. varchar表示可變長字串,長度是可變的;
2. 插入的資料是多長,就按照多長來儲存;
3. varchar在存取方面與char相反,它存取慢,因為長度不固定,但正因如此,不佔據多 餘的空間,是時間換空間的做法;
4. 對於varchar來說,最多能存放的字元個數為65532
如何選擇?
1. 對於經常變更的資料來說,CHAR比VARCHAR更好,因為CHAR不容易產生碎片。
2. 對於非常短的列,CHAR比VARCHAR在儲存空間上更有效率。
3. 使用時要注意只分配需要的空間,更長的列排序時會消耗更多記憶體。
4. 儘量避免使用TEXT/BLOB型別,查詢時會使用臨時表,導致嚴重的效能開銷。
mysql中int(10)和char(10)以及varchar(10)的區別?
- int(10)的10表示顯示的資料的長度,不是儲存資料的大小;
- char(10)表示儲存定長的10個字元,不足10個就用空格補齊,佔用更多的儲存空間;
- varchar(10)表示儲存10個變長的字元,儲存多少個就是多少個,空格也按一個字元儲存,這一點是和char(10)的空格不同的,char(10)的空格表示佔位不算一個字元
MySQL中delete,drop,truncate的區別?
三者都表示刪除,但是三者有一些差別:
Delete | Truncate | Drop | |
---|---|---|---|
型別 | 屬於DML | 屬於DDL | 屬於DDL |
回滾 | 可回滾 | 不可回滾 | 不可回滾 |
刪除內容 | 表結構還在,刪除表的全部或者一部分資料行 | 表結構還在,刪除表中的所有資料 | 從資料庫中刪除表,所有的資料行,索引和許可權也會被刪除 |
刪除速度 | 刪除速度慢,需要逐行刪除 | 刪除速度快 | 刪除速度最快 |
因此,當不再需要一張表的時候,用drop;在想刪除部分資料行時候,用delete;在保留表而刪除所有資料的時候用truncate。
MySQL的binlog有有幾種錄入格式?分別有什麼區別?
有三種格式,statement,row和mixed。
- statement模式下,每一條會修改資料的sql都會記錄在binlog中。不需要記錄每一行的變化,減少了binlog日誌量,節約了IO,提高效能。由於sql的執行是有上下文的,因此在儲存的時候需要儲存相關的資訊,同時還有一些使用了函式之類的語句無法被記錄複製。
- row級別下,不記錄sql語句上下文相關資訊,僅儲存哪條記錄被修改。記錄單元為每一行的改動,基本是可以全部記下來但是由於很多操作,會導致大量行的改動(比如alter table),因此這種模式的檔案儲存的資訊太多,日誌量太大。
- mixed,一種折中的方案,普通操作使用statement記錄,當無法使用statement的時候使用row。
此外,新版的MySQL中對row級別也做了一些優化,當表結構發生變化的時候,會記錄語句而不是逐行記錄。