1. 程式人生 > 實用技巧 >MySql | 為什麼大家都在說 Select * 效率低

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 * 是反設計模式。

查詢的目的不太明顯,應用程式使用的列是不透明的,打破的列的模組化設計。

關於作者

我是小小,一個生於二線,活在一線的程式猿,我是小小,我們下期再見。

小明菜市場

推薦閱讀

k8s | 搞不明白為什麼大家都在學習 k8s

對戰 | RabbitMq 大戰 kafka

執行流程 | 你真的瞭解Spring AOP的執行順序嗎?

吊打面試官 | Java到底是值傳遞還是引用傳遞

容器 | Docker 如此之好,你為什麼還要用k8s

給我個好看再走好嗎?