MySql | 為什麼大家都在說 Select * 效率低
Hi ! 我是小小,今天帶來本週的第三篇。為什麼大家都在說 Select * 效率低。
面試現場
面試官:“小小啊,說一說你常用的SQL優化方式吧”。
小小:“很多的,相當多,比如不要用SELECT,查詢效率低,巴拉巴拉。。。”
面試官:“為什麼不要用 SELECT* ?它在那些情況下效率低呢?”
小小:“SELECT * 它好像比寫指定列多一次全表查詢吧,還多查了一些無用的欄位。”
面試官:“嗯?”
小小:“emememem~ 沒了”
小小:“...??????”
面試官:“嗯,你還有什麼藥問的”
小小:“沒了,我問你個錘子,趕緊把簡歷給我”
下面開始進入正題,
不需要的列會增加資料傳輸時間和網路開銷
用SELECT * 資料庫需要解析更多的物件,欄位,許可權,屬性等等相關內容,在SQL語句複雜,硬解析較多的情況下,會對資料庫造成沉重的負擔。
增大網路開銷,* 有時會誤操作,帶上log,icomMD%等之類的無用且大的文字欄位,資料傳輸size會幾何的增長,如果DB和應用程式不在同一臺機器,這種開銷相當的明顯
即使 Mysql 伺服器和客戶端在同一臺機器上,使用的協議還是 tcp,通訊也需要額外的時間。
對無用的大欄位,例如varchar,blob,text會增加io操作
正確來說,長度操作728位元組的時候,會先把超出的資料序列化到另外一個地方,因此肚臍去的時候,這條記錄會增加一次io操作。
失去Mysql優化器,覆蓋索引優化措施的可能性
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 的大小和命中率),這種情況下,一個是記憶體讀,一個是磁碟讀,速度差異就很顯著了,幾乎是數量級的差異。
後期維護
使用 SELECT * 時候,不熟悉程式碼庫的人將會被迫查詢文件,以瞭解能夠進行有效更改之前需要返回那些列,從長遠來看,使得程式碼更不具有可讀性,從而耗費了更多的時間和精力。
如果程式碼取決於列順序,SELECT * 則如果表的列順序已經更改,則會隱藏等待發生的錯誤。
使用時配置更加複雜化。
設計模式
select * 是反設計模式。
查詢的目的不太明顯,應用程式使用的列是不透明的,打破的列的模組化設計。
關於作者
我是小小,一個生於二線,活在一線的程式猿,我是小小,我們下期再見。
小明菜市場
推薦閱讀
●執行流程 | 你真的瞭解Spring AOP的執行順序嗎?
給我個好看再走好嗎?