SQL基礎
1.MySQL的數據類型

2.MySQL的SQL語句分類
DDL(Data Definition Language)語句:數據定義語言,這些語句定義了不同的數據段、表、列、索引等數據庫對象的定義。常用的語句關鍵字主要包括create、drop、alter等。
DML(Data Manipulation Language)語句:數據操縱語句,用於添加、刪除、更新和查詢數據庫記錄,並檢查數據完整性,常用的語句關鍵字主要包括insert、delete、update和select等。
DCL(Data Control Language)語句:數據控制語句,用於控制不同數據段直接的許可和訪問級別的語句。這些語句定義了數據庫、表、字段、用戶的訪問權限和安全級別。主要的語句關鍵字包括grant、revoke等。
數據庫范式
第一范式(1NF)是指在關系模型中,數據庫表的每一列都是不可分割的原子數據項,而不能是集合,數組,記錄等非原子數據項。
第二范式(2NF)是在1NF的基礎上,要求實體的屬性完全依賴於主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性
第三范式(3NF)在2NF基礎上,任何非主屬性不依賴於其它非主屬性(在2NF基礎上消除傳遞依賴)
巴斯-科德范式(BCNF)在3NF基礎上,任何非主屬性不能對主鍵子集依賴(在3NF基礎上消除對主碼子集的依賴)
白話區:
第一范式:每個表應該有唯一標識每一行的主鍵。
第二范式:在復合主鍵的情況下,非主鍵部分不應該依賴於部分主鍵。
第三范式:非主鍵之間不應該有依賴關系。
BC范式:排除了任何屬性(不光是非主屬性,2NF和3NF所限制的都是非主屬性)對候選鍵的傳遞依賴與部分依賴。
MyISAM與Innodb區別
(1)MyISAM不支持事務,Innodb支持事務
(2)Myisam不支持外鍵,innodb支持外鍵
(3)myisam支持表級鎖,innodb支持行級鎖
(4)innodb 進行select count(*) from tablename時,需要對表進行一次遍歷;myisam進行select count(*) from tablename時
(5)myisam刪除表時,先將表drop,然后新建一個表;innodb則是將表中數據一條一條的刪除
(6)對於包含auto-increment字段的索引,innodb只包含auto-increment字段;而myisam則可以和其他字段一起建立聯合索引
(7)myisam搜索引擎查找要比innodb搜索引擎快
(8)innodb中索引沒有fulltext類型,而myisam中有fulltext類型
視圖
視圖(View)是一種虛擬存在的表,對於使用視圖的用戶來說基本上是透明的。視圖並
不在數據庫中實際存在,行和列數據來自定義視圖的查詢中使用的表,並且是在使用視圖時
動態生成的
簡單:使用視圖的用戶完全不需要關心后面對應的表的結構、關聯條件和篩選條件,
對用戶來說已經是過濾好的復合條件的結果集。
安全:使用視圖的用戶只能訪問他們被允許查詢的結果集,對表的權限管理並不能
限制到某個行某個列,但是通過視圖就可以簡單的實現。
數據獨立:一旦視圖的結構確定了,可以屏蔽表結構變化對用戶的影響,源表增加
列對視圖沒有影響;源表修改列名,則可以通過修改視圖來解決,不會造成對訪問
者的影響
事務的特性及隔離級別:
1.事務特性--ACID
Atomicity(原子性):要么全做,要么不做,不能只做一半(銀行轉賬)
Consistency(約束性):事務的前后,約束都能滿足
Isolation(依賴性):事務之間是獨立的,互不影響的
Durability(持久性):事務執行之后,事物的結果可以持久保存
2.事務隔離級別:
read uncommitted:可以讀到未提交的事務結果
read committed:只能讀已提交事務的結果
repeatable reads:可以讀到開啟事務時的值
serializable:兩個事務同時發生,必定是有先后的
索引
1.什么是索引
索引(Index)是幫助MySQL高效獲取數據的數據結構。
2.索引的種類
從邏輯角度
1、主鍵索引:主鍵是一種唯一性索引,但它必須指定為“PRIMARY KEY”
2、唯一索引:不允許具有索引值相同的行,從而禁止重復的索引或鍵值。系統在創建該索引時檢查是否有重復的鍵值,並在每次使用 INSERT 或 UPDATE 語句添加數據時進行檢查。
3、組合索引
從物理存儲角度
1、聚簇索引(clustered index):聚簇索引的葉子節點就是數據節點
2、非聚簇索引(non-clustered index):非聚簇索引的葉子節點仍然是索引節點,只不過有指向對應數據塊的指針。

