1.關於count(1),count(*),和count(列名)的區別
相信大家總是在工作中,或者是學習中對於count()的到底怎么用更快。一直有很大的疑問,有的人說count(*)更快,也有的人說count(列名)更快,那到底是誰更快,我將會在本文中詳細介紹一下到底是count(1),count(*)和count(列明)的區別,和更適合的使用場景。
往常在工作中有人會說count(1)比count(*)會快,或者相反,首先這個結論肯定是錯的,實際上count(1)和count(*)並沒有區別。
接下來,我們來對比一下count(*)和count(列)到底誰更快一些
首先我們執行以下sql,來看一下執行效率(下面sql針對的是ORACLE數據庫,大致邏輯為先刪除t別,然后在根據dba_objects創建t表,在更新t表根據rownum)
1 drop table t purge; 2 create table t as select * from dba_objects; 3 --alter table T modify object_id null; 4 update t set object_id =rownum ; 5 set timing on 6 set linesize 1000 7 set autotrace on --開啟跟蹤 8 9 select count(*) from t; 10 / 11 select count(object_id) from t; 12 /
然后咱們分別看一下“select count(*) from t”和“select count(object_id) from t”語句的執行計划。(執行計划是指sql的一個執行順序和耗費的資源,耗費的資源越少越快,如果在plsql中,使用F8可以查看sql的執行計划)
通過我們執行sql的實驗來說,count(*)和count(列)消耗的資源是一樣的,說面他們是一樣快的,但是真的是這樣么。那么咱們接着以下的實驗。
這次咱們給object_id這一列加一個索引試一下。我們執行一下索引sql
1 create index idx_object_id on t(object_id); 2 select count(*) from t; 3 / 4 5 6 select count(object_id) from t; 7 /
然后我們在分別看一下兩條sql的執行計划
通過我們建完索引后。突然發現count(列)變快了好多,但是count(*)還是和以前一樣的。這說明了count(列)可以用到索引,而count(*)不行,但是真的這樣么,咱們在往下看。
接下來我們給object_id這個字段加上不可為空條件。我們執行以下sql
1 create index idx_object_id on t(object_id); 2 select count(*) from t; 3 / 4 5 6 select count(object_id) from t; 7 /
接下來我們在來看一下count(*)的執行計划
現在count(*)和count(列)一樣快了,由此我們得出了這個結論:count(列)和count(*)其實一樣快,如果索引列是非空的,count(*)可用到索引,此時一樣快。
總結:但是真的結論是這樣的么。其實不然。其實在數據庫中count(*)和count(列)根本就是不等價的,count(*)是針對於全表的,而count(列)是針對於某一列的,如果此列值為空的話,count(列)是不會統計這一行的。所以兩者根本沒有可比性,性能比較首先要考慮寫法等價,這兩個語句根本就不等價。也就失去了去比較的意義!!!
2.關於表中字段順序的問題
首先我們建一張有25個字段的表並加入數據在進行count(*)和count(列)比較。由於建表語句和插入語句和上面雷同。就不貼出代碼了。
然后我們分別執行count(*)和count每一列的操作來看一下到底誰更快一些,由於執行計划太多,就不一一貼圖了。我整理了一個excel來給大家看一下執行的結果
經過實驗我們看出,count(列)越往后。我們的執行效率越慢。所以,我們得出以下結論:
1.列的偏移量決定性能,列越靠后,訪問的開銷越大。
2.由於count(*)的算法與列偏移量無關,所以count(*)最快。
總結:所以我們在開發設計中。越常用的列,要放在靠前的位置。而cout(*)和count(列)是兩個不等價的用法,所以無法比較哪個性能更好,在實際的sql優化場景中要根據當時的業務場景再去考慮是使用count(*)還是count(列)(其中的區別上文有提到)。