你都是會點啥技術(四)--- 數據庫

你都是會點啥技術(四)— 數據庫

寫在前面的話:還記得2018年的時候開發的項目上線,經過大概一個月,因爲數據量增加,造成項目查詢頁面的延遲,因爲項目使用的羣體是固定的,所以當時提出來後並沒有着力解決,不過我一直對數據庫優化這塊耿耿於懷,抽出時間來基於MYSQL學習一下!

1.概念知識補充

數據庫系統圖:
在這裏插入圖片描述

2.查詢優化技術分類

(1.)查詢重用:①查詢結果重用;②查詢計劃重用。
(2.)查詢重寫規則:①基於關係型代數;②視圖重寫、子查詢優化、等價位置重寫、條件化簡、外聯接消除、聯接消除、嵌套聯接消除;③語義優化。
(3.)查詢優化算法(基於代價估算模型):①單表掃描算法(全表掃描、索引掃描、行定位掃描);②兩表連接算法(嵌套聯接算法、歸併連接算法、哈希連接算法);③多表連接算法(貪婪)。
(4.)並行查詢優化:利用分解查詢SQL,進行並行計算查詢,提高查詢目的。
(5.)分佈式查詢優化:利用分佈式系統優化查詢。

3.數據庫調優

數據庫調優包括數據庫管理系統優化和查詢優化,主要目的是使數據庫有更高的吞吐量和更高的響應時間。
在這裏插入圖片描述

4.差不多了,實際應用開始走起!

第一招explain

顯示了mysql如何使用索引來處理語句以及連接表。可以幫助選擇更好的索引和寫出更優化的查詢語句!我們以select語句爲例子
詳情請參考:https://www.cnblogs.com/yycc/p/7338894.html
在這裏插入圖片描述

第二招子查詢優化
1.子查詢合併:

原理:把多次表掃描、多次連接減少爲低次表掃描和低次連接。

/*
*優化前
*/
 SELECT * FROM t_user WHERE zhuhuid < 20 AND (
 EXISTS (SELECT id FROM t_zhuhu WHERE id<15 AND id=5) OR
 EXISTS (SELECT id FROM t_zhuhu WHERE id<15 AND id=10));
/*
*優化後
*/
 SELECT * FROM t_user WHERE zhuhuid < 20 AND (
 EXISTS (SELECT id FROM t_zhuhu WHERE id<15 AND id=5 OR id=10))

2.子查詢展開:

原理:將子查詢上拉到父查詢,實質是把某些子查詢重寫爲等價的多表連接操作,這樣有關的的訪問路徑、連接方法、連接順序可能被有效使用、使得查詢語句的層次儘可能減少。

/*
*優化前
*/
SELECT * FROM t_user a,(SELECT * FROM t_zhuhu WHERE 
t_zhuhu.id>10) b WHERE a.zhuhuid<10 AND b.id<20
/*
*優化後
*/
SELECT * FROM t_user a,t_zhuhu b WHERE a.zhuhuid<10
 AND b.id<20 AND b.id>10

3.聚集子查詢消除

原理:利用SQL函數消除子查詢的優化技術。

SELECT * FROM t_user a WHERE a.zhuhuid > (SELECT AVG(b.id)
 FROM t_zhuhu b)

能夠做子查詢優化格式要求:
1.簡單Select查詢中的子查詢,
2.帶有DISTINCT、ORDERBY、LIMIT操作的簡單SELECT查詢中的子查詢。
不能做子查詢優化的格式:
1.帶有UNION操作
2.帶有GROUPBY、HAVING、聚集函數
3.使用ORDERBY中帶有LIMIT
4.內表、外表的個數超過MySQL支持的最大表的連接數(mysql最大連接數63)。

第三招:視圖重寫

定義:視圖是數據庫中基於表的一種對象,把對錶的查詢固化,這種固化是視圖。
原理:MySQL支持簡單視圖優化技術,MySQL把視圖轉爲對基表的查詢,然後進行類似子查詢的優化。但不支持複雜視圖(帶有GROUP BY、Oreder By 等操作稱爲複雜視圖)優化。