從數據結構角度
1、B+樹索引
2、hash索引
3、FULLTEXT索引(InnoDB引擎5.7以后支持):
3.索引的設計原則

4.索引存在但是不使用索引
(1)如果MySQL估計使用索引比全表掃描更慢,則不使用索引。例如如果列key_part1均勻分布在1~100之間,下列查詢使用索引就不是很好
SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90;
(2)如果使用 MEMORY/HEAP 表並且 where 條件中不使用“=”進行索引列,那么不會用到索引。heap 表只有在“=”的條件下才會使用索引。
(3)用 or 分割開的條件,如果 or 前的條件中的列有索引,而后面的列中沒有索引,那么涉及到的索引都不會被用到,例如
(4)對於符合索引如果不是第一列,在查詢中也不會被MySQL用到
(5)如果like是以%開始,那么索引不會被MySQL使用
(6)如果列類型是字符串,那么一定記得在 where 條件中把字符常量值用引號引起來,否則的話即便這個列上有索引,MySQL 也不會用到的,因為,MySQL 默認把輸入的常量值進行轉換以后才進行檢索。
5.B+Tree索引
B+樹:B+樹是為磁盤或其他直接存取輔助設備設計的一種平衡查找樹。在B+樹中,所有記錄結點都是按鍵值的大小順序存放在同一層的葉子節點上,由各葉子節點指針進行連接。
數據庫中B+樹索引分為聚集索引和輔助索引,兩者內部都是B+樹,即高度平衡的,葉子節點存放着所有的數據。聚集索引與輔助索引不同的是,葉子節點存放的是否是一整行的信息。
聚集索引
聚集索引:聚集索引就是按照每張表的主鍵構造的一棵B+樹,同時葉子節點中存放的即為整張表的行記錄數據,也將聚集索引的葉子節點稱為數據頁。
輔助索引
慢查詢
1.為什么查詢速度會慢
查詢性能低下最基本的原因是訪問的數據太多。某些查詢可能不可避免的需要篩選大量數據,但這並不常見。大部分性能低下的查詢都可以減少訪問的數據量的方式進行優化。對於低效的查詢,我們發現通過下面兩個步驟來分析總是很有效:
(1)確認應用程序是否在檢索大量超過需要的數據。這通常意味着訪問了太多的行,但有時候也可能是訪間了太多的列。
(2)確認MYSQL服務器層是否在分析大量超過需要的數據行。
2.慢查詢基礎
(1)是否向數據庫請求了不需要的數據
查詢不需要的記錄
一個常見的錯誤是常常會誤以為MYSQL會只返回需要的數據,實際上MYSQL卻
是先返回全部結果集再進行計算。我們經常會看到一些了解其他數據庫系統的人會
設計出這類應用程序。這些開發者習慣使用這樣的技術,先使用SELECT語句查詢大
量的結果,然后獲取前面的N行后關閉結果集(例如在新聞網站中取出100條記錄,
但是只是在頁面上顯示前面10條)。他們認為MYSQL會執行查詢,並只返回他們
需要的10條數據,然后停止查詢。實際情況是MYSQL會查詢出全部的結果集,客
戶端的應用程序會接收全部的結果集數據,然后拋棄其中大部分數據。最簡單有效
的解決方法就是在這樣的查詢后面加上LIMIT。
多表關聯時返回全部列
如果你想查詢所有在電影Academy Dinosaur中出現的演員,千萬不要按下面的寫法
編寫查詢:
ysql> select FRO sakila. Actor MER torn sakila. fin actor usimg(actor. id -2 INBROR, 5azla to. Mt -) WERE sakila. Film. Title - 'acadery Dinosaur'; 這將返回這三個表的全部數據列。正確的方式應該是像下面這樣只取需要的列: my5ql> SELECT sakila. Actor. " fro sakila. Actor. . ;
總是取出全部列
每次看到SELECT *的時候都需要用懷疑的眼光審視,是不是真的需要返回全部的
列?很可能不是必需的。取出全部列,會讓優化器無法完成索引覆蓋掃描這類優化,
還會為服務器帶來額外的I/O、內存和CPU的消耗。因此,一些DBA是嚴格禁止
SELECT *的寫法的,這樣做有時候還能避免某些列被修改帶來的問題。
當然,查詢返回超過需要的數據也不總是壞事。在我們研究過的許多案例中,人們
會告訴我們說這種有點浪費數據庫資源的方式可以簡化開發,因為能提高相同代碼
片段的復用性,如果清楚這樣做的性能影響,那么這種做法也是值得考慮的。如果
應用程序使用了某種緩存機制,或者有其他考慮,獲取超過需要的數據也可能有其
好處,但不要忘記這樣做的代價是什么。獲取並緩存所有的列的查詢,相比多個獨
立的只獲取部分列的查詢可能就更有好處。
重復查詢相同的數據
如果你不太小心,很容易出現這樣的錯誤——不斷地重復執行相同的查詢,然后每
次都返回完全相同的數據。例如,在用戶評論的地方需要查詢用戶頭像的URL,那
么用戶多次評論的時候,可能就會反復查詢這個數據。比較好的方案是,當初次查
的的時候將這個數據緩存起來,需要的時候從緩存中取出,這樣性能顯然會更好
(2)MySQL是否在掃描額外的記錄
響應時間
掃描行數
返回的行數
3.查看慢查詢日志
慢查詢日志記錄了包含所有執行時間超過參數 long_query_time(單位:秒)所設置值的 SQL
語句的日志。獲得表鎖定的時間不算作執行時間。
(1) 文件位置和格式
當用--log-slow-queries[=file_name]選項啟動 mysqld(MySQL 服務器)時,慢查詢日志開始被
記錄。和前面幾種日志一樣,如果沒有給定 file_name 的值,日志將寫入參數 DATADIR(數
據目錄)指定的路徑下,默認文件名是 host_name-slow.log。
(2) 日志的讀取
和錯誤日志、查詢日志一樣,慢查詢日志記錄的格式也是純文本,可以被直接讀取。下例中
演示了慢查詢日志的設置和讀取過程。
(2.1)首先查詢一下 long_query_time 的值。
mysql> show variables like 'long%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | long_query_time | 10 | +-----------------+-------+ 1 row in set (0.00 sec)
(2.2)為了方便測試,將修改慢查詢時間為 2 秒。
mysql> set long_query_time=2; Query OK, 0 rows affected (0.02 sec)
(2.3)依次執行下面兩個查詢語句。
第一個查詢因為查詢時間低於 2 秒而不會出現在慢查詢日志中:
mysql> select count(1) from emp; +----------+ | count(1) | +----------+ | 131075 | +----------+ 1 row in set (0.00 sec)
第二個查詢因為查詢時間大於 2 秒而應該出現在慢查詢日志中:
mysql> select count(1) from emp t1,dept t2 where t1.id=t2.id; 322 +----------+ | count(1) | +----------+ | 33555200 | +----------+ 1 row in set (11.31 sec)
(2.4)查看慢查詢日志。
[root@localhost mysql]# more localhost-slow.log /usr/sbin/mysqld, Version: 5.0.41-community-log (MySQL Community Edition (GPL)). started with: Tcp port: 3306 Unix socket: /var/lib/mysql/mysql.sock Time Id Command Argument # Time: 070810 23:43:55 # User@Host: root[root] @ localhost [] # Query_time: 297 Lock_time: 0 Rows_sent: 0 Rows_examined: 26214 use test; # Query_time: 11 Lock_time: 0 Rows_sent: 1 Rows_examined: 512 select count(1) from emp t1,dept t2 where t1.id=t2.id;
從上面日志中,可以發現查詢時間超過 2 秒的 SQL,而小於 2 秒的則沒有出現在此日志中。
如果慢查詢日志中記錄內容很多,可以使用 mysqldumpslow 工具(MySQL 客戶端安裝自帶)
來對慢查詢日志進行分類匯總。下例中對日志文件 bj37-slow.log 進行了分類匯總,只顯示匯
總后摘要結果:
[zzx@bj37 data]$ mysqldumpslow bj37-slow.log [root@localhost mysql]# mysqldumpslow localhost-slow.log Reading mysql slow query log from localhost-slow.log Count: 1 Time=297.00s (297s) Lock=0.00s (0s) Rows=0.0 (0), root[root]@localhost select count(N) from emp t1,emp t2 where t1.id<>t2.id Count: 2 Time=11.00s (22s) Lock=0.00s (0s) Rows=1.0 (2), root[root]@localhost select count(N) from emp t1,dept t2 where t1.id=t2.id Count: 1 Time=9.00s (9s) Lock=0.00s (0s) Rows=0.0 (0), root[root]@localhost select count(N) from emp t1,emp t2 where t1.id=t2.id Count: 2 Time=3.00s (6s) Lock=0.00s (0s) Rows=1.0 (2), root[root]@localhost select count(N) from emp t1,dept t2 where t1.id=t2.id and t1.id=N
對於 SQL 文本完全一致,只是變量不同的語句,mysqldumpslow 將會自動視為同一個語句進
行統計,變量值用 N 來代替。這個統計結果將大大增加用戶閱讀慢查詢日志的效率,並迅
速定位系統的 SQL 瓶頸。
注意:慢查詢日志對於我們發現應用中有性能問題的 SQL 很有幫助,建議正常情況下,打開此
日志並經常查看分析。
(3) 其他選項
在 MySQL 5.1 中,通過--log-slow-admin-statements 服務器選項,可以請求將慢管理語句,例
如 OPTIMIZE TABLE、ANALYZE TABLE 和 ALTER TABLE 寫入慢查詢日志
MySQL優化
1.優化SQL語句
(1)通過show status命令了解各種SQL的執行效率
例如show status like 'Com_%'
Com_select:執行select操作的次數,一次查詢只累加1.
Com_insert:執行insert操作的次數,對於批量插入的INSERT操作,只累加一次。
Com_updated:執行UPDATE操作的次數。
Com_deleted:執行delle操作的次數。
Innodb_rows_read:select查詢返回的行數.
Innodb_rows_inserted:執行INSERT操作插入的行數。
Innodb_rows_updated:執行UPDATE操作更新的行數
Innodb_rows_deleted:執行DELETE操作刪除的行數。
Connections::圖連接MYSQL服務器的次數。
Uptime:服務器工作時間。
Slow_queries:慢查詢的次數。
(2)定位性效率較低的SQL語句
通過慢查詢日志定位那些執行效率較低的sql語句,用--log-slow-queries[=file_name]選
項啟動時,mysqld寫一個包含所有執行時間超過long_query_time秒的SQL語句的日志
文件。
慢查詢日志在查詢結束以后才紀錄,所以在應用反映執行效率出現問題的時候慢查
詢日志並不能定位問題,可以使用show processlist命令查看當前mysql在進行的線程,
包括線程的狀態、是否鎖表等,可以實時地查看SOL的執行情況,同時對一些鎖表操
作進行優化。
(3)通過Explain分析低效SQL的執行計划
Explain解析的每一列含義:
select_type:表示select的類型,常見的取值有simple(簡單表,即不使用表連接
或者子查詢)、PRIMARV(主查詢,即外層的查詢)、UNION(UNION中的第二個或
中的第二個或者后面的查詢語句)、SUBQUERY (子查詢中的第一個SHLECT)等。
table:輸出結果集的表。
type:表示表的連接類型,性能由好到差的連接類型為
system(表中僅有一行,即常量表)、
const(單表中最多有一個匹配行,例如primary key或者unique index).
eq_ref(對於前面的每一行,在此表中只查詢一條記錄,簡單來說,就是多表連接中使用primary key或者unique index)、
ref(與eq_ref類似,區別在於不是使用primary key或者unique index,而是使用普通的索引)、
ref_or_null(與ref類似,區別在於條件中包含對NULL的查詢)、
index_merge(索引合並優化)、
unique_subquery (in的后面是一個查詢主鍵字段的子查詢)、
index_subquery(與unique_Subquery類似,區別在於in的后面是查詢非唯一索引字段的子查詢)、
range(單表中的范圍查詢)、
index(對於前面的每一行,都通過查詢索引來得到數據)、
all(對於前面的每一行都通過全表掃描來得到數據)。
possible_keys:表示查詢時,可能使用的索引
key:表示實際使用的索引。
key_len:索引字段的長度。
rows:掃描行的數量。
extra:執行情況的說明和描述。
(4)確定問題並采取相應的優化措施
2.MySQL如何使用索引
