今天小麥苗給你們分享的是【優化】COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主鍵)、COUNT(ROWID)、COUNT(非空列)、COUNT(容許爲空列)、COUNT(DISTINCT 列名)等內容,詳細過程參考博客:http://blog.itpub.net/26736162/viewspace-2136339/。數據庫
各位技術愛好者,看完本文後,你能夠掌握以下的技能,也能夠學到一些其它你所不知道的知識,~O(∩_∩)O~:微信
① COUNT(1)和COUNT(*)的區別(重點)ide
② 10046和10053的使用函數
③ 「SELECT COUNT(列)」和「SELECT 列」在選擇索引方面的區別學習
④ COUNT計數的優化優化
Tips:this
① 本文在itpub(http://blog.itpub.net/26736162)、博客園(http://www.cnblogs.com/lhrbest)和微信公衆號(xiaomaimiaolhr)上有同步更新。spa
② 文章中用到的全部代碼、相關軟件、相關資料及本文的pdf版本都請前往小麥苗的雲盤下載,小麥苗的雲盤地址見:http://blog.itpub.net/26736162/viewspace-1624453/。.net
③ 若網頁文章代碼格式有錯亂,請下載pdf格式的文檔來閱讀。3d
④ 在本篇BLOG中,代碼輸出部分通常放在一行一列的表格中。
⑤ 本文適合於Oracle初中級人員閱讀,Oracle大師請略過本文。
本文若有錯誤或不完善的地方請你們多多指正,您的批評指正是我寫做的最大動力。
看了不少有關COUNT(1)和COUNT(*)的區別和效率,衆說紛紜。最終仍是決定本身動手實驗一番。
項目 |
source db |
db 類型 |
RAC |
db version |
11.2.0.3.0 |
db 存儲 |
ASM |
OS版本及kernel版本 |
RHEL 6.5 |
弄清楚COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主鍵)、COUNT(ROWID)、COUNT(非空列)、COUNT(容許爲空列)、COUNT(DISTINCT 列名)之間的區別,以及它們之間的效率問題。
--建立1W行的表 DROP TABLE T_COUNT_LHR; CREATE TABLE T_COUNT_LHR AS SELECT OBJECT_ID, OBJECT_NAME, OWNER, DATA_OBJECT_ID, OBJECT_TYPE, LAST_DDL_TIME FROM DBA_OBJECTS D WHERE D.OBJECT_ID IS NOT NULL AND D.OBJECT_NAME IS NOT NULL AND ROWNUM <= 10000;
--更新空值, UPDATE T_COUNT_LHR t SET t.object_type='' WHERE Rownum<=5; UPDATE T_COUNT_LHR t SET t.LAST_DDL_TIME=T.LAST_DDL_TIME+ROWNUM; UPDATE T_COUNT_LHR t SET t.LAST_DDL_TIME='' WHERE Rownum<=1; COMMIT;
--添加主鍵、非空約束、惟一索引、普通索引 ALTER TABLE T_COUNT_LHR ADD CONSTRAINT PK_OBJECT_ID PRIMARY KEY(OBJECT_ID); ALTER TABLE T_COUNT_LHR MODIFY OBJECT_NAME NOT NULL; CREATE UNIQUE INDEX IDX_LDT ON T_COUNT_LHR(LAST_DDL_TIME); CREATE INDEX IDX_DATA_OBJECT_ID ON T_COUNT_LHR(DATA_OBJECT_ID); CREATE INDEX IDX_DATA_OWNER ON T_COUNT_LHR(OWNER); ALTER TABLE T_COUNT_LHR MODIFY OWNER NOT NULL;
--收集統計信息 EXEC dbms_stats.gather_table_stats(USER,'T_COUNT_LHR'); SELECT d.COLUMN_NAME,d.DATA_TYPE,d.NUM_NULLS,d.NUM_DISTINCT,d.LAST_ANALYZED FROM cols d WHERE d.TABLE_NAME='T_COUNT_LHR';
|
表的信息以下所示:
列名 |
是否主鍵 |
是否容許爲空 |
是否有索引 |
數據類型 |
空值的行數 |
不一樣值的行數 |
總行數 |
OBJECT_ID |
Y |
N |
惟一索引 |
NUMBER |
0 |
10000 |
10000 |
OBJECT_NAME |
N |
無 |
VARCHAR2 |
0 |
8112 |
10000 |
|
OWNER |
N |
普通索引(IDX_OWNER) |
VARCHAR2 |
0 |
5 |
10000 |
|
DATA_OBJECT_ID |
Y |
普通索引(IDX_DATA_OBJECT_ID) |
NUMBER |
7645 |
2318 |
10000 |
|
OBJECT_TYPE |
Y |
無 |
VARCHAR2 |
5 |
20 |
10000 |
|
LAST_DDL_TIME |
Y |
惟一索引(IDX_LDT) |
DATE |
1 |
9999 |
10000 |
須要統計以下幾種狀況:
SELECT COUNT(1) FROM T_COUNT_LHR;--走索引 SELECT COUNT(*) FROM T_COUNT_LHR;--走索引 SELECT COUNT(ROWID) FROM T_COUNT_LHR; --走索引 SELECT COUNT(OBJECT_ID) FROM T_COUNT_LHR; --走索引 SELECT COUNT(OBJECT_NAME) FROM T_COUNT_LHR;--走索引 SELECT COUNT(OWNER) FROM T_COUNT_LHR D;--走索引 SELECT COUNT(D.DATA_OBJECT_ID) FROM T_COUNT_LHR D; --走索引 SELECT COUNT(D.LAST_DDL_TIME) FROM T_COUNT_LHR D;--走索引 SELECT COUNT(D.LAST_DDL_TIME) FROM T_COUNT_LHR D WHERE D.LAST_DDL_TIME IS NOT NULL;--走索引 SELECT D.LAST_DDL_TIME FROM T_COUNT_LHR D; --不走索引 SELECT D.LAST_DDL_TIME FROM T_COUNT_LHR D WHERE D.LAST_DDL_TIME IS NOT NULL;--走索引 SELECT COUNT(DISTINCT DATA_OBJECT_ID) FROM T_COUNT_LHR D;--不走索引 SELECT COUNT(DISTINCT OWNER) FROM T_COUNT_LHR D;--走索引 SELECT COUNT(DISTINCT DATA_OBJECT_ID) FROM T_COUNT_LHR D WHERE DATA_OBJECT_ID IS NOT NULL ;--走索引
|
COUNT()函數是Oracle中的聚合函數,用於統計結果集的行數。其語法形式以下所示:
COUNT({ * | [ DISTINCT | ALL ] expr }) [ OVER (analytic_clause) ] |
COUNT returns the number of rows returned by the query. You can use it as an aggregate or analytic function.
If you specify DISTINCT, then you can specify only the query_partition_clause of the analytic_clause. The order_by_clause and windowing_clause are not allowed.
If you specify expr, then COUNT returns the number of rows where expr is not null. You can count either all rows, or only distinct values of expr.
If you specify the asterisk (*), then this function returns all rows, including duplicates and nulls. COUNT never returns null.
咱們把COUNT的使用狀況分爲如下3類:
① COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主鍵)、COUNT(ROWID)、COUNT(非空列)
② COUNT(容許爲空列)
③ COUNT(DISTINCT 列名)
下面分別從查詢結果和效率方面作個比較:
(一)結果區別
① COUNT(1)、COUNT(*)、COUNT(ROWID)、COUNT(常量)、COUNT(主鍵)、COUNT(非空列)這幾種方式統計的行數是表中全部存在的行的總數,包括值爲NULL的行和非空行。因此,這幾種方式的執行結果相同。這裏的常量能夠爲數字或字符串,例如,COUNT(2)、COUNT(333)、COUNT('x')、COUNT('xiaomaimiao')。須要注意的是:這裏的COUNT(1)中的「1」並不表示表中的第一列,它實際上是一個表達式,能夠換成任意數字或字符或表達式。
② COUNT(容許爲空列) 這種方式統計的行數不會包括字段值爲NULL的行。
③ COUNT(DISTINCT 列名) 獲得的結果是除去值爲NULL和重複數據後的結果。
④ 「SELECT COUNT(''),COUNT(NULL) FROM T_COUNT_LHR;」返回0行。
(二)效率、索引
① 若是存在主鍵或非空列上的索引,那麼COUNT(1)、COUNT(*)、COUNT(ROWID)、COUNT(常量)、COUNT(主鍵)、COUNT(非空列)會首先選擇主鍵上的索引快速全掃描(INDEX FAST FULL SCAN)。若主鍵不存在則會選擇非空列上的索引。若非空列上沒有索引則確定走全表掃描(TABLE ACCESS FULL)。其中,COUNT(ROWID)在走索引的時候比其它幾種方式要慢。經過10053事件能夠看到這幾種方式除了COUNT(ROWID)以外,其它最終都會轉換成COUNT(*)的方式來執行。
② 對於COUNT(COL1)來講,只要列字段上有索引則會選擇索引快速全掃描(INDEX FAST FULL SCAN)。而對於「SELECT COL1」來講,除非列上有NOT NULL約束,不然執行計劃會選擇全表掃描。
③ COUNT(DISTINCT 列名) 若列上有索引,且有非空約束或在WHERE子句中使用IS NOT NULL,則會選擇索引快速全掃描。其他狀況選擇全表掃描。
全文請參考:http://blog.itpub.net/26736162/viewspace-2136339/
長按下圖識別二維碼或微信掃描下圖二維碼來關注小麥苗的微信公衆號:xiaomaimiaolhr,學習最實用的數據庫技術。
本文分享自微信公衆號 - DB寶(lhrdba)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。