資料庫中的檢視,事物,索引一些介紹及使用
檢視
檢視是一種基於查詢結果產生的虛擬表。
為什麼要有檢視?
當在執行查詢操作時,經常會出現查詢頻率高並且查詢語句非常複雜的情況。 每次都要將複雜的SQL語句重新書寫,非常不便。
比如:顯示每種商品的名字以及對應的商品型別名和品牌名
select goods.name,goods_cates.name,goods_brands.name from goods inner join goods_cates on goods.cate_id = goods_cates.id inner join goods_brands on goods.brand_id = goods_brands.id;
上面的功能實際很簡單,但是書寫起來很頭疼,如果每天還要執行很多次。頭大。。。
如果能將這個查詢的結果儲存下來,下次在使用時,直接使用結果就非常完美了。
這個需求通過檢視就可以完成。
檢視的特性
- 檢視是一個虛擬表,實際它就是一條被封裝起來的 SQL 查詢語句。
- 在使用檢視時,就相當執行了被封裝的複雜SQL查詢語句。
- 檢視不儲存具體的資料。
- 檢視的基本表發生變化,那麼檢視也隨之變化
定義檢視
檢視在定義時,建議檢視名稱以 v_xxx 形式命名,以便和普通的表區分。 語法:create view 檢視名稱 as select語句;
create view v_goods_info as select goods.name as gname,goods_cates.name as gcname,goods_brands.name as gbname from goods inner join goods_cates on goods.cate_id = goods_cates.id inner join goods_brands on goods.brand_id = goods_brands.id;
檢視檢視
檢視以表的形式體現,通過 show tables
即可檢視檢視。
使用檢視
檢視的作用就是用來查詢,檢視的作用類似將子查詢做了封裝。
select * from v_goods_info;
刪除檢視
語法: drop view 檢視名稱
drop view v_goods_info;
檢視小結
* 檢視封裝了對多張基本表的複雜操作,簡化使用者操作
* 檢視只是一個虛表,並不儲存任何基本表的表資料,當用戶使用檢視的時候 檢視會從基本表中取出
* 通過檢視可以對使用者展示指定欄位從而遮蔽其他欄位資料,更加安全
事務
事務Transaction,是指作為一個基本工作單元執行的一系列SQL語句的操作,要麼完全地執行,要麼完全地都不執行。
為什麼要有事務?
以下內容出自《高效能MySQL》第三版,瞭解事務的ACID有助於我們更好的理解事務運作。 下面舉一個銀行應用是解釋事務必要性的一個經典例子。假如一個銀行的資料庫有兩張表:支票表(checking)和儲蓄表(savings)。現在要從使用者Jane的支票賬戶轉移200美元到她的儲蓄賬戶,那麼至少需要三個步驟:
> 1. 檢查支票賬戶的餘額高於或者等於200美元。
> 2. 從支票賬戶餘額中減去200美元。
> 3. 在儲蓄帳戶餘額中增加200美元。
上述三個步驟的操作必須打包在一個事務中,任何一個步驟失敗,則必須回滾所有的步驟。
可以用START TRANSACTION語句開始一個事務,然後要麼使用COMMIT提交將修改的資料持久儲存,要麼使用ROLLBACK撤銷所有的修改。事務SQL的樣本如下:
> 1. start transaction;
> 2. select balance from checking where customer_id = 10233276;
> 3. update checking set balance = balance - 200.00 where customer_id = 10233276;
> 4. update savings set balance = balance + 200.00 where customer_id = 10233276;
> 5. commit;
事務的四大特性 ACID
1. 原子性(Atomicity)
>一個事務必須被視為一個不可分割的最小工作單元,整個事務中的所有操作要麼全部提交成功,要麼全部失敗回滾,對於一個事務來說,不可能只執行其中的一部分操作,這就是事務的原子性
2. 一致性(Consistency)
>資料庫總是從一個一致性的狀態轉換到另一個一致性的狀態。(在前面的例子中,一致性確保了,即使在執行第三、四條語句之間時系統崩潰,支票賬戶中也不會損失200美元,因為事務最終沒有提交,所以事務中所做的修改也不會儲存到資料庫中。)
3. 隔離性(Isolation)
>通常來說,一個事務所做的修改在最終提交以前,對其他事務是不可見的。(在前面的例子中,當執行完第三條語句、第四條語句還未開始時,此時有另外的一個賬戶彙總程式開始執行,則其看到支票帳戶的餘額並沒有被減去200美元。)
4. 永續性(Durability)
>一旦事務提交,則其所做的修改會永久儲存到資料庫。(此時即使系統崩潰,修改的資料也不會丟失。)
事務操作
MySQL使用的InnoDB引擎支援事務操作。
+ 開啟事務
開啟事務後執行修改命令,變更會維護到本地快取中,而不維護到物理表中
`begin;`
或
`start transaction;`
+ 提交事務
將快取中的資料變更維護到物理表中
`commit;`
+ 回滾事務
放棄快取中變更的資料 表示事務執行失敗 應該回到開始事務前的狀態
`rollback;`
驗證事務提交
為了檢視效果,需要開啟兩個終端視窗,使用同一個資料庫,操作同一張表。
step 1:
兩個終端同時連線同一個資料庫並查詢同一張表
`select * from goods_cates;`
step 2:
終端1開啟事務,插入資料,檢視
```sql
begin;
insert into goods_cates(name) values('手機')
select * from goods_cates; -- 插入的資料顯示插入成功了
```
setp 3:
終端2查詢資料
```sql
select * from goods_cates; -- 並沒有看到新資料,因為終端1的操作快取在本地,還沒有提交。隔離性
```
step 4:
終端1提交資料,並查詢
```sql
commit; -- 提交後,事務完成,原子性操作結束
select * from goods_cates;
```
step 5:
終端2查詢
```sql
select * from goods_cates; -- 可以查到新資料,一致性,永續性。
```
驗證事務回滾
為了檢視效果,需要開啟兩個終端視窗,使用同一個資料庫,操作同一張表。
step 1:
兩個終端同時連線同一個資料庫並查詢同一張表
`select * from goods_cates;`
step 2:
終端1開啟事務,刪除所有資料,檢視
```sql
begin;
insert into goods_cates(name) values('HIFI播放器');
select * from goods_cates; -- 插入的資料顯示插入成功了
```
setp 3:
終端2查詢資料
```sql
select * from goods_cates; -- 並沒有看到新資料,因為終端1的操作快取在本地,還沒有提交。隔離性
```
step 4:
終端1因為各種原因不想或不能提交資料,取消之前的操作
```sql
rollback;
```
step 5:
終端2查詢
```sql
select * from goods_cates; -- 沒有查到新資料,一致性,永續性。
```
事務小結
事務的存在是解決資料在操作過程中的 ACID 問題。
索引
什麼是索引?
能夠快速查詢資料的線索就稱之為索引。
為什麼需要索引?
思考: 如何在一個圖書館中找到一本書的?
在圖書館中如果沒有其他輔助手段只能一條道走到黑,一本書->一本書的掃。 終於經過1個小時的連續掃描發現你需要看的那本書在一分鐘之前被人借走了。這種就是順序查詢。 圖書館管理員發現這個問題,於是決定減少這樣的(>﹏<)悲劇故事。 為同學們購置了一套圖書館管理系統。 大家要找書籍先在系統上查詢到書籍所在的房屋編號和貨架編號,然後就可以直接大搖大擺的去取書了。 這個房屋編號和貨架編號就是索引。
索引目的
索引的目的在於提高查詢效率。
索引原理
除了詞典,生活中隨處可見索引的例子,如火車站的車次表、圖書的目錄等,它們的原理都是一樣的。 通過不斷的縮小想要獲得資料的範圍來篩選出最終想要的結果。
索引的使用
+ 查看錶中已有索引
`show index from 表名`
+ 建立索引
`create index 索引名稱 on 表名(欄位名稱(長度))`
- 如果指定欄位是字串,需要指定長度,建議長度與定義欄位時的長度一致
- 欄位型別如果不是字串,可以不填寫長度部分
+ 刪除索引:
`drop index 索引名稱 on 表名;`
驗證索引的效率
+ 建立一個新表(不帶索引)
```sql
create table test_index(title varchar(10));
```
+ 準備10萬條資料
```python
from pymysql import connect
def main():
# 建立Connection連線
conn = connect(host='localhost',port=3306,database='jddb',user='root',password='123123',charset='utf8')
# 獲得Cursor物件
cursor = conn.cursor()
# 插入10萬次資料
for i in range(100000):
cursor.execute("insert into test_index values('ha-%d')" % i)
# 提交資料
conn.commit()
if __name__ == "__main__":
main()
```
+ 查詢驗證
- 開啟執行時間監測
`set profiling=1;`
- 查詢 ha-99999 的資料
`select * from test_index where title='ha-99999;`
- 為表 test_index 建立索引
`create index title_index on test_index(title(10));`
- 再次查詢 ha-99999 的資料
`select * from test_index where title='ha-99999;`
- 檢視執行時間
`show profiles;`
<img src='images/118.png'>
- 使用 desc 命令也可以檢視索引的效率
` desc select * from test_index where title='ha-99999';`
<img src='images/119.png'>
索引小結:
1. 索引可以明顯提高某些欄位的查詢效率。
1. 但不是所有的表都需要建立索引
1. 如果表中資料很少,沒有必要建立索引
1. 如果一個表中的資料增刪很頻繁,不能建立索引 ,因為只要資料發生增減,索引就要重新建立。增加了系統開銷,反而慢了。
1. 索引只適合查詢操作頻繁的表。