/*
 * 創建視圖
 */
CREATE VIEW t_view AS SELECT * FROM t_user   
/*
* 未使用視圖
*/
SELECT a.id FROM (SELECT id,zhuhuid FROM t_user) as a 
WHERE a.zhuhuid>10
/*
* 使用視圖
*/
SELECT id FROM t_view WHERE zhuhuid>10

第四招:等價謂詞重寫

原理:把邏輯表達式重寫成等價的且效率更高的形式,提高查詢執行效率。

1.LIKE規則重寫

如果name列上存在索引,則可以利用索引提高查詢效率。

/*
* 重寫前
*/
name LIKE 'abc'
/*
* 重寫後
*/
name = 'abc'

2.BETWEEN-AND規則

如果sno上建立了索引,則可以用索引掃描代替原來BETWEEN-AND謂詞限定的全表掃描,從而提高了查詢的效率。

/*
* 重寫前
*/
sno BETWEEN 10 AND 20
/*
* 重寫後
*/
sno >=10 AND sno <=20

3.IN轉換OR規則

看實際情況使用,如果age列上存在索引,則轉換後查詢效率會提高。

/*
* 重寫前
*/
age IN (8,12,21)
/*
* 重寫後
*/
age=8 OR age=12 OR age=21

4.NOT規則

如果col_1建立了索引,則可以用索引掃描代替原來的全表掃描,從而提高查詢的效率

/*
* 重寫前
*/
NOT (col_1 != col_2)
/*
* 重寫後
*/
col_1 = col_2

5.OR重寫並集規則

可以分別利用列sex和age上的索引,進程索引掃描,執行UNION操作獲得最終結果。

/*
* 重寫前
*/
SELECT * FROM student WHERE (sex='f' and age>15) OR age>18
/*
* 重寫後
*/
SELECT * FROM student WHERE sex='f' and age>15
UNION
SELECT * FROM student WHERE age>18

第五招:條件化簡
1.把HAVING條件併入WHERE條件,前提是SQL中不存在GROUPBY條件或聚集函數的情況下,才能將HAVING條件與WHERE條件合併。

/*
*例子
*/
SELECT * FROM t1 WHERE a1>1 having a2=2
/*
*等價於
*/
SELECT * FROM t1 WHERE a1>1 and a2=2

2.去除表達式中冗餘的括號

減少語法分析時產生的AND和OR樹的層次。減少了CPU的消耗

/*
*例子
*/
((a AND b)AND (c AND d))
/*
*化簡爲
*/
a AND b AND c AND d

3.常量傳遞

/*
*例子
*/
col_1=col_2 AND col_2=3
/*
*化簡爲
*/
col_1=3 AND col_2=3

4.消除死碼,表達式計算,等式變換,不等式變換,布爾表達式變換

儘量減少數據庫去計算,把一些計算進行優化,儘量利用索引,提升數據庫查詢效率。

第六招.外連接消除、嵌套連接消除、連接消除

連接消除:去掉的是被連接的某個對象。
外連接消除:去掉的事外連接的語義,變形爲內連接。
嵌套連接消除:就是消除嵌套的連接層次,把多個層次的連接減少爲較少層次的連接,儘量"扁平化"。

第七招.8.語義優化

1.連接消除
2.連接引入
3.謂詞引入
4.檢測空回答集
5.排序優化
6.唯一性使用

9.非SPJ的優化

1.GROUP BY、ORDER BY優化,儘量利用索引。

物理優化

1.索引

優點:提高少量數據的獲取/檢索速度
缺點:佔用存儲空間、多個索引耗費索引的挑選時間、降低寫操作的性能,需要實時維護索引、併發情況下索引的維護高度複雜。
不使用索引:數據的重複度高、選擇率高於10%、表的數據量少

MYSQL高級教程

記錄一下學習過程!

1.觸發器

四個必要條件:監視地點(table)、監視事件(insert/update/delete)、觸發時間(after/before)、觸發事件(insert/update/delete)

觸發器使用語法練習

