如何寫出優質mysql實戰

需求1:找出發佈文章的用戶姓名以及文章的信息

首先創建一張普通的表 文章表

create table article(
	id int PRIMARY key auto_increment,
	title varchar(10) not null,
	publish_id int not null,#文章的發佈人
	gmt_create TIMESTAMP, # 發佈時間
	comment_number INT,# 評論數
	like_number int ,#喜歡的人數
	view_number int ,#瀏覽數
	content  VARCHAR(1000)#文章內容
    category_id int#文章所屬類型
)

用戶表

create table users(
	id int primary key auto_increment,##用戶的唯一索引
	publish_id int not null,##用戶的賬號
	`name` varchar(10) ,#用戶的姓名
	user_pwd varchar(20) not null
)

select * from article left join users on users.publish_id = article.publish_id;

在這裏插入圖片描述
分析(病例書) select_type爲SIMPLE說明是普通的查詢 type=ALL 全表查詢,position_keys 和key 說明沒有用到索引,並且最重要的extra中使用了using join buffer,可見效率很差。

如何優化(治病)
雙表建立索引時,對於左連接而言,連接的關鍵是右邊的表,所以索引建在右邊的表上即users上
添加索引
alter table users add index publish(publish_id);
治療結果 extra裏面了上面的額外條件。而且也用了索引。
在這裏插入圖片描述

需求2. 顯示用戶文章下評論數最多的3篇文章,並且顯示用戶的名字。

sql語句
select * from article left join users on users.publish_id = article.publish_id where article.publish_id =1 ORDER BY comment_number desc limit 3 ;
首先寫下沒有優化時的狀態。
在這裏插入圖片描述
分析:extra裏面使用了 using filesort 並且type爲All 可以,此sql肯定需要優化
如果只給publish_id加上索引,雖然在很短的時間內可以找到用戶,但是對於用戶文章評論數的排序就要浪費時間,這會引起 using filesort.因此我們需要對publish_id和comment_number使用複合索引。

如何優化(治病)
alter table article add index index_demo(publish_id,comment_number);
效果,
在這裏插入圖片描述

需求3. 查找出在特定的一天內發佈文章,並且發佈類型爲2的用戶的信息。

sql 語句
select * from article where DATE_FORMAT(gmt_create,'%Y-%m-%d')='2020-04-02' and category_id=2
在這裏插入圖片描述
type ALL 有優化的空間
我們給日期和類型加上覆合索引
alter table article add index index_demo(gmt_create,category_id);
在這裏插入圖片描述
結果卻沒有用
我們換一種索引的方式
alter table article add index index_demo(category_id,gmt_create);
發現下面可以使用
在這裏插入圖片描述
得出結論 不能對索引的列進行函數的操作 ,不然索引會失效。
但是上面那句也對日期進行操作了呀,因爲索引的第一個字段是category_id,並且在查詢的時候category_id在最開始因此沒有失效,而最開始的時候是將gmt_create置於最開始,因此如果對最開始的gmt_create進行操作,索引就會完全失效。

如果我們在查詢的時候調換下gmt_create 和category_id的位置不對索引進行函數操作會怎麼樣 如下。
sql語句
select * from article where gmt_create ='2020-04-02 08:13:31' and category_id=2
在這裏插入圖片描述
發現索引沒有失效,這是爲什麼,我在知乎上看到,首先肯定的是mysql在執行的時候是按照(category_id和gmt_create)進行執行的,之所以上面可以查到,因爲mysql有查詢優化器,它會查詢我們的索引,找出最佳的查找順序並執行。

但是必須包含索引的第一個字段也就是category_id,否則就會失效 如下
在這裏插入圖片描述

需求4. 搜索與標題類似的文章

sql 語句
select * from article where title like ‘%spring%’
在這裏插入圖片描述
上述進行了全表掃描,在優化的過程中我們可以遵守 like關鍵字%加在字段前面索引失效的原則
修改語句
select * from article where title like 'spring%'
在這裏插入圖片描述
但是出現一個問題就是查詢不出匹配的數據了。
那麼我們如何做
這就涉及到覆蓋索引的問題,我們用* 來查詢時使用like肯定會索引失效,但是我們要明確寫出查詢的字段 就不會索引失效,如下
select title from article where title like '%spring%' 很明確的使用了覆蓋索引,雖然possible_keys爲null 但是key 實際上還是使用了索引,這就是覆蓋索引的魅力。
在這裏插入圖片描述

需求5. 查找title爲2000的文章。

sql語句
select * from article where title = 2000;
首先肯定的時能查詢出來 雖然 name時varchar類型的。
在這裏插入圖片描述
但是explain 檢查之後發現
在這裏插入圖片描述
type 爲ALL 是全表掃描的
我們再中規中矩寫sql 給title加上單引號
select * from article where title = '2000';
在這裏插入圖片描述
哈哈 又用上索引了,太棒了。
總結 varchar類型的字段一定注意要加上單引號。
注意在mybatis中#$的區別
使用#{name}時 在sql語句中是加了雙引號的
使用${name}時 在sql語句中是直接顯示的。

select id,name,age from student where id =#{id}
當我們傳遞的參數id爲 “1” 時,上述 sql 的解析爲:
select id,name,age from student where id ="1"

SqLselectid,name,agefromstudentwhereid=傳入的參數在SqL中直接顯示爲傳入的值 `select id,name,age from student where id ={id}當我們傳遞的參數id爲 "1" 時,上述 sql 的解析爲:select id,name,age from student where id =1`

在這裏插入圖片描述

優化口頭禪
帶頭大哥不能死
中間兄弟不能斷
varchar引號不能丟
範圍之後全失效
索引列上無計算
like百分加右邊

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