需求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"
{id}當我們傳遞的參數id爲 "1" 時,上述 sql 的解析爲:
select id,name,age from student where id =1`
優化口頭禪
帶頭大哥不能死
中間兄弟不能斷
varchar引號不能丟
範圍之後全失效
索引列上無計算
like百分加右邊