此篇主要整理基礎篇中的疑問
PS:文章整理的知識內容及資料均來自極客時間《SQL必知必會》專欄優化
SELECT COUNT(*)
,SELECT COUNT(1)
和SELECT COUNT(具體字段)
的查詢效率具體如何?在MySQL InnoDB存儲引擎中,COUNT(*)
和COUNT(1)
都是對全部結果進行COUNT。若是有WHERE子句,則是對數據表的數據行數進行統計。所以COUNT(*)
和COUNT(1)
本質上並無區別,執行的複雜度都是O(N)
,也就是採用全表掃描,進行循環 + 計數的方式進行統計。code
在MySQL MyISAM 存儲引擎,統計數據表的行數只須要O(1)
的複雜度,這是由於每張 MyISAM 的數據表都有一個 meta 信息存儲了row_count
值,而一致性則由表級鎖來保證。由於 InnoDB 支持事務,採用行級鎖和 MVCC 機制,因此沒法像 MyISAM 同樣,只維護一個row_count
變量,所以須要採用掃描全表,進行循環 + 計數的方式來完成統計。排序
另外在 InnoDB 引擎中,若是採用COUNT(*)
和COUNT(1)
來統計數據行數,要儘可能採用二級索引。由於主鍵採用的索引是聚簇索引,聚簇索引包含的信息多,明顯會大於二級索引(非聚簇索引)。對於COUNT(*)
和COUNT(1)
來講,它們不須要查找具體的行,只是統計行數,系統會自動採用佔用空間更小的二級索引來進行統計。索引
總結:
一、列名爲主鍵,count(列名)
和count(1)
和count(*)
執行效率是同樣的:由於 explain 中 type 類型都爲 index
二、列名不爲主鍵,並且列名沒有建立索引可是其餘字段建立了索引:count(1) = count(*) > count(列名)
;因
爲expalin 中的 type 類型count(1)
和count(*)
類型都爲 index 而count(列名)
的 type 類型爲 all
三、列名不爲主鍵,可是列名建立索引:count(1) = count(*)= count(列名)
;由於 explain 中 type 類型都爲 index
四、若是表多個列而且沒有主鍵,則count(1) = count(*)
五、若是表只有一個字段,則select count(*)
和select count(1)
和select count(列名)
執行效率同樣。
LIMIT
關鍵詞是最後執行的,若是確認結果集就只有一條,爲什麼還需加上LIMIT 1
進行優化?若是你能夠肯定結果集只有一條,那麼加上LIMIT 1
的時候,當找到一條結果的時候就不會繼續掃描了,這樣會加快查詢速度。若是數據表已經對字段創建了惟一索引,那麼能夠經過索引進行查詢,不會全表掃描的話,就不須要加上LIMIT 1
了。事務
在 MySQL 中,支持兩種排序方式,分別是 FileSort 和 Index 排序。在 Index 排序中,索引能夠保證數據的有序性,不須要再進行排序,效率更高。而 FileSort 排序則通常在內存中進行排序,佔用 CPU 較多。若是待排結果較大,會產生臨時文件 I/O 到磁盤進行排序的狀況,效率較低。因此使用 ORDER BY 子句時,應該儘可能使用 Index 排序,避免使用 FileSort 排序。固然你可使用 explain 來查看執行計劃,看下優化器是否採用索引進行排序。內存
ORDER BY 就是對記錄進行排序。若是你在 ORDER BY 前面用到了 GROUP BY,實際上這是一種分組的聚合方式,已經把一組的數據聚合成爲了一條記錄,再進行排序的時候,至關於對分的組進行了排序。效率