做者:陳哈哈
來源:blog.csdn.net/qq_39390545/article/details/106766965面試官:「小陳,說一下你經常使用的SQL優化方式吧。」
陳小哈:「那不少啊,好比不要用SELECT *,查詢效率低。巴拉巴拉...」java面試官:「爲何不要用SELECT * ?它在哪些狀況下效率低呢?」
陳小哈:「SELECT * 它好像比寫指定列名多一次全表查詢吧,還多查了一些無用的字段。」mysql面試官:「嗯...」
陳小哈:「emmm~ 沒了」面試陳小哈:「....??(幾個意思)」sql
面試官:「嗯...好,那你還有什麼要問個人麼?」
陳小哈:「我問你個錘子,把老子簡歷還我!」數據庫
不管在工做仍是面試中,關於SQL中不要用「SELECT *」,都是你們聽爛了的問題,雖然說聽爛了,但廣泛理解仍是在很淺的層面,並無多少人去追根究底,探究其原理。 服務器
廢話很少說,本文帶你深刻了解一下"SELECT * "效率低的緣由及場景。網絡
在《阿里java開發手冊(泰山版)》中 MySQL 部分描述:app
4 - 1. 【強制】在表查詢中,一概不要使用 * 做爲查詢的字段列表,須要哪些字段必須明確寫明。
說明:tcp
開發手冊中比較歸納的提到了幾點緣由,讓咱們深刻一些看看:性能
準確來講,長度超過 728 字節的時候,會先把超出的數據序列化到另一個地方,所以讀取這條記錄會增長一次 io 操做。(MySQL InnoDB)
SELECT * 杜絕了覆蓋索引的可能性,而基於MySQL優化器的「覆蓋索引」策略又是速度極快,效率極高,業界極爲推薦的查詢優化方式。
例如,有一個表爲t(a,b,c,d,e,f),其中,a爲主鍵,b列有索引。
那麼,在磁盤上有兩棵 B+ 樹,即彙集索引和輔助索引(包括單列索引、聯合索引),分別保存(a,b,c,d,e,f)和(a,b),若是查詢條件中where條件能夠經過b列的索引過濾掉一部分記錄,查詢就會先走輔助索引,若是用戶只須要a列和b列的數據,直接經過輔助索引就能夠知道用戶查詢的數據。
若是用戶使用select *,獲取了不須要的數據,則首先經過輔助索引過濾數據,而後再經過彙集索引獲取全部的列,這就多了一次b+樹查詢,速度必然會慢不少。
因爲輔助索引的數據比彙集索引少不少,不少狀況下,經過輔助索引進行覆蓋索引(經過索引就能獲取用戶須要的全部列),都不須要讀磁盤,直接從內存取,而彙集索引極可能數據在磁盤(外存)中(取決於buffer pool的大小和命中率),這種狀況下,一個是內存讀,一個是磁盤讀,速度差別就很顯著了,幾乎是數量級的差別。
上面提到了輔助索引,在MySQL中輔助索引包括單列索引、聯合索引(多列聯合),單列索引就再也不贅述了,這裏提一下聯合索引的做用
聯合索引 (a,b,c) 實際創建了 (a)、(a,b)、(a,b,c) 三個索引
咱們能夠將組合索引想成書的一級目錄、二級目錄、三級目錄,如index(a,b,c),至關於a是一級目錄,b是一級目錄下的二級目錄,c是二級目錄下的三級目錄。要使用某一目錄,必須先使用其上級目錄,一級目錄除外。
以下:
where條件
效果
where a=1 and c=1
只使用了一級目錄,c在三級目錄,沒有使用二級目錄,那麼三級目錄就無法使用
where a=1 and b=1
只使用了一級目錄、二級目錄。
建一個聯合索引 (a,b,c) ,實際至關於建了 (a)、(a,b)、(a,b,c) 三個索引。每多一個索引,都會增長寫操做的開銷和磁盤空間的開銷。對於大量數據的表,使用聯合索引會大大的減小開銷!
對聯合索引 (a,b,c),若是有以下 sql 的,
SELECT a,b,c from table where a='xx' and b = 'xx';
那麼 MySQL 能夠直接經過遍歷索引取得數據,而無需回表,這減小了不少的隨機 io 操做。減小 io 操做,特別是隨機 io 實際上是 DBA 主要的優化策略。因此,在真正的實際應用中,覆蓋索引是主要的提高性能的優化手段之一。
索引列多,經過聯合索引篩選出的數據越少。好比有 1000W 條數據的表,有以下SQL:
select col1,col2,col3 from table where col1=1 and col2=2 and col3=3;
假設:假設每一個條件能夠篩選出 10% 的數據。
答案天然是否認的
相信能看到這裏這老鐵要麼是對MySQL有着一腔熱血的,要麼就是喜歡滾鼠標的。來了就是緣分,若是從本文學到了東西,請不要吝嗇手中的贊哦,拒絕白嫖~
有朋友問我,你對SQL規範那麼上心,平時你寫代碼不會用SELECT * 吧?
咋可能啊,每天用。。代碼裏也在用(一臉羞愧),其實咱們的項目廣泛很小,數據量也上不去,性能上尚未遇到瓶頸,因此比較放縱。
寫本篇文章主要是這個知識點網上總結的不多很散,也不規範,算是給本身也是給你們總結一份比較詳細的,值得記一下的。之後給面試官說完讓他無法找你茬。