1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
1)创建测试表 test@CISCOSYS> create table t as select * from dba_objects;
表已创建。 test@CISCOSYS> update t set object_id =rownum ;
已更新50967行。 2)使用 count (*)进行统计
test@CISCOSYS> select count (*) from t;
COUNT (*)
---------- 50967 已用时间: 00: 00: 00.01 执行计划 ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 161 (2)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL | T | 44475 | 161 (2)| 00:00:02 |
------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement
统计信息 ---------------------------------------------------------- 4 recursive calls 0 db block gets 764 consistent gets 0 physical reads 0 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to / from client
0 sorts (memory) 0 sorts (disk) 1 rows processed
3)使用 COUNT (列)进行统计
test@CISCOSYS> select count (*) from t;
COUNT (*)
---------- 50967 已用时间: 00: 00: 00.01 执行计划 ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 161 (2)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL | T | 44475 | 161 (2)| 00:00:02 |
------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement
统计信息 ---------------------------------------------------------- 4 recursive calls 0 db block gets 764 consistent gets 0 physical reads 0 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to / from client
0 sorts (memory) 0 sorts (disk) 1 rows processed
解释一下 :物理读为0,是因为创建表的时候,数据已经载入 load buffer.
可以使用 test@CISCOSYS> alter system flush buffer_cache;
通过比较 COUNT (*) 和 Count (列) ,两种情况的COST 是完全一样的。
继续试验!!! 为表创建索引 test@CISCOSYS> create index idx_t_id on t(object_id);
索引已创建。 test@CISCOSYS> alter system flush buffer_cache;
系统已更改。 test@CISCOSYS> select count (*) from t;
COUNT (*)
---------- 50967 已用时间: 00: 00: 00.26 执行计划 ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 161 (2)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL | T | 44475 | 161 (2)| 00:00:02 |
------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement
统计信息 ---------------------------------------------------------- 5 recursive calls 0 db block gets 765 consistent gets 705 physical reads 0 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to / from client
0 sorts (memory) 0 sorts (disk) 1 rows processed
test@CISCOSYS> select count (object_id) from t;
COUNT (OBJECT_ID)
---------------- 50967 已用时间: 00: 00: 00.09 执行计划 ---------------------------------------------------------- Plan hash value: 3570898368 -------------------------------------------------------------------------------- -- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
| -------------------------------------------------------------------------------- -- | 0 | SELECT STATEMENT | | 1 | 13 | 30 (4)| 00:00:01
| | 1 | SORT AGGREGATE | | 1 | 13 | | | | 2 | INDEX FAST FULL SCAN| IDX_T_ID | 44475 | 564K| 30 (4)| 00:00:01
| -------------------------------------------------------------------------------- -- Note ----- - dynamic sampling used for this statement
统计信息 ---------------------------------------------------------- 4 recursive calls 0 db block gets 181 consistent gets 477 physical reads 0 redo size
418 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to / from client
0 sorts (memory) 0 sorts (disk) 1 rows processed
在这里,用 COUNT (列)比 COUNT (*)要快。通过比较执行计划。可以看出 COUNT (*)不能用到索引,而 COUNT (列)可以
继续试验!!! 将键值设为非空 test@CISCOSYS> alter table T modify object_id not null ;
表已更改。 已用时间: 00: 00: 01.34 test@CISCOSYS> alter system flush buffer_cache;
系统已更改。 已用时间: 00: 00: 00.01 test@CISCOSYS> select count (*) from t;
COUNT (*)
---------- 50967 已用时间: 00: 00: 00.31 执行计划 ---------------------------------------------------------- Plan hash value: 3570898368 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 30 (4)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| IDX_T_ID | 44475 | 30 (4)| 00:00:01 |
-------------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement
统计信息 ---------------------------------------------------------- 205 recursive calls 0 db block gets 213 consistent gets 496 physical reads 0 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to / from client
5 sorts (memory) 0 sorts (disk) 1 rows processed
test@CISCOSYS> alter system flush buffer_cache;
系统已更改。 已用时间: 00: 00: 00.04 test@CISCOSYS> select count (object_id) from t;
COUNT (OBJECT_ID)
---------------- 50967 已用时间: 00: 00: 00.20 执行计划 ---------------------------------------------------------- Plan hash value: 3570898368 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 30 (4)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| IDX_T_ID | 44475 | 30 (4)| 00:00:01 |
-------------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement
统计信息 ---------------------------------------------------------- 4 recursive calls 0 db block gets 181 consistent gets 477 physical reads 0 redo size
418 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to / from client
0 sorts (memory) 0 sorts (disk) 1 rows processed
将一些记录object_id置为 null .
test@CISCOSYS> alter table t modify (object_id number null );
表已更改。 test@CISCOSYS> update t set object_id= null where object_id<=10;
已更新10行。 test@CISCOSYS> select count (*) from t;
COUNT (*)
---------- 50967 已用时间: 00: 00: 00.00 test@CISCOSYS> select count (object_id) from t;
COUNT (OBJECT_ID)
---------------- 50957 发现 count (*)和 count (列)记录不一样。也就是说,两个功能上根本不是等价的。
如果一个列上存在索引,且非空。 COUNT (*)和 COUNT (列)功能相当。
反之, COUNT (*) 和 COUNT (列)两者功能本身就功能不同,不应等同对待。
|
基于案例学SQL
本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1354315,如需转载请自行联系原作者