資料庫(4)索引優化和SQL語句優化

2021-08-21 03:52:32 字數 4454 閱讀 5532

這一段時間一直在學習關係型資料庫,準備寫乙個小專題來總結一下這一段時間的學習結果。

話說資料庫優化一直是sql型資料庫的熱門問題,包括從網路i/o方面,從硬碟i/o方面,從cpu計算方面等等很多手段,都可以對資料庫進行優化。

這篇文章主要總結了如何建立合適的索引提公升查詢速度,如何通過優化sql提公升語句執行速度。

當然這些**都是淺嘗輒止的,如果有任何謬誤,希望大家指出。

二. sql語句優化

首先聚合索引是提公升查詢速度的最有效的手段。基於聚合索引的性質,我們可以了解到,資料庫的物理儲存順序是按照聚合索引順序排列的,而通過聚合索引的b+樹,我們可以迅速的查詢到任何一行的全部資訊,注意是全部資訊。

不了解聚集索引的同學可以參考我的 資料庫(3)資料庫索引這篇文章。

在mysql中,innodb引擎會預設主鍵索引為聚集索引,所以建立乙個表時,我們應該優先設立乙個主鍵,後面所有基於主鍵的where條件查詢語句都會使用到這個聚集索引。

一行資料唯一的身份標識(資料庫原理中叫做候選碼),可以是幾列的組合

額外新增的字段,用來唯一標識一行,通常是自增的id

create

table test(

id int

primary

key,

# 其他字段

);

同時需要特別注意的是,如果在乙個表有很多資料的情況下,新增了主鍵,那麼會導致這個表重新對硬碟上的儲存結構做調整,這是乙個費時的過程,所以推薦在建表時就建立主鍵,從而獲得聚集索引。我們知道,對於資料的查詢,一般是通過條件查詢(where語句),而如果條件查詢中的字段上沒有建立索引的話,就會進行一次全表掃瞄,這是非常耗時的操作。

create

table test(

id int,

name varchar(20)

); // 假設test表沒有任何索引

select name from test where id=100; // 這條語句會導致全表查詢,然後再進行where語句篩選(沒有支援icp的情況下)

這時候我們需要對id字段建立索引

create

index index_name

on table_name (id)

這樣再進行查詢語句就會使用b+樹進行索引查詢得到id=100的索引葉節點,然後根據查到的聚合索引的值,進行二次查詢得到name這是因為非聚集索引的葉子節點儲存結構類似下圖。

更好的解決方案是建立乙個組合索引

create

index index_name

on table_name (id,name)

這樣就不需要進行二次查詢,而是直接完全通過索引b+樹的葉子節點內容久能得到name比如說你建立了乙個表:

create

table test(

name_1 char(20),

name_2 char(20),

name_3 char(20),

index index_1 (name_1,name_2,name_3)

);

建立了乙個組合索引(name_1,name_2,name_3)然後你美滋滋的進行了一波查詢:

select name_1 from test where name_1='haha';

select name_1 from test where name_2='wuwu';

select name_1 from test where name_3='yingyingying';

select name_1 from test where name_1='haha'

and name_2='wuwu';

select name_1 from test where name_1='haha'

and name_3='yingyingying';

我們逐條來分析這些語句會如何使用索引進行查詢:

查詢字段name_1在建立的索引裡,而條件語句中where name_1='haha'也在索引裡,而且符合最左字首規則,索引毫無疑問,這次查詢會直接使用索引查詢,而且查詢資料在索引葉子節點裡,查詢效率是很高的。查詢字段name_1在建立的索引裡,而條件語句中where name_2='wuwu'也在索引裡,但不符合最左字首原則,這種查詢不會使用到b+樹的優秀特性,而是會進行全索引查詢,然後再比較where語句條件和上面那種情況一樣,也是會進行全索引查詢,然後再比較where語句條件查詢字段name_1在建立的索引裡,條件語句where name_1='haha' and name_2='wuwu'欄位在索引裡,而且符合最左字首原則,因此會利用b+樹的性質進行查詢,效率是很高的。

where name_1='haha' and name_3='yingyingying'條件語句違背了最左字首原則,需要進行全索引查詢,而且這種寫法會進行兩次where語句條件的比較,效率及其低下。

可以看到,建立組合索引優化查詢語句時,一定要考慮到最左字首原則,否則你的索引建立的可以說毫無意義。

什麼是無意義的索引?

基本上就是和上面體到的原則衝突的索引型別:

查詢次數很少的語句中的字段的索引,因為建立索引是會降低資料表dml(insert,update,delete)效能的,如果一條語句查詢語句一天都用不到幾次,你卻為它建立了繁雜的索引,那麼將會導致資料表很不科學。

備註描述和大字段的索引,比如資料庫中儲存了文章字段,如果對這個字段新增了索引,那麼將會增加非常多的額外磁碟占用開銷,而且查詢效率並不能得到很大的提公升。

日期,年月,狀態位,長字元,這些欄位在資料庫設計是盡量要滿足3nf的要求,通過主鍵或者唯一鍵就能獲得這些資訊,盡量不要依據這些資訊建立索引進行查詢。

對於這方面我是真的不敢信口開河,因為我也只是處於學習階段,因此也只總結一些常見的優化手段。

這是顯而易見的一條原則,我們知道b樹這種資料結構實在是太適合資料庫儲存了,查詢效能比起順序查詢高出太多倍了,因此如果能利用到自己建立的索引,那麼就會極大的提公升查詢語句的效能。

sql什麼條件會使用索引?

當字段上建有索引時,通常以下情況會使用索引,在where語句中:

index_column = x

index_column > x

index_column >= x

index_column < x

index_column <= x

index_column between x and x

index_column in (x,y,...,z)

index_column like 'x' 或者 'x%'(後導模糊查詢)

t1. index_column=t2. column1(兩個表通過索引字段關聯)

以上x,y,z代表任何和index_column同一型別的資料同時避免查詢時不能使用索引查詢的資料:

可以看到幾乎是和能使用索引查詢的情況對立的。總結就是

不等的操作

函式運算或者運算子預算後的字段

前導模糊查詢

字段型別不同

null值

不符合最左字首規則

distinct在查詢乙個字段或者很少欄位的情況下使用,會避免重複資料的出現,給查詢帶來優化效果。

但是查詢字段很多的情況下使用,則會大大降低查詢效率。

這樣會減少i/o查詢的次數。

這樣會減少網路i/o的壓力,避免一次傳輸資料過多導致速度變慢。

jdbc中的批處理了解一下,批量插入比起迴圈插入效能高太多了(當然這還和程式語言已經網路有關)

12 優化資料庫 優化SQL語句 索引

第 一 優化索引 sql語句 分析慢查詢 第二 設計表的時候嚴格按照資料庫的設計正規化來設計資料庫 第三 我們可以加上redis快取,將經常被訪問到的資料,但是不需要經常變化的資料放入至redis快取伺服器裡面 第四 還可優化硬體,在硬體層面,我們可以使用更好的一些硬碟 固態硬碟 使用一些磁碟陣列技...

資料庫調優教程 優化sql語句

上一章講了如何設計一張好的表,一張好的表自然需要好的sql語句去操作它。本章就來聊聊如何優化sql語句。1.sql語句優化原則 優化需要優化的query 定位優化物件效能瓶頸 從explain入手 盡可能在索引中完成排序 只取自己需要的column 盡可能避免複雜的join和子查詢 2.優化limi...

資料庫調優教程(十二) 優化sql語句

上一章講了如何設計一張好的表,一張好的表自然需要好的sql語句去操作它。本章就來聊聊如何優化sql語句。1.sql語句優化原則 優化需要優化的query 定位優化物件效能瓶頸 從explain入手 盡可能在索引中完成排序 只取自己需要的column 盡可能避免複雜的join和子查詢 2.優化limi...