/*
* 聲明以;爲結尾符
*/
delemiter ;   

/*
* 監聽table_1表在table_1表有insert事件之後更新table_2
*/
create trigger trigger_1
after
insert
on table_1
for each row
begin
	update table_2 set num=num-1;
end;

/*
*new.num獲取table_1新插入的num值,相反old.num是獲取表刪除的num值
* insert 只能用 new
* delete 只能用 old
* update 可用 new/old
*/
create trigger trigger_2
after
insert
on table_1
for each row
begin
	update table_2 set num=num-new.num;
end;

/*
*declare 聲明變量
*select num into rnum/set new.num = rnum;賦值
*if 條件 then 語句 end if; 判斷語句
*/
create trigger trigger_3
before
insert
on table_1
for each row
begin
	declare rnum int;
	select num into rnum from table_2 where id=new.id;

	if new.num > runm then
		set new.num = rnum;
	end if;	

	update table_2 set num=num-new.num;

end;

2.存儲過程

/*
*創建存儲過程語法
*/
create procedure procedureName()
begin 
	--sql語句;
ends;

/*
*查看已有的procedure
*/
show procedure status;
/*
*調用存儲過程語法
*/
call procedureName()

/*
 * 給存儲過程傳參數
 */
create procedure p1(width int,height int)
begin
	select concat('你的面積是',width * height);
	if width > height then
	select '你挺胖';
	elseif width<height then
	select '你挺瘦';
	else
	select '你挺方';
	end if;
end;
--調用
CALL p1(4,5)

/*
*in 輸入 out 輸出
*/
create procedure p2(in n int,out total int)
begin 
declare num int default 0;
	set total = 0;
	while num < n do
		set num = num + 1;
		set total = total + num;
	end while;
end;

call p2(100,@total)

SELECT @total

/*
*inout 輸入處理後輸出,即是輸入又是輸出
*/
create procedure p3(inout age int)
begin
	SELECT CONCAT("20年後你的年齡是:",age+20);
end;

set @age =18;

call p3(@age)


/*
*repeat的用法
*/
--刪除存儲過程
drop  procedure p4

create procedure p4()
	begin 
	declare num int default 0;
	declare total int default 0;
	repeat
	set num = num +1;
	set total = total + num;
	until num >= 100 end repeat;
	select total;
	end
	
call p4()	

/*
*case的用法
*RAND()隨機0.1-1的數
*floor()取整
*/
create procedure p5()
begin
declare a int default 1;
set a = floor(RAND()*5);
case a 
WHEN 0  then select "我是0";
WHEN 1  then select "我是1";
WHEN 2  then select "我是2";
else select "我不是0,1,2";
end case;
end;

call p5();

3.遊標

定義:sql查詢多條結果集,利用遊標可以一次取出一行
聲明:declare 遊標名 cursor for sql查詢結果集
打開:open 遊標名
取值:fetch 遊標名 into 值1,值2
關閉:close 遊標名

CREATE TABLE t_student ( sid INT PRIMARY KEY, sname VARCHAR ( 20 ), sage INT );

INSERT INTO t_student ( sid, sname, sage ) VALUES ( 1, "李一", 10 );
INSERT INTO t_student ( sid, sname, sage ) VALUES ( 2, "李二", 20 );
INSERT INTO t_student ( sid, sname, sage ) VALUES ( 3, "李三", 30 );

create procedure p6()
begin
declare row_sname varchar(20);
declare you int default 1;
declare c1 cursor for select sname from t_student;
declare exit handler for not found set you =0;  
--如果句柄沒有值設置you爲0 
--exit handler觸發後,後面的語句不再執行
--continue handler觸發後,後面的語句繼續執行
--undo handler觸發後,前面的語句撤銷 mysql不支持
open c1;
repeat 
fetch c1 into row_sname;SELECT row_sname;
until you = 0 end repeat; 
close c1;
end;

call p6

4.用戶權限設置
在這裏插入圖片描述
5.主從複製

配置:https://www.cnblogs.com/liaojie970/p/6198547.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章