輕鬆理解HTTP快取策略
一、檢視
檢視是一個虛擬表,是sql的查詢結果,其內容由查詢定義。同真實的表一樣,檢視包含一系列帶有名稱的列和行資料,在使用檢視時動態生成。檢視的資料變化會影響到基表,基表的資料變化也會影響到檢視[insert update delete ]
--建立檢視 create view view_name as select * from table_name; --顯示建立檢視 show create view view_name; --顯示檢視的欄位 desc view_name; --查詢檢視資料 select * from view_name; --顯示檢視 show tables; --修改檢視 alter view view_name as select * from table_name; --刪除檢視 drop view view_name;
二、觸發器
觸發器是與表有關的資料庫物件,在滿足定義條件時觸發,並執行觸發器中定義的語句集合。觸發器的這種特性可以協助應用在資料庫端確保資料的完整性。
--建立觸發器 create trigger trigger_name trigger_time trigger_event on table_name for each row begin 執行語句1; 執行語句2; end --刪除觸發器 drop triggertrigger_name;
- trigger_time:觸發時機,before/after,在trigger_event之前/之後觸發
- trigger_event:觸發事件,insert/update/delete,在插入/修改/刪除時觸發
- for each row:每一次滿足觸發器的操作
- new/old:new指新資料,insert/update會產生新資料;old指老資料,update/delete會產生老資料
三、函式
MySQL提供許多內建函式,也可以自定義函式;官方內建函式地址https://dev.mysql.com/doc/refman/5.7/en/functions.html
--呼叫函式select 函式名(引數);
1.常用內建函式
函式名稱 | 介紹 | 示例 |
char_length(str) | 返回字串的長度,單位是字元 | select char_length('abcde');返回5 select char_length('中文');返回2 |
length(str) | 返回字串的長度,單位是位元組 | select length('abcde');返回5 select length('中文');返回4 |
concat(str1,str2,...) | 字串拼接,返回拼接之後的字串;若有任何一個引數為null,則返回結果為null | select concat_ws('a','','b',null,'c');返回null |
congcat_ws(separator,str1,str2,...) | 字串拼接,自定義連線符,返回拼接之後的字串;不會忽略任何的空字串,但是會忽略null | select concat_ws(',','a','','b',null,'c');返回a,,b,c |
ascii(str) | 返回第一個字元的ascii碼;如果str是空字串,返回0。如果str是NULL,返回NULL | select ascii('ab');返回97 |
lower(str)/upper(str) | 返回字串的小寫/大寫 | |
instr(str,substr) | 返回子串substr在字串str中第一次出現的位置;如果字串中不包含子串,返回0 | select instr('foobarbar','bar');返回4 select instr('foobarbar','br');返回0 |
left(str,len)/right(str,len) | 返回字串左邊/右邊len長度的字串 | select left('qwerty',2);返回qw |
substring(str,pos,len) | 返回從pos位置開始的長度為len的字串;不寫len,返回pos位置開始到結尾的字串 | select substring('abcdefg',2,4);返回bcde |
trim(str)/ltrim(str)/rtrim(str) | 返回刪除str首尾/首/尾空格的字串 | |
replace(str,from_str,to_str) | 返回字串str,其字串from_str的所有出現由字串to_str代替 | select replace('www.mysql.com','w','ab');返回ababab.mysql.com |
repeat(str,count) | 返回由重複count次的字串str組成的一個字串。如果count <= 0,返回一個空字串。如果str或count是NULL,返回NULL | |
reverse(str) | 返回顛倒字元順序的字串str | |
insert(str,pos,len,newstr) | 返回字串str,在位置pos起始的子串且len個字元長的子串由字串newstr代替 | select insert('abcdefg',3,2,'ooo');返回aboooefg |
abs(x) | 返回x的絕對值 | |
mod(m,n)/%: | 返回m被n除的餘數 | select mod(5,2);返回1select 5%4;返回1 |
ceiling(x) | 返回不小於x的最小整數值 | select ceiling(-2.33);返回-2 |
round(x) | 返回引數x的四捨五入的一個整數 | select format(12345678.11,4); 返回12,345,678.1100 |
format(x,d) | 將x保留小數位d位 | |
now() | 返回現在的日期和時間 | select now();返回2020-12-15 22:54:12 |
curdate() | 返回現在的日期 | select curdate(); 返回2020-12-15 |
curtime() | 返回現在的時間 | select curtime();返回22:54:28 |
year(date)/month(date)/day(date) | 返回日期的年/月/日 | select year(curdate());返回2020 |
weekday(date) | 返回date的星期索引(0=星期一,1=星期二, ……6= 星期天) | |
hour(time)/minute(time)/second(time) | 返回時間的時/分/秒 | select hour('18:18:18');返回18 |
dayofweek(date)/dayofmonth(date)/dayofyear(date) | 返回日期date的星期索引(1=星期天,2=星期一, …7=星期六)/返回date的月份中的日期,在1到31範圍內/返回date在一年中的日數, 在1到366範圍內 | |
date_format(date,format) | 返回格式化時間 | select date_format(now(),'%Y-%m %H:%i');返回2020-12 17:14 |
if(expr1,expr2,expr3) | 如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),則返回值為expr2; 否則返回值則為 expr3。IF() 的返回值為數字值或字串值,具體情況視其所在語境而定 | |
ifnull(value1,value2) | 如果value1為空,返回value2,否則返回value1 | |
last_insert_id() | 返回最後生成的AUTO_INCREMENT值 | |
strcmp(str1,str2) | 如果字串相同,STRCMP()返回0,如果第一引數根據當前的排序次序小於第二個,返回-1,否則返回1 | |
charset(str) | 函式返回字串str的字符集,一般情況這個字符集就是系統的預設字符集 | select charset('abc');返回gbk |
collatiion(str) | 返回字串str的字元排列方式 | select collation('abc');返回gbk_chinese_ci |
version(); | 返回MySQL的版本 | |
connection_id() | 返回伺服器的連線數,也就是到現在為止MySQL服務的連線次數 | |
database()/schema() | 返回當前資料庫名 | |
user()/current_user()/system_user()/session_user() | 返回當前使用者名稱 |
2.自定義函式
--自定義函式,自定義函式的函式體內不能包括select語句之類 create function 函式名(引數名 引數型別) --多個引數之間用,隔開 returns 返回型別 begin 函式體 end --刪除函式 drop function 函式名;
- log_bin_trust_function_creators:當二進位制日誌啟用後,這個變數就會啟用。它控制是否可以信任儲存函式建立者,不會建立寫入二進位制日誌引起不安全事件的儲存函式。如果設定為0(預設值),使用者不得建立或修改儲存函式,除非它們具有除CREATE ROUTINE或ALTER ROUTINE特權之外的SUPER許可權。 設定為0還強制使用DETERMINISTIC特性或READS SQL DATA或NO SQL特性宣告函式的限制。 如果變數設定為1,MySQL不會對建立儲存函式實施這些限制。 此變數也適用於觸發器的建立。
四、變數
- @變數名:是使用者變數
- @@變數名:是會話變數或全域性變數
--設定使用者變數 set @變數名 = values; select @變數名 := values; --查詢變數 show session variables; --查詢所有會話變數 show global variables; --查詢所有全域性變數 show variables like '%部分變數名%'; --查詢變數 select @變數名; --查詢使用者變數; select @@session.變數名; --查詢會話變數 select @@global.變數名; --查詢全域性變數 --設定變數 set session 變數名=value; --設定會話變數 set @@session.變數名=value; --設定會話變數 set global 變數名=value; --設定全域性變數 set @@global.變數名=value; --設定全域性變數
五、儲存過程
儲存過程是一個SQL語句集合,當主動去呼叫儲存過程時,其中內部的SQL語句會按照邏輯執行。
--建立儲存過程 create procedure 儲存過程名稱() begin SQL語句; end --建立有引數的儲存過程 create procedure 儲存過程名稱( in 引數名稱 引數型別, inout 引數名稱 引數型別, out 引數名稱 引數型別) begin SQL語句; end --呼叫儲存過程 call 儲存過程名稱(引數); --刪除儲存過程 drop procedure 儲存過程名稱;
1.無引數的儲存過程
2.有引數的儲存過程
3.儲存過程條件語句
if(條件) then ...; elseif(條件) then ...; else ...; end if;
4.儲存過程迴圈語句
4.1while迴圈
while(條件) do ...; end while;
4.2 repeat迴圈
repeat ...; until 條件 end repeat;
4.3 loop迴圈
loopname:loop ...; if(條件) then leave loopname; end if; end loop;
5.儲存過程使用遊標
遊標是儲存查詢結果的臨時區域
delimiter || create procedure p13() begin declare sid int; declare sname char(10); declare cid int; declare flag int default true; --cursor和handler變數必須在普通變數的後面 declare cur cursor for select * from student; --遊標變數儲存了查詢的臨時結果,就是結果集 --將遊標變數中的結果集都遍歷一遍,到達結尾,將flag設為false declare continue handler for not found set flag=false; open cur; --開啟遊標 fetch cur into sid,sname,cid; --遊標向前走一步,將結果放到變數中 while(flag) do --遊標還沒到達結尾就繼續迴圈 begin insert into t1 values(sid,sname,cid); fetch cur into sid,sname,cid; --每次循環遊標向前走一步,當結尾continue為not found設定flag為false,結束迴圈 end; end while; close cur; --關閉遊標 end||
6.儲存過程中的事務
6.1 事務
事務的特徵
- 在 MySQL 中只有使用了 Innodb 資料庫引擎的資料庫或表才支援事務。
- 事務處理可以用來維護資料庫的完整性,保證成批的 SQL 語句要麼全部執行,要麼全部不執行。
- 事務用來管理 insert,update,delete 語句
一般來說,事務是必須滿足4個條件(ACID)::原子性(Atomicity,或稱不可分割性)、一致性(Consistency)、隔離性(Isolation,又稱獨立性)、永續性(Durability)。
--開啟事務 start transaction; SQL語句; --提交 commit; --回滾 rollback;
6.2儲存過程中的事務
delimiter || create procedure p15(out p_return_code tinyint) begin declare exit handler for sqlexception --不能加;會報語法錯誤 begin --error set p_return_code =1; rollback; end; declare exit handler for sqlwarning begin --warning set p_return_code=2; rollback; end; start transaction; delete from t1; delete from t100; --沒有t100這個表 commit; --sucess set p_return_code=0; end|| delimiter ;
7.動態執行儲存過程
8.python執行儲存過程
import pymysql connect = pymysql.connect("localhost","root","","db1") cursor = connect.cursor() # cursor.callproc("p1") #執行沒有引數的儲存過程 cursor.callproc("p7", args=(1,1,1)) #執行有引數的儲存過程 cursor.execute("select @_p7_0,@_p7_1,@_p7_2") #獲取儲存過程的第0,1,2個引數,返回元組裡套元組 result = cursor.fetchall() cursor.close() connect.close() print(result)
六、索引
索引,是資料庫中專門用於幫助使用者快速查詢資料的一種資料結構。類似於字典中的目錄,查詢字典內容時可以根據目錄查詢到資料的存放位置,然後直接獲取即可。
索引大大提高了查詢速度,但同時會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要儲存資料,還要儲存一下索引檔案。建立索引會佔用磁碟空間的索引檔案。
索引分為普通索引、唯一索引、主鍵索引、唯一索引
1.普通索引
普通索引的作用,就是加速查詢
--建立普通索引 --建立表時,建立索引 create table tablename( field type ..., ..., index indexname(field) ); --表已經存在建立索引
--注意:對於建立索引時如果是BLOB和TEXT型別,必須指定length。
create index indexname on tablename(field([length]))
--修改表結構增加索引
alter table tablename add index indexname(field);
--刪除索引
drop index indexname on tablename;
alter table tablename drop index indexname;
--顯示索引 show index from table_name;
python造資料
import pymysql import random connect = pymysql.connect("localhost","root","","db1") cursor = connect.cursor() #如果表已經存在,刪除 sql_d = "drop table if exists staff;" cursor.execute(sql_d) connect.commit() #建立staff表 sql_c = """create table staff( id int unsigned not null auto_increment primary key, name char(10) not null, email char(20), department_id tinyint unsigned )engine=innodb default charset=utf8;""" cursor.execute(sql_c) connect.commit() #插入資料 sql_i = "insert into staff(id,name,email,department_id) values(%s,%s,%s,%s);" for i in range(1,1000000): #因為id是unsigned,不能為0 id = i name = "Lucy" + str(i) email = name +"@qq.com" department_id = random.randint(1,9) cursor.execute(sql_i,(id,name,email,department_id)) connect.commit() cursor.close() connect.close()
2.唯一索引
--建立唯一索引 --建立表時建立唯一索引 create table tablename( ..., unique uniquename (field) ); --表已存在時建立唯一索引 create unique index indexname on tablename(field); --刪除唯一索引 drop index indexname on tablename;
3.組合索引
組合索引是將n個列組合成一個索引,其應用場景為:頻繁的同時使用n列來進行查詢
--建立組合索引 create index indexname on table(field1,field2);
如建立name和email的組合索引之後,查詢:
- name and email -- 使用索引
- name -- 使用索引
- email -- 不使用索引
注意:對於同時搜尋n個條件時,組合索引的效能好於多個單一索引合併。
4.命中索引
正確使用索引才能加快查詢速度,以下方式會降低查詢速度
- 使用like '%...%'
- 使用函式
- 使用or ,當or中有未設定索引的列會降低查詢速度
- 型別不一致,如果name的型別是char,但是查詢時寫name=999,會降低查詢速度
- !=,如果是主鍵還是會走索引
- >,如果是主鍵或者索引是整數型別還是會走索引
- order by,當排序使用索引,但是對映不是索引時,會降低查詢速度,如果是主鍵還是走索引
5.執行計劃
可通過執行計劃推測查詢語句的時間
explain SQL語句;
select_type列常見的有:
- simple:表示不需要union操作或者不包含子查詢的簡單select查詢。有連線查詢時,外層的查詢為simple,且只有一個
- primary:一個需要union操作或者含有子查詢的select,位於最外層的單位查詢的select_type即為primary。且只有一個
- union:union連線的兩個select查詢,第一個查詢是dervied派生表,除了第一個表外,第二個以後的表select_type都是union
- dependent union:與union一樣,出現在union 或union all語句中,但是這個查詢要受到外部查詢的影響
- union result:包含union的結果集,在union和union all語句中,因為它不需要參與查詢,所以id欄位為null
- subquery:除了from字句中包含的子查詢外,其他地方出現的子查詢都可能是subquery
- dependent subquery:與dependent union類似,表示這個subquery的查詢要受到外部表查詢的影響
- derived:from字句中出現的子查詢,也叫做派生表,其他資料庫中可能叫做內聯檢視或巢狀select
- system:表中只有一行資料或者是空表,且只能用於myisam和memory表。如果是Innodb引擎表,type列在這個情況通常都是all或者index
- const:使用唯一索引或者主鍵,返回記錄一定是1行記錄的等值where條件時,通常type是const。其他資料庫也叫做唯一索引掃描
- eq_ref:出現在要連線過個表的查詢計劃中,驅動表只返回一行資料,且這行資料是第二個表的主鍵或者唯一索引,且必須為not null,唯一索引和主鍵是多列時,只有所有的列都用作比較時才會出現eq_ref
- ref:不像eq_ref那樣要求連線順序,也沒有主鍵和唯一索引的要求,只要使用相等條件檢索時就可能出現,常見與輔助索引的等值查詢。或者多列主鍵、唯一索引中,使用第一個列之外的列作為等值查詢也會出現,總之,返回資料不唯一的等值查詢就可能出現。
- fulltext:全文索引檢索,要注意,全文索引的優先順序很高,若全文索引和普通索引同時存在時,mysql不管代價,優先選擇使用全文索引
- ref_or_null:與ref方法類似,只是增加了null值的比較。實際用的不多。
- unique_subquery:用於where中的in形式子查詢,子查詢返回不重複值唯一值
- index_subquery:用於in形式子查詢使用到了輔助索引或者in常數列表,子查詢可能返回重複值,可以使用索引將子查詢去重。
- range:索引範圍掃描,常見於使用>,<,is null,between ,in ,like等運算子的查詢中。
- index_merge:表示查詢使用了兩個以上的索引,最後取交集或者並集,常見and ,or的條件使用了不同的索引
- index:索引全表掃描
- all:全表掃描資料檔案