這一段時間一直在學習關係型資料庫,準備寫乙個小專題來總結一下這一段時間的學習結果。
話說資料庫優化一直是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...