1. 程式人生 > 實用技巧 >輕鬆理解HTTP快取策略

輕鬆理解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 trigger
trigger_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
table:顯示的查詢表名,如果查詢使用了別名,那麼這裡顯示的是別名,如果不涉及對資料表的操作,那麼這顯示為null,如果顯示為尖括號括起來的<derived N>就表示這個是臨時表,後邊的N就是執行計劃中的id,表示結果來自於這個查詢產生。 type:依次從好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一個索引
  • 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:全表掃描資料檔案
possible_keys:查詢可能使用到的索引都會在這裡列出來 key:查詢真正使用到的索引 key_len:用於處理查詢的索引長度 ref:如果是使用的常數等值查詢,這裡會顯示const,如果是連線查詢,被驅動表的執行計劃這裡會顯示驅動表的關聯欄位,如果是條件使用了表示式或者函式,或者條件列發生了內部隱式轉換,這裡可能顯示為func rows:這裡是執行計劃中估算的掃描行數,不是精確值