Consistent gets 的理解
来源:互联网 发布:古玩玉器交友软件 编辑:程序博客网 时间:2024/05/22 18:48
Consistent gets 与db block gets的区别很明显,后者指DML访问,前者指SELECT访问,这里的一致性读不表示从回滚块组织一致性数据,意思是以保证一致性为目标的读。DML不需要保证一致性,所以直接读data block。
Consistent gets 的值是怎么得来,有何意义,现在也并不很明白。计算公式差不多等于:
SELECT COUNT(*) FROM T5;得到的Consistent gets + (结果集的行数rows / arraySize);
也有很多COPY一遍又一遍的文章说是rows/arraySize + blocks
指代的意义,是这次查询扫描了几次数据块,并不是几个数据块。开始我一直没想到这里。
现在的理解还是比较模糊,仅供参考:
在没有索引的表上面条件查询时,先进行全表扫描,得到完整结果集,服务端组织数据到SQLPLUS显示,由于设置了arraySize分页,默认15,那么服务器与客户端网络上往返的次数会跟这个arraySize有关。如果<15条数据,得到一次,如果是50条数据,得到4次。再加上count得到的值。
但是大数据量的时候这个公式还是不准确。
create table T5( id NUMBER(9), age NUMBER(9), name VARCHAR2(888))
begin for i in 1..50 loop insert into t5 values(i,99,'TOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMYTOMMY'); END LOOP; COMMIT; END;
查数据库分布:SQL> SELECT dbms_rowid.rowid_block_number(ROWID) L,COUNT(*) FROM T5 GROUP BY dbms_rowid.rowid_block_number(ROWID); L COUNT(*)---------- ---------- 189 12 191 12 188 2 190 12 192 12
SQL> select blocks from user_segments where segment_name ='T5'; BLOCKS---------- 8
SQL> SELECT blocks,empty_blocks FROM USER_TABLES T WHERE T.TABLE_NAME='T5'; BLOCKS EMPTY_BLOCKS---------- ------------ 5 3
总共50条记录。分布在5个数据块。另外有三个空块。
但是,上面第一个使用ROWID_BLOCK_NUMBER的查询在数据量大的时候与USER_TABLES表明的块数量会不一样。这些是有差别的。
进入SQLPLUS
多次查询保证没有物理读。
SQL> set autotrace traceonly statistics;SQL> select count(*) from t5;统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 7 consistent gets 0 physical reads 0 redo size 408 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(*) = 7。这7个里面,先是访问了5个数据块,从块头读到记录行数(或者扫描块体),另外的两个就不得而知了。
当进行条件查询时,仍然进行全表扫描,这时就以这个7为基数,然后加上因为arraySize导致的客户端服务端往返的重复扫描同一个块的次数。
所以过程可能是:第一步执行所有数据块的全部扫描,得到7次,然后会确定结果集的分布情况,分布在哪些数据块里面,接下来再到这些块里面提取行,提取的过程因为arraySize所以可能会多次进入同一个块提取。
(===================如果是这样:第一步扫描完所有块,得到一个结果集,服务端保留这个结果集为临时数据,然后根据arraySize分成一次或几次发送到客户端,那么后面几次到服务端取数据时就不用访问数据块,所以第一步应该只是确定数据分布吧)
SQL> show arrayarraysize 10SQL> set array 15array和arraysize是一样的SQL> select * from t5;已选择50行。统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 11 consistent gets 0 physical reads 0 redo size 29829 bytes sent via SQL*Net to client 418 bytes received via SQL*Net from client 5 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 50 rows processed
然后改arraysize。重新查询。依次得到
1/2>>32gets
3>>24
4>>20
5/6>>16
7/8>>14
9>>13
10/11/12>>12
13>>10
14/15>>11
20>>10
50>>8
100>>8
这里array=1时只出现了32次,可能是有一些细节处理的机制。因为这些机制,特别是大数据量的时候就不一定准确了。
接下来条件查询:
SQL> select * from t5 where id<=1;统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 1077 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 processedSQL> select * from t5 where id<=15;已选择15行。统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 8 consistent gets 0 physical reads 0 redo size 1220 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) 15 rows processed
改条件,依次得到:
id<=15---------------------------------------8
15<id<=30 ---------------------------------------9
30<id<=45 ---------------------------------------10
45<id ---------------------------------------11
所以,关键应该在于数据集通过arraySize分页的过程中。
另外还有一个fetchSize,SQLPLUS里面没有这个值,JAVA里面可以设置,好像是一个用处
下面设置索引
SQL> CREATE INDEX I_1 ON T5(ID);索引已创建。
全部查询统计信息还是一样。COUNT(*) 也没有变。
条件查询就不一样了。
SQL> SELECT * FROM T5 WHERE ID=5;执行计划----------------------------------------------------------Plan hash value: 4059149231------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 564 | 2 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T5 | 1 | 564 | 2 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | I_1 | 1 | | 1 (0)| 00:00:01 |------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("ID"=5)统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 3 consistent gets 0 physical reads 0 redo size 1083 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
这里数据块可能只扫描了一次,而索引块扫描了两次。
所以关键之处,应该在于理解服务端提取数据的步骤。分成两步,第一步是服务端查询出所有结果集,第二步是分次数发送到客户端。
SQL> SELECT * FROM T5 WHERE ID<=20;已选择20行。执行计划----------------------------------------------------------Plan hash value: 2002323537--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 20 | 11280 | 3 (0)| 00:00:01 ||* 1 | TABLE ACCESS FULL| T5 | 20 | 11280 | 3 (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("ID"<=20)统计信息---------------------------------------------------------- 1 recursive calls 0 db block gets 9 consistent gets 0 physical reads 0 redo size 1387 bytes sent via SQL*Net to client 396 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 20 rows processed
当ID<=19时还是选择的索引范围扫描,当ID<=20时,就变成了全表扫描。因为优化器估算出使用索引可能比全部扫描访问的块更多。
- Consistent gets 的理解
- 对于'Consistent Gets',''Physical Reads'和'DB Block Gets'的理解和解释
- 对'Consistent Gets',''Physical Reads'和'DB Block Gets'的理解和解释
- 对'Consistent Gets',''Physical Reads'和'DB Block Gets'的理解和解释
- 对于'Consistent Gets',''Physical Reads'和'DB Block Gets'的理解和解释
- 对'Consistent Gets',''Physical Reads'和'DB Block Gets'的理解和解释
- 浅谈consistent gets的计算
- Consistent gets
- consistent gets
- +++consistent read(读一致性)的通俗理解 & db block gets的解释
- update对consistent gets的影响
- ++++update对consistent gets的影响
- Oracle 有关 Consistent gets 的测试
- Oracle 有关 Consistent gets 的测试
- Oracle 有关 Consistent gets 的测试
- 关于 db block gets,consistent gets,physical reads的概念
- 关于 db block gets,consistent gets,physical reads的概念
- about consistent read gets
- SLF4J+Logback 日志框架使用
- THE COINBASE BLOG
- Can't login Ubuntu graphic desktop after remotely enabling X11vnc (command line OK)
- samba共享使用端口
- UVA 439 (骑士移动 第一道DFS 13.07.17)
- Consistent gets 的理解
- Android开发入门之建立能与访问者进行相互通信的本地服务
- 高效程序员的45个习惯
- Codeforces Round #189 (Div. 1) Kalila and Dimna in the Logging Industry 斜率DP
- CheckedListBox数据绑定及取值技巧
- Java中同步与并发
- CGAffineTransformInvert: singular matrix. 解决方案
- 黑马程序员____基础加强____反射(框架的基石)
- django admin扩展-自定义后台管理界面