數(shù)據(jù)庫索引&視圖&存儲(chǔ)一
1 索引
1.1 概述:
MySQL官方對索引的定義為:索引( index )是幫助MysSQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)(有序)徽职。
在數(shù)據(jù)之外象颖,數(shù)據(jù)庫系統(tǒng)還維護(hù)者滿足特定查找算法的數(shù)據(jù)結(jié)構(gòu),
這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù)姆钉,這樣就可以在這些數(shù)據(jù)結(jié)構(gòu)上實(shí)現(xiàn)高級(jí)查找算法说订,
這種數(shù)據(jù)結(jié)構(gòu)就是索引。如下面的示意圖所示:
概念圖
左邊是數(shù)據(jù)表,一共有兩列七條記錄,最左邊的是數(shù)據(jù)記錄的物理地址(注意邏輯上相鄰的記錄在磁盤上也并不是一定物理相鄰的)潮瓶。
為了加快Col2的查找,可以維護(hù)一個(gè)右邊所示的二叉查找樹,每個(gè)節(jié)點(diǎn)分別包含索引鍵值和一個(gè)指向?qū)?yīng)數(shù)據(jù)記錄物理地址的指針陶冷,
這樣就可以運(yùn)用二叉查找快速獲取到相應(yīng)數(shù)據(jù)。
一般來說索引本身也很大,不可能全部存儲(chǔ)在內(nèi)存中,因此索引往往以索引文件的形式存儲(chǔ)在磁盤上毯辅。
索引是數(shù)據(jù)庫中用來提高性能的最常用的工具埂伦。
1.2 優(yōu)缺點(diǎn)
優(yōu)勢
1)類似于書籍的目錄索引,提高數(shù)據(jù)檢索的效率,降低數(shù)據(jù)庫的10成本。
2)通過索引列對數(shù)據(jù)進(jìn)行排序思恐,降低數(shù)據(jù)排序的成本沾谜,降低CPU的消耗。
劣勢
1)實(shí)際上索引也是一張表,該表中保存了主鍵與索引字段,并指向?qū)嶓w類的記錄,所以索引列也是要占用空間的胀莹。
2)雖然索引大大提高了查詢效率,同時(shí)卻也降低更新表的速度,如對表進(jìn)行INSERT, UPDATE, DELETE,
因?yàn)楦卤頃r(shí),MysQL不僅要保存數(shù)據(jù),還要保存一下索引文件每次更新添加了索引列的字段,都會(huì)調(diào)整因?yàn)楦滤鶐淼逆I值變化后的索引信息基跑。
1.2 索引結(jié)構(gòu)
索引是在MySQL的存儲(chǔ)引擎層中實(shí)現(xiàn)的,而不是在服務(wù)器層實(shí)現(xiàn)的描焰。
所以每種存儲(chǔ)引擎的索引都不一定完全相同媳否,也不是所有的存儲(chǔ)引擎都支持所有的索引類型的。MySQL目前提供了以下4種索引:
BTREE 索引:最常見的索引類型,大部分索引都支持B樹索引。
HASH 索引:只有Memory引擎支持,使用場景簡單
R-tree索引 (空間索引 ) :空間索引是MyISAM引擎的一個(gè)特殊索引類型,主要用于地理空間數(shù)據(jù)類型,通常使用較少,不做特別介紹逆日。
Full-text (全文索引 ) :全文索引也是MylSAM的一個(gè)特殊索引類型,主要用于全文索引, InnoDB從Mysq15.6版本開始支持全文索引嵌巷。
? MyISAM,InnoDB室抽,Memory三種存儲(chǔ)引擎對各種索引類型的支持
索引 | InnoDB引擎 | MyISAM引擎 | Memory引擎 |
---|---|---|---|
BTREE 索引 | 支持 | 支持 | 支持 |
HASH 索引 | 不支持 | 不支持 | 支持 |
R-tree 空間索引 | 不支持 | 支持 | 不支持 |
Full-text 全文索引 | 5.6版本之后支持 | 支持 | 不支持 |
我們平常所說的索引,如果沒有特別指明,都是指B+樹(多路搜索樹,并不一定是二叉的)結(jié)構(gòu)組織的索引搪哪。
其中聚集索引、復(fù)合索引坪圾、前綴索引晓折、唯一索引默認(rèn)都是使用B+tree樹索引,統(tǒng)稱為索引兽泄。
1.2.1 BTREE 結(jié)構(gòu)
BTree又叫多路平衡搜索樹漓概,一顆m叉的BTree特性如下:
樹中每個(gè)節(jié)點(diǎn)最多包含m個(gè)孩子。
除根節(jié)點(diǎn)與葉子節(jié)點(diǎn)外病梢,每個(gè)節(jié)點(diǎn)至少有[ceil(m/2)個(gè)孩子胃珍。
若根節(jié)點(diǎn)不是葉子節(jié)點(diǎn),則至少有兩個(gè)孩子蜓陌。
所有的葉子節(jié)點(diǎn)都在同一層觅彰。
每個(gè)非葉子節(jié)點(diǎn)由n個(gè)key與n+1個(gè)指針組成,其中[ceil(m/2)-1] <=n <=m-1钮热。
BTREE 樹和二叉樹相比,查詢數(shù)據(jù)的效率更高,因?yàn)閷τ谙嗤臄?shù)據(jù)量來說, BTREE的層級(jí)結(jié)構(gòu)比二叉樹小,因此搜索速度快填抬。
1.2.2 B+TREE 結(jié)構(gòu)
B+Tree為BTree的變種, B+Tree與BTree的區(qū)別為:
1)n叉B+Tree最多含有n個(gè)key ,而BTree最多含有n-1個(gè)key。
2)B+Tree的葉子節(jié)點(diǎn)保存所有的key信息,依key大小順序排列隧期。
3)所有的非葉子節(jié)點(diǎn)都可以看作是key的索引部分飒责。
B+TREE結(jié)構(gòu)
由于B+Tree只有葉子節(jié)點(diǎn)保存key信息,查詢?nèi)魏蝛ey都要從root走到葉子。所以B+Tree的查詢效率更加穩(wěn)定仆潮。
1.2.3 MySQL中的B+TREE 結(jié)構(gòu)
MySq索引數(shù)據(jù)結(jié)構(gòu)對經(jīng)典的B+Tree進(jìn)行了優(yōu)化宏蛉。在原B+Tree的基礎(chǔ)上,增加一個(gè)指向相鄰葉子節(jié)點(diǎn)的鏈表指針鸵闪,就形成了帶有順序指針的B+Tree檐晕,提高區(qū)間訪問的性能。
MySQL中的B+Tree索引結(jié)構(gòu)示意圖:
MySQL中的B+Tree索引結(jié)構(gòu)示意圖
1.3 索引分類
1)單值索引:即一個(gè)索引只包含單個(gè)列,一個(gè)表可以有多個(gè)單列索引蚌讼。
2)唯一索引:索引列的值必須唯一,但允許有空值辟灰。
3)復(fù)否索引:即一個(gè)索引包含多個(gè)列
1.4 索引語法
準(zhǔn)備環(huán)境
# 數(shù)據(jù)庫
create database demo_01 default charset=utf8mb4;
use demo_01;
#表
CREATE TABLE city (
city_id INT (11) NOT NULL AUTO_INCREMENT,
city_name VARCHAR (50) NOT NULL,
country_id INT (11) NOT NULL,
PRIMARY KEY (city_id)
) ENGINE=INNODB DEFAULT CHARSET = utf8;
#表
CREATE TABLE country (
country_id INT (11) NOT NULL AUTO_INCREMENT,
country_name VARCHAR (100) NOT NULL,
PRIMARY KEY (country_id)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
#插入數(shù)據(jù)
INSERT INTO city (city_id, city_name, country_id) VALUES (1, '西安', 1);
INSERT INTO city (city_id, city_name, country_id) VALUES (2, 'NewYork', 2);
INSERT INTO city (city_id, city_name, country_id) VALUES (3, '北京', 1);
INSERT INTO city (city_id, city_name, country_id) VALUES (4, '上海', 1);
INSERT INTO country (country_id, country_name) VALUES (1,'china');
INSERT INTO country (country_id, country_name) VALUES (2,'America');
INSERT INTO country (country_id, country_name) VALUES (3, 'Japan');
INSERT INTO country (country_id, country_name) VALUES (4, 'UK');
1.4.1 創(chuàng)建索引
通用語法
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
[USING index_type]
ON tbl-name(index_col-name, ...)
# 創(chuàng)建 指定索引類型 index 索引名稱 [USING 索引類型(不指定使用類型,默認(rèn)是B+樹索引)on 表名(哪個(gè)字段)
UNIQUE 唯一索引
FULLTEXT 全文索引
SPATIAL 空間索引
create index idx_city_name on city(city_name);
1.4.2 刪除索引
drop index idx_city_name on city;
1.4.3 ALTER 命令
通用語法
alter table 表名 add [primary key | unique | index fulltext ] 索引名稱 (字段列表)
1) alter table tb_name add primary key(column_list);
該語句添加一個(gè)主鍵,這意味著索引值必須是唯一的,且不能為NULL
2) alter table tb_name add unique index_name(column_list);
這條語句創(chuàng)建索引的值必須是唯一的(除了NULL外, NULL可能會(huì)出現(xiàn)多沖)
3) alter table tb_name add index index_name(column_list);
添加普通索引,索引值可以出現(xiàn)多次
4) alter table tb_name add fulltext index_name(column_list);
該語句指定了索引為FULLTEXT,用于全文索引
1.5 索引設(shè)計(jì)原理
索引的設(shè)計(jì)可以遵循一些已有的原則篡石,創(chuàng)建索引的時(shí)候請盡量考慮符合這些原則芥喇,便于提升索引的使用效率,更高效的使用索引。
對查詢頻次較高凰萨,且數(shù)據(jù)量比較大的表建立索引继控。
索引字段的選擇械馆,最佳候選列應(yīng)當(dāng)從where子句的條件中提取,
如果where子句中的組合比較多武通,那么應(yīng)當(dāng)挑選最常用霹崎、過濾效果最好的列的組合。
使用唯一索引冶忱,區(qū)分度越高尾菇,使用索引的效率越高。
索引可以有效的提升查詢數(shù)據(jù)的效率囚枪,但索引數(shù)量不是多多益善派诬,索引越多,維護(hù)索引的代價(jià)自然也就水漲船高链沼。
對于插入默赂、更新、刪除等DML操作比較頻繁的表來說括勺,索引過多缆八,會(huì)引入相當(dāng)高的維護(hù)代價(jià),降低DML操作的效率朝刊,增加相應(yīng)操作的時(shí)間消耗耀里。
另外索引過多的話蜈缤, MysQL也會(huì)犯選擇困難病拾氓,雖然最終仍然會(huì)找到一個(gè)可用的索引,但無疑提高了選擇的代價(jià)底哥。
使用短索引咙鞍,索引創(chuàng)建之后也是使用硬盤來存儲(chǔ)的,因此提升索引訪問的I0效率趾徽,也可以提升總體的訪問效率续滋。
假如構(gòu)成索引的字段總長度比較短,那么在給定大小的存儲(chǔ)塊內(nèi)可以存儲(chǔ)更多的索引值孵奶,相應(yīng)的可以有效的提升MysQL訪問索引的I0效率疲酌。
利用最左前綴,N個(gè)列組合而成的組合索引了袁,那么相當(dāng)于是創(chuàng)建了N個(gè)索引朗恳,
如果查詢時(shí)where子句中使用了組成該索引的前幾個(gè)字段,那么這條查詢SQL可以利用組合索引來提升查詢效率
創(chuàng)建復(fù)合索引:
CREATE INDEX idx_name_email_status oN tb_seller (NAME , email, STATUS);
就相當(dāng)于對name 創(chuàng)建索引;
對name , email 創(chuàng)建了索引;
對name, email, status創(chuàng)建了索引
2 視圖
2.1 概述
視圖(View )是一種虛擬存在的表载绿。視圖并不在數(shù)據(jù)庫中實(shí)際存在粥诫,行和列數(shù)據(jù)來自定義視圖的查詢中使用的表,并且是在使用視圖時(shí)動(dòng)態(tài)生成的崭庸。通俗的講,視圖就是一條SELECT語句執(zhí)行后返回的結(jié)果集怀浆。所以我們在創(chuàng)建視圖的時(shí)候谊囚,主要的工作就落在創(chuàng)建這條SQL查詢語句上。
視圖相對于普通的表的優(yōu)勢主要包括以下幾項(xiàng)执赡。
簡單:使用視圖的用戶完全不需要關(guān)心后面對應(yīng)的表的結(jié)構(gòu)镰踏、關(guān)聯(lián)條件和篩選條件,對用戶來說已經(jīng)是過濾好的復(fù)合條件的結(jié)果集沙合。
安全:使用視圖的用戶只能訪問他們被允許查詢的結(jié)果集余境,對表的權(quán)限管理并不能限制到某個(gè)行某個(gè)列,但是通過視圖就可以簡單的實(shí)現(xiàn)灌诅。
數(shù)據(jù)獨(dú)立:一旦視圖的結(jié)構(gòu)確定了芳来,可以屏蔽表結(jié)構(gòu)變化對用戶的影響,源表增加列對視圖沒有影響猜拾;源表修改列名即舌,則可以通過修改視圖來解決,不會(huì)造成對訪問者的影響挎袜。
2.2 創(chuàng)建或修改視圖
創(chuàng)建視圖:
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
解讀:create view 視圖名稱 as 查詢SQL語句 ;
創(chuàng)建視圖成功后就可以通過視圖查看表數(shù)據(jù)顽聂,同時(shí)也可以通過視圖更新表數(shù)據(jù)
修改視圖:
ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS select statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
WITH [CASCADED | LOCAL] CHECK OPTION 決定了是否允許更新數(shù)據(jù)使記錄不再滿足視圖的條件。
LOCAL :只要滿足本視圖的條件就可以更新盯仪。
CASCADED :必須滿足所有針對該視圖的所有視圖的條件才可以更新紊搪。
2.3 查看或刪除視圖
查看視圖
從MySQL5.1版本開始,使用SHOW TABLES 命令的時(shí)候不僅顯示表的名字,同時(shí)也會(huì)顯示視圖的名字全景,而不存在單獨(dú)顯示視圖的 SHOW VIEWS 命令耀石。
使用SHOW TABLE STATUS 命令的時(shí)候,不但可以顯示表的信息,同時(shí)也可以顯示視圖的信息爸黄。
如果需要查詢某個(gè)視圖的定義滞伟,可以使用SHOW CREATE VIEW 命令進(jìn)行查看
刪除視圖
DROP VIEW [IF EXISTS] view_name [view_name] ...[RESTRICT | CASCADE]
示例: drop view 視圖名稱 ;
3 存儲(chǔ)過程和函數(shù)
3.1 概述
存儲(chǔ)過程和函數(shù)是事先經(jīng)過編譯并存儲(chǔ)在數(shù)據(jù)庫中的一段SQL語句的集合,
調(diào)用存儲(chǔ)過程和函數(shù)可以簡化應(yīng)用開發(fā)人員的很多工作炕贵,
減少數(shù)據(jù)在數(shù)據(jù)庫和應(yīng)用服務(wù)器之間的傳輸梆奈,對于提高數(shù)據(jù)處理的效率是有好處的。
存儲(chǔ)過程和函數(shù)的區(qū)別在于函數(shù)必須有返回值称开,而存儲(chǔ)過程沒有亩钟。
函數(shù):是一個(gè)有返回值的過程;
過程:是一個(gè)沒有返回值的函數(shù);
3.2 創(chuàng)建存儲(chǔ)過程
CREATE PROCEDURE procedure_name ([proc-parameter [....])
begin
SQL語句
end;
示例:
知識(shí)小貼士
DELIMITER
該關(guān)鍵字用來聲明SQL語句的分隔符,告訴MySQL解釋器,該段命令是否已經(jīng)結(jié)束了, mysq是否可以執(zhí)行了鳖轰。
默認(rèn)情況下, delimiter是分號(hào)清酥。在命令行客戶端中,如果有一行命令以分號(hào)結(jié)束,那么回車后, mysa將會(huì)執(zhí)行該命令。
3.3 調(diào)用或查看存儲(chǔ)過程
調(diào)用:
call procedure_name ;
查看:
# 查詢數(shù)據(jù)庫中的所有的存儲(chǔ)過程
select name from mysql.proc where db='數(shù)據(jù)庫名稱';
# 查詢存儲(chǔ)過程的狀態(tài)信息
show procedure status;
show procedure status \G;
# 查詢某個(gè)存儲(chǔ)過程的定義
show create procedure 存儲(chǔ)的名稱 \G;
刪除:
drop procedure [IF EXISTS] SP_name;
3.4 語法
3.4.1 變量
DECIARE
通過 DECLARE 可以定義一個(gè)局部變量,該變量的作用范圍只能在 BEGIN..ND 塊中脆霎。
DECLARE var_name[....] type [DEFAULT value]
#示例
create procedure pro_test2()
begin
declare num int default 5;
select num+ 10;
end;
set
直接賦值使用set总处,可以賦常量或者賦表達(dá)式,具體語法如下:
SET var_name = expr [var_name = expr] ...
#示例
CREATE PROCEDURE pro_test3()
BEGIN
DECLARE NAME VARCHAR (20);
SET NAME = 'MYSQL';
SELECT NAME
END;
也可以通過select ...into 方式進(jìn)行賦值
CREATE PROCEDURE pro_test4()
BEGIN
declare countnum int;
select count(*) into countnum from city;
select countnum;
END;
3.4.2 if條件判斷
語法結(jié)構(gòu)
if search_condition then statement_list
[elseif search_condition then statement_list] ...
[else statement_1ist]
end if;
3.4.3 傳遞參數(shù)
create procedure procedure_name ([in/out/inout] 參數(shù)名 參教類型)
IN: 該參數(shù)可以作為輸入睛蛛,也就是需要調(diào)用方傳入值鹦马,默認(rèn)值
OUT: 該參數(shù)作為輸出胧谈,也就是該參數(shù)可以作為返回值
INOUT:既可以作為輸入?yún)?shù),也可以作為輸出參數(shù)
3.4.4 case結(jié)構(gòu)
方式一:
CASE case_value
WHEN when_value THEN statement_list
[WHEN when-value THEN statement_list] ..
[ELSE statement_list]
END CASE;
方式二:
CASE
WHEN Search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ..
[ELSE statement_list]
END CASE;
3.4.5 while循環(huán)
待補(bǔ)充
3.4.6 repeat結(jié)構(gòu)
待補(bǔ)充
3.4.7 loop語句
待補(bǔ)充
3.4.8 leave語句
待補(bǔ)充
3.4.9 游標(biāo)/光標(biāo)
待補(bǔ)充
3.5 存儲(chǔ)函數(shù)
待補(bǔ)充
4 觸發(fā)器
4.1 介紹
觸發(fā)器是與表有關(guān)的數(shù)據(jù)車對象荸频,指在insert/update/delete之前或之后菱肖,觸發(fā)并執(zhí)行觸發(fā)器中定義的SQL語句集合。
觸發(fā)器的這種特性可以協(xié)助應(yīng)用在數(shù)據(jù)庫端確保數(shù)據(jù)的完整性旭从,日志記錄稳强,數(shù)據(jù)校驗(yàn)等操作。
使用別名 OLD 和 NEW 來引用觸發(fā)器中發(fā)生變化的記錄內(nèi)容和悦,這與其他的數(shù)據(jù)庫是相似的退疫。
現(xiàn)在觸發(fā)器還只支持行級(jí)觸發(fā),不支持語句級(jí)觸發(fā)。
觸發(fā)器類型 | NEW和OLD的使用 |
---|---|
INSERT型觸發(fā)器 | NEW表示將要或者已經(jīng)新增的數(shù)據(jù) |
UPDATE型觸發(fā)器 | OLD表示修改之前的數(shù)據(jù), NEW表示將要或已經(jīng)修改后的數(shù)據(jù) |
DELETE型觸發(fā)器 | OLD表示將要或者已經(jīng)刪除的數(shù)據(jù) |
4.2 創(chuàng)建觸發(fā)器
語法結(jié)構(gòu)
create trigger trigger_name
before/after insert/update/delete
on tbl_name
[ for each row ]--行級(jí)觸發(fā)器
begin
trigger_stmt;
end;
4.3 刪除觸發(fā)器
語法結(jié)構(gòu):
drop trigger [schema_name]trigger_name
如果沒有指定schema_name鸽素,默認(rèn)為當(dāng)前數(shù)據(jù)庫褒繁。
4.4 查看觸發(fā)器
可以通過執(zhí)行 SHOW TRIGGERS 命令查看觸發(fā)器的狀態(tài)、語法等信息馍忽。
語法結(jié)構(gòu)
show triggers ;