本文章为网络笔记,看了warehouse老师的视频受益匪浅,更是感觉自己技术太过初级,特写了本笔记,方便以后反复学习!
如有任何不妥,请发邮件至102448567@qq.com删除文章!
关于warehouse:
http://blog.itpub.net/19602/viewspace-1059211/
11gR2视频第四版 8_05_优化器统计信息_高水位_柱状图等
optimizer statistics:
优化器作用:负责sql执行的时候解析sql并生成执行计划
sql访问的对象如果没有优化器统计信息的话而且又把动态取样屏蔽了这个时候就很容易产生错误的执行计划,从而这个sql的性能就很差

optimizer statistics分为三种
1.table
select * from dba_tabes where table_name = ‘TT2’;
其中的blocks:表示存放这个表里的数据用了多少个块
num_rows:表里一共有多少行数据
avg_row_len:平均每一行的长度是多少个字节
这三个信息能宏观的说明这个表大不大
2.index
select * from dba_indexes where table_name = ‘TT2’

blevel:树的深度=树的高度减1(高度就是只有branch和leaf就是2层高)
leaf_blocks:叶子块的数量
distinct_keys:这个index有多少个不同的值

SQL> select count(distinct object_id) from tt2;COUNT(DISTINCTOBJECT_ID)
------------------------14726

avg_leaf_blocks_per_key:平均每个介质在几个叶子上,意思就是所有的object_id=2在1个leaf上存放着,3在1个叶子上存放着…

下面可以看到在索引中所有相同的数据都在同一个块中

row#0[4600] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 00 8b 00 30
row#1[4612] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 01 e9 00 30
row#2[4624] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 02 ed 00 01
row#3[4636] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 03 d3 00 1c
row#4[4648] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 04 4b 00 30
row#5[4660] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 05 78 00 18
row#6[4672] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 06 45 00 3a
row#7[4684] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 07 18 00 30
row#8[4696] flag: ------, lock: 0, len=12
col 0; len 2; (2):  c1 03
col 1; len 6; (6):  01 00 07 57 00 0b

而表中的相同的数据是分散在不同的块中的

SQL> select object_id,rowid,dbms_rowid.rowid_block_number(rowid) from tt2 where object_id = 2;OBJECT_ID ROWID          DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------ ------------------------------------2 AAAD9tAAEAAAACDAAw                     1312 AAAD9tAAEAAAAFwAAw                     3682 AAAD9tAAEAAAAJnAAX                     6152 AAAD9tAAEAAAAN9ABE                     8932 AAAD9tAAEAAAAPJAAs                     9692 AAAD9tAAEAAAATnAAK                    12552 AAAD9tAAEAAAAX+AA+                      15342 AAAD9tAAEAAAAaeAAE                    16942 AAAD9tAAEAAAAbYAAc                    17522 AAAD9tAAEAAAAewAA2                    19682 AAAD9tAAEAAAAiMAAb                    21882 AAAD9tAAEAAAAmpABD                    24732 AAAD9tAAEAAAApQAAr                    26402 AAAD9tAAEAAAAsMAAA                    28282 AAAD9tAAEAAAAwtAAv                    31172 AAAD9tAAEAAAAxGABG                    31422 AAAD9tAAEAAAA0wABD                    33762 AAAD9tAAEAAAA1MAAz                    34042 AAAD9tAAEAAAA5JAAm                    36572 AAAD9tAAEAAAA9kAAJ                    39402 AAAD9tAAEAAABA/AAv                    41592 AAAD9tAAEAAABDuAAY                    43342 AAAD9tAAEAAABHgABE                    45762 AAAD9tAAEAAABKEAAf                    47402 AAAD9tAAEAAABM9AAq                    49252 AAAD9tAAEAAABPnABG                    50952 AAAD9tAAEAAABQLAAV                    51312 AAAD9tAAEAAABUwABJ                    54242 AAAD9tAAEAAABYuAAc                    56782 AAAD9tAAEAAABdLAAN                    59632 AAAD9tAAEAAABewAAw                    60642 AAAD9tAAEAAABi+AAO                   633432 rows selected.

avg_data_blocks_per_key:平均每个介质在几个数据块上,意思是表中的数据是分散的,杂乱的不像是索引中的数据是排好序的,反应数据存放的密集程度

验证一下:

SQL> create table tt3 tablespace users as select * from tt2 order by object_id;Table created.SQL> create index idx_tt3 on tt3(object_id);Index created.SQL> exec dbms_stats.gather_table_stats('sys','tt3');PL/SQL procedure successfully completed.

SQL> select object_id,rowid,dbms_rowid.rowid_block_number(rowid) from tt3 where object_id = 2;OBJECT_ID ROWID          DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------ ------------------------------------2 AAAD9vAAEAAABj7AAA                    63952 AAAD9vAAEAAABj7AAB                    63952 AAAD9vAAEAAABj7AAC                    63952 AAAD9vAAEAAABj7AAD                    63952 AAAD9vAAEAAABj7AAE                    63952 AAAD9vAAEAAABj7AAF                    63952 AAAD9vAAEAAABj7AAG                    63952 AAAD9vAAEAAABj7AAH                    63952 AAAD9vAAEAAABj7AAI                    63952 AAAD9vAAEAAABj7AAJ                    63952 AAAD9vAAEAAABj7AAK                    63952 AAAD9vAAEAAABj7AAL                    63952 AAAD9vAAEAAABj7AAM                    63952 AAAD9vAAEAAABj7AAN                    63952 AAAD9vAAEAAABj7AAO                    63952 AAAD9vAAEAAABj7AAP                    63952 AAAD9vAAEAAABj7AAQ                    63952 AAAD9vAAEAAABj7AAR                    63952 AAAD9vAAEAAABj7AAS                    63952 AAAD9vAAEAAABj7AAT                    63952 AAAD9vAAEAAABj7AAU                    63952 AAAD9vAAEAAABj7AAV                    63952 AAAD9vAAEAAABj7AAW                    63952 AAAD9vAAEAAABj7AAX                    63952 AAAD9vAAEAAABj7AAY                    63952 AAAD9vAAEAAABj7AAZ                    63952 AAAD9vAAEAAABj7AAa                    63952 AAAD9vAAEAAABj7AAb                    63952 AAAD9vAAEAAABj7AAc                    63952 AAAD9vAAEAAABj7AAd                    63952 AAAD9vAAEAAABj7AAe                    63952 AAAD9vAAEAAABj7AAf                    639532 rows selected.

因为tt3是排好序的,所以object_id相同的数据就放在了一起,也就是avg_data_blocks_per_key会很小
对比tt2tt3的逻辑读,因为tt3数据存放的密集,所以他访问的块就少,逻辑读就少,效率就高

SQL> select count(object_name) from tt2 where object_id = 2;Execution Plan
----------------------------------------------------------
Plan hash value: 1424956034---------------------------------------------------------------------------
| Id  | Operation      | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 1 |    25 | 4   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      | 1 |    25 |        |      |
|*  2 |   TABLE ACCESS FULL| TT2  | 1 |    25 | 4   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - filter("OBJECT_ID"=2)Statistics
----------------------------------------------------------1  recursive calls0  db block gets39  consistent gets0  physical reads0  redo size536  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processedSQL> select count(object_name) from tt3 where object_id = 2;Execution Plan
----------------------------------------------------------
Plan hash value: 409595855----------------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |         |     1 |    25 |     4   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE          |         |     1 |    25 |        |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| TT3     |    32 |   800 |     4   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN      | IDX_TT3 |    32 |       |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------3 - access("OBJECT_ID"=2)Statistics
----------------------------------------------------------2  recursive calls0  db block gets7  consistent gets0  physical reads0  redo size536  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

clustering_factor:聚集因子/集群因子(和avg_data_blocks_per_key类似反应的也是表中数据的密集程度)

聚集因子算法:上图中五个蓝色小方块相当于一个数据块,C、B、A等相当表中数据,索引中的rowid指向数据块中的数据,如果我们找C假设当前的聚集因子是5,当找到第一个C的时候,聚集因子加1,如果找到下一个C的时候也是在相同的块中那聚集因子不增加了,如果是在别的块中就再加1
降低聚集因子的方法就是重新建表,在建表的时候按照索引字段排好序
所以tt3的聚集因子比tt2低很多

最理想的状态是dba_indexes中的clustering_factor跟dba_tables中的blocks非常接近,也就是说所有相同的值都是放在了同一个块中,想要找哪个值直接在一个块中就找出来了。
从10g开始create index的时候自动收集了统计信息
手动收集dbms_stats.gather_index_stats('owner','index_name')
手动删除dbms_stats.delete_index_stats('owner','index_name')
3.column
在收集表的统计信息的时候自动收集列的统计信息,也可以排除列的统计信息但是这种操作没有意义
select * from dba_tab_col_statistics where table_name = ‘对应的表’
分为两种:
a.basic(基本的)

因为object_id上有索引,就拿这个字段为例

其中NUM_DISTINCT:多少个不同值
LOW_VALUE:最小值
HIGH_VALUE:最大值
NUM_NULLS:多少个空值
验证一下:

SQL> select min(object_id),max(object_id),count(distinct object_id) from tt2;MIN(OBJECT_ID) MAX(OBJECT_ID) COUNT(DISTINCTOBJECT_ID)
-------------- -------------- ------------------------2     15000            14726SQL> select utl_raw.cast_to_number('c103') from dual;UTL_RAW.CAST_TO_NUMBER('C103')
------------------------------2SQL> select utl_raw.cast_to_number('C30233') from dual;UTL_RAW.CAST_TO_NUMBER('C30233')
--------------------------------15000

DENSITY(密度):不同值(num_distinct)的倒数
dba_tab_col_statistics中的值是科学计数法,下面的结果是对的

SQL> select 1/14726 from dual;1/14726
----------
.000067907

为什么要收集列的统计信息,是因为Oracle要判断where子句中的字段是走索引效率高还是不走效率高

b.histogram(柱状图/直方图):用来表述列的数据的分布程度
有没有直方图就是看histogram这个列,要是none就是没有直方图

先把表tt2备份一下

SQL> create table tt4 tablespace users as select * from tt2;Table created.SQL> create index idx_tt4 on tt4(object_id);Index created.

修改一下表,为什么是大于等于255是因为buket的数量最大是254

SQL> update tt2 set object_id = 99999 where object_id >= 255;463136 rows updated.SQL> commit;Commit complete.

重新收集统计信息

SQL> exec dbms_stats.gather_table_stats('sys','tt2');PL/SQL procedure successfully completed.

最后这个字段刚刚是none,现在是FREQUENCY(频率)就是直方图的一种,每一个不同的值占用一个bucket,现在是一共有254个不同的值,生成频率直方图的要求就是不同值的数量要小于等于最大bucket的数量也就是<=254

SQL> select min(object_id),max(object_id),count(distinct object_id) from tt2;MIN(OBJECT_ID) MAX(OBJECT_ID) COUNT(DISTINCTOBJECT_ID)
-------------- -------------- ------------------------2     99999              254

想要理解好直方图bucket(桶)概念很重要

直方图的原理:
如果一个列上有直方图查这个视图dba_tab_histograms
分析Oracle是怎么知道999992占的比例多的很多,所以他不走索引

注意上面的数据是取样的,我们有tt2表中有254个不同而objec_id,这里只有74个,想办法所有的都展示出来(estimate_percent=>null就是不要取样收集,100%的收集)

SQL> exec dbms_stats.gather_table_stats('sys','tt2',method_opt=>'for columns object_id size 254',estimate_percent=>null);PL/SQL procedure successfully completed.Elapsed: 00:00:00.55

都显示出来了

ENDPOINT_NUMBER(用来计算值的个数)和ENDPOINT_VALUE(表中不同的值)拿到excel中,看下图也就能理解为什么叫直方图了,Oracle就是根据只直方图来判断列上数据的均匀程度
下面的直方图中的一个柱子就理解成一个bucket

看一下列的分布程度

SQL> select object_id,count(1) from tt2 group by object_id order by object_id;OBJECT_ID   COUNT(1)
---------- ----------2     323     324     325     32
--...中间略,中间的count(1)都是32253    32254       3299999     463136254 rows selected.

查询object_id=2的数据是走索引的

SQL> set timing on    --显示执行的时间
SQL> select * from tt2 where object_id = 2;32 rows selected.Elapsed: 00:00:00.01Execution Plan
----------------------------------------------------------
Plan hash value: 3665371926---------------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |    85 |  7650 |     6   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TT2     |    85 |  7650 |     6   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN      | IDX_TT2 |    85 |       |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=2)Statistics
----------------------------------------------------------14  recursive calls0  db block gets77  consistent gets    --逻辑读是77个块,效率很快0  physical reads0  redo size4575  bytes sent via SQL*Net to client546  bytes received via SQL*Net from client4  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)32  rows processed

查询object_id=99999,这次不走索引了,全表扫描了

SQL> select * from tt2 where object_id = 99999;463136 rows selected.Elapsed: 00:00:03.23Execution Plan
----------------------------------------------------------
Plan hash value: 1248358058--------------------------------------------------------------------------
| Id  | Operation     | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |  |   463K|    39M|  1675   (1)| 00:00:21 |
|*  1 |  TABLE ACCESS FULL| TT2  |   463K|    39M|  1675   (1)| 00:00:21 |
--------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("OBJECT_ID"=99999)Statistics
----------------------------------------------------------1  recursive calls    --有递归调用0  db block gets36694  consistent gets   --逻辑读很大,效率差0  physical reads0  redo size21500501  bytes sent via SQL*Net to client340149  bytes received via SQL*Net from client30877  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)463136  rows processed

加上注释强制走索引效率反而更差了,这是为啥?

SQL> select /*+ index(tt2 idx_tt2) */ * from tt2 where object_id = 99999;463136 rows selected.Elapsed: 00:00:03.68Execution Plan
----------------------------------------------------------
Plan hash value: 3665371926---------------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |   463K|    39M| 14946   (1)| 00:03:00 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TT2     |   463K|    39M| 14946   (1)| 00:03:00 |
|*  2 |   INDEX RANGE SCAN      | IDX_TT2 |   463K|       |   935   (1)| 00:00:12 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=99999)Statistics
----------------------------------------------------------1  recursive calls0  db block gets68408  consistent gets  --逻辑读很大,跟不走索引差了将近一倍0  physical reads0  redo size49712329  bytes sent via SQL*Net to client340149  bytes received via SQL*Net from client30877  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)463136  rows processed

说明索引效率不一定高,但是Oracle凭什么知道object_id=2的时候走索引效率高,object_id=99999不走索引效率高靠的就是直方图
删除直方图11g之前有一种办法就是在收集优化器统计信息的时候加上method_opt选项
这个size指定的就是bucket的数量,11g之前就是这种方法只收集列的basic优化器统计信息而不收集直方图

SQL> exec dbms_stats.gather_table_stats('sys','tt2',method_opt=>'for all columns size 1');PL/SQL procedure successfully completed.Elapsed: 00:00:00.31

没有直方图了

这时候object_id=2或者=99999的时候都走索引了,但是这不是我们希望看到的,出现这种错误就是因为没有了直方图

SQL> select * from tt2 where object_id = 2;32 rows selected.Elapsed: 00:00:00.00Execution Plan
----------------------------------------------------------
Plan hash value: 3665371926---------------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |  1855 |   163K|    63   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TT2     |  1855 |   163K|    63   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN      | IDX_TT2 |  1855 |       |     6   (0)| 00:00:01 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=2)Statistics
----------------------------------------------------------1  recursive calls0  db block gets42  consistent gets0  physical reads0  redo size4575  bytes sent via SQL*Net to client546  bytes received via SQL*Net from client4  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)32  rows processedSQL> select * from tt2 where object_id = 99999;463136 rows selected.Elapsed: 00:00:03.24Execution Plan
----------------------------------------------------------
Plan hash value: 3665371926---------------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |  1855 |   163K|    63   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TT2     |  1855 |   163K|    63   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN      | IDX_TT2 |  1855 |       |     6   (0)| 00:00:01 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=99999)Statistics
----------------------------------------------------------0  recursive calls0  db block gets36694  consistent gets0  physical reads0  redo size21500501  bytes sent via SQL*Net to client340149  bytes received via SQL*Net from client30877  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)463136  rows processed

重新收集统计信息

SQL> exec dbms_stats.gather_table_stats('sys','tt2');PL/SQL procedure successfully completed.Elapsed: 00:00:00.30

有直方图了

不走索引了

SQL> select * from tt2 where object_id = 99999;463136 rows selected.Elapsed: 00:00:03.19Execution Plan
----------------------------------------------------------
Plan hash value: 1248358058--------------------------------------------------------------------------
| Id  | Operation     | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |  |   462K|    39M|  1675   (1)| 00:00:21 |
|*  1 |  TABLE ACCESS FULL| TT2  |   462K|    39M|  1675   (1)| 00:00:21 |
--------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("OBJECT_ID"=99999)Statistics
----------------------------------------------------------0  recursive calls0  db block gets36694  consistent gets0  physical reads0  redo size21500501  bytes sent via SQL*Net to client340149  bytes received via SQL*Net from client30877  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)463136  rows processed

还有一种直方图叫HEIGHT BALANCED(高度均衡直方图)叫高度均衡的意思就是每一个bucket上的值都是差不多但是因为bucket数量可能不够用,那就有可能多个不同的值在一个bucket上,这种直方图的条件就是不同值的数量要超过254
下面的sql使得不同值的数量超过了bucket的最大值254

SQL> update tt4 set object_id=99999 where object_id >400;458496 rows updated.Elapsed: 00:00:05.86
SQL> commit;Commit complete.Elapsed: 00:00:00.01
SQL> exec dbms_stats.gather_table_stats('sys','tt4');PL/SQL procedure successfully completed.Elapsed: 00:00:00.35

有了高度直方图,如果没有高度直方图手机统计信息的时候就加上estimate_percent=>null参数,不要取样收集,全部收集

有了直方图之后无论是object_id=2还是=99999都走了正确的执行计划

SQL> select * from tt4 where object_id = 2;32 rows selected.Elapsed: 00:00:00.01Execution Plan
----------------------------------------------------------
Plan hash value: 2707091987---------------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |         |    28 |  2520 |     5   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TT4     |    28 |  2520 |     5   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN      | IDX_TT4 |    28 |       |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=2)Statistics
----------------------------------------------------------36  recursive calls0  db block gets96  consistent gets0  physical reads0  redo size4575  bytes sent via SQL*Net to client546  bytes received via SQL*Net from client4  SQL*Net roundtrips to/from client4  sorts (memory)0  sorts (disk)32  rows processedSQL> select * from tt4 where object_id = 99999;458496 rows selected.Elapsed: 00:00:03.22Execution Plan
----------------------------------------------------------
Plan hash value: 3980746492--------------------------------------------------------------------------
| Id  | Operation     | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |  |   459K|    39M|  1708   (1)| 00:00:21 |
|*  1 |  TABLE ACCESS FULL| TT4  |   459K|    39M|  1708   (1)| 00:00:21 |
--------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("OBJECT_ID"=99999)Statistics
----------------------------------------------------------1  recursive calls0  db block gets36374  consistent gets7  physical reads0  redo size21283052  bytes sent via SQL*Net to client336750  bytes received via SQL*Net from client30568  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)458496  rows processed

生成高度直方图的时候没有指定bucket的数量,这里Oracle一共用了8个桶,其中0号桶是一个特殊的桶
注意:频率直方图和高度直方图ENDPOINT_NUMBERENDPOINT_VALUE代表的意义不一样
ENDPOINT_NUMBER:桶的标号,0号桶上是这一列的最小值我们这里也就是2
ENDPOINT_VALUE:1号桶上放的是2-77之间的值(2,3,4等等到77),2号桶上就是77-125区间的值后面的以此类推1-6号桶保存的区间的值大概是相同的,但是254号桶放的值是不均衡的,频率直方图准确的反映出了百分比,而高度直方图比较模糊

指定bucket的数量

SQL> exec dbms_stats.gather_table_stats('sys','tt4',method_opt=>'for columns object_id size 254',estimate_percent=>null);PL/SQL procedure successfully completed.Elapsed: 00:00:00.54

指定了也没用

for all columns size2-254之间时Oracle会自己判断哪些列上需要统计直方图,1的时候就是不收集直方图

SQL> exec dbms_stats.gather_table_stats('sys','tt2',method_opt=>'for columns object_id size 1');PL/SQL procedure successfully completed.Elapsed: 00:00:00.23

SQL> exec dbms_stats.gather_table_stats('sys','tt2',method_opt=>'for columns object_id size 2');PL/SQL procedure successfully completed.Elapsed: 00:00:00.23


删除直方图:
11g之前:
要先把列的统计信息删除

SQL> exec dbms_stats.delete_column_stats('sys','tt2','object_id');PL/SQL procedure successfully completed.Elapsed: 00:00:00.02

然后再重新收集列的统计信息但是要加上for all columns size 1参数,显然要是表很大的话这种方式不好
11g开始:
收集一下直方图

SQL> exec dbms_stats.gather_table_stats('sys','tt2',method_opt=>'for columns object_id size 2');PL/SQL procedure successfully completed.Elapsed: 00:00:00.24

有了高度均衡的直方图

删除直方图,HISTOGRAM是只删除直方图,要是ALL就是删除直方图和列的统计信息

SQL> exec dbms_stats.delete_column_stats('sys','tt2',colname=>'object_id',col_stat_type=>'HISTOGRAM');PL/SQL procedure successfully completed.Elapsed: 00:00:00.00

已经没有了直方图
optimizer statistics手动收集有两种办法
1.8i之前:这个语句后面还可以加很多参数

SQL> select num_rows,blocks,empty_blocks,avg_row_len from dba_tables where table_name = 'TT2';NUM_ROWS     BLOCKS EMPTY_BLOCKS AVG_ROW_LEN
---------- ---------- ------------ -----------SQL> analyze table tt2 compute statistics;Table analyzed.SQL> select num_rows,blocks,empty_blocks,avg_row_len from dba_tables where table_name = 'TT2';NUM_ROWS     BLOCKS EMPTY_BLOCKS AVG_ROW_LEN
---------- ---------- ------------ -----------247104     3229       98      92

上面的blocks中不一定有数据,但是曾经一定存放过数据,其中empty_blocks是分配给这个对象但是从来没有用过的块,db_tables中的avg_space是平均每个块空闲了多少空间(单位:字节),一个8k的块不是都放满了默认预留了pct_free的空间为了防止比如varchar2这种长度可变的数据类型定义的varchar2(50)刚开始存了一个a,但是他后期可能updateaaaaaaaaa如果预留的空间也不够放update的数据这个时候要再占用另一个数据块也就是chain_cnt的个数,这种情况就是行链接或者行迁移,如果avg_row_len很大那么可能意味着这个表中有很多的字段并且每个字段定义的很宽,last_analyxzed最后一次分析的时间,sample_size取样数据的大小,analyzed的时候如果表很大就不会全部分析,要是表很小就会全部分析

8i开始就有一个包来分析统计信息(dbms_stats功能非常强大)
先删除之前使用analyzed收集的信息

SQL> exec dbms_stats.delete_table_stats('sys','tt2');PL/SQL procedure successfully completed.


可以收集table的统计信息

SQL> exec dbms_stats.gather_table_stats('sys','tt2');PL/SQL procedure successfully completed.


上图中的blocks叫做segment hwm(high water mark)段的高水位表示数据段中存放数据使用块的历史最大值,这个值越大不能说明数据越多因为使用delete的时候blocks不会变小但是数据行(num_rows)会变小,但是当访问一个表的时候如果这个表上没有索引走的是TABLE ACCESS FULL的时候,那就要把blocks上所有的块都扫描一遍这样就会大大影响性能
例子:

注意做实验的tt2表不要放在system表空间

先看一下目前有多少个空块,要在段头块的dump文件中看,在4号数据文件的130号块上是段头块

SQL> alter system dump datafile 4 block 130;System altered.
SQL> select spid from v$process2  where addr = (select paddr from v$session3  where sid = (select distinct sid from v$mystat));SPID
------------------------
2108

只粘贴一小部分

vim sales_ora_2108.trcExtent Control Header-----------------------------------------------------------------Extent Header:: spare1: 0      spare2: 0      #extents: 41     #blocks: 3328last map  0x00000000  #maps: 0      offset: 2716Highwater::  0x01000d62  ext#: 40     blk#: 98     ext size: 128#blocks in seg. hdr's freelists: 0#blocks below: 3298mapblk  0x00000000  offset: 40Unlocked--------------------------------------------------------Low HighWater Mark :Highwater::  0x01000d62  ext#: 40     blk#: 98     ext size: 128#blocks in seg. hdr's freelists: 0#blocks below: 3298mapblk  0x00000000  offset: 40Level 1 BMB for High HWM block: 0x01000d01Level 1 BMB for Low HWM block: 0x01000d01--------------------------------------------------------Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0L2 Array start offset:  0x00001434First Level 3 BMB:  0x00000000L2 Hint for inserts:  0x01000081Last Level 1 BMB:  0x01000d01Last Level II BMB:  0x01000081Last Level III BMB:  0x00000000Map Header:: next  0x00000000  #extents: 41   obj#: 16220  flag: 0x10000000Inc # 0Extent Map

在上面没有看到有多少个空块,那就是在Last Level 1(第一个块)和Last Level II(第二个块)中找(他们都是十六进制数)
转换成十进制数

SQL> select to_number('01000d01','xxxxxxxx') from dual;TO_NUMBER('01000D01','XXXXXXXX')
--------------------------------16780545SQL> select to_number('01000081','xxxxxxxx') from dual;TO_NUMBER('01000081','XXXXXXXX')
--------------------------------16777345

通过这两个块的十进制地址找到这两个块的数据文件和具体位置

SQL> select dbms_utility.data_block_address_file(16780545) from dual;DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16780545)
----------------------------------------------4SQL> select dbms_utility.data_block_address_block(16780545) from dual;DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16780545)
-----------------------------------------------3329SQL> select dbms_utility.data_block_address_file(16777345) from dual;DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16777345)
----------------------------------------------4SQL> select dbms_utility.data_block_address_block(16777345) from dual;DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16777345)
-----------------------------------------------129
SQL> alter system dump datafile 4 block 3329;System altered.

vim sales_ora_2108.trc,要的就是下面的这些信息

Start dump data blocks tsn: 4 file#:4 minblk 3329 maxblk 3329
中间省略。。。
Dump of First Level Bitmap Block--------------------------------nbits : 4 nranges: 1         parent dba:  0x01000081   poffset: 57unformatted: 30      total: 64        first useful block: 0owning instance : 1instance ownership changed atLast successful SearchFreeness Status:  nf1 0      nf2 0      nf3 0      nf4 0Extent Map Block Offset: 4294967295First free datablock : 34Bitmap block lock opcode 2Locker xid:     :  0x000a.01d.000001bcDealloc scn: 655408.0Flag: 0x00000001 (-/-/-/-/-/HWM)Inc #: 0 Objd: 16220HWM Flag: HWM SetHighwater::  0x01000d62  ext#: 40     blk#: 98     ext size: 128#blocks in seg. hdr's freelists: 0#blocks below: 3298mapblk  0x00000000  offset: 40--------------------------------------------------------DBA Ranges :--------------------------------------------------------0x01000d40  Length: 64     Offset: 0
--五种状态full(满的);25-50% free(百分只25到50是满的);50-75% free(百分之50到75是满的);75-100% free(百分之75到100是满的);unformatted(未定义)0:FULL   1:FULL   2:FULL   3:FULL4:FULL   5:FULL   6:FULL   7:FULL8:FULL   9:FULL   10:FULL   11:FULL12:FULL   13:FULL   14:FULL   15:FULL16:FULL   17:FULL   18:FULL   19:FULL20:FULL   21:FULL   22:FULL   23:FULL24:FULL   25:FULL   26:FULL   27:FULL28:FULL   29:FULL   30:FULL   31:FULL32:FULL   33:FULL   34:unformatted   35:unformatted36:unformatted   37:unformatted   38:unformatted   39:unformatted40:unformatted   41:unformatted   42:unformatted   43:unformatted44:unformatted   45:unformatted   46:unformatted   47:unformatted48:unformatted   49:unformatted   50:unformatted   51:unformatted52:unformatted   53:unformatted   54:unformatted   55:unformatted56:unformatted   57:unformatted   58:unformatted   59:unformatted60:unformatted   61:unformatted   62:unformatted   63:unformatted--------------------------------------------------------
End dump data blocks tsn: 4 file#: 4 minblk 3329 maxblk 3329

再看第二个块

SQL> alter system dump datafile 4 block 129;System altered.

vim sales_ora_2108.trc没有看到块使用情况的信息也就是说第一个块中记录了块的使用信息

 Start dump data blocks tsn: 4 file#:4 minblk 129 maxblk 129
中间省略。。。。--------------------------------------------------------
End dump data blocks tsn: 4 file#: 4 minblk 129 maxblk 129

现在tt2的优化器统计信息是

先删除一小部分数据,delete不会降低高水位线(blocks

SQL> delete from tt2 where object_id > 15000;11488 rows deleted.SQL> commit;Commit complete.

看一下统计信息

SQL> set autotrace traceonly exp stat
SQL> select count(1) from tt2; --不加where条件为的是把高水位下的块都找一遍Execution Plan
----------------------------------------------------------
Plan hash value: 1424956034-------------------------------------------------------------------
| Id  | Operation      | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 1 |   896   (1)| 00:00:11 |
|   1 |  SORT AGGREGATE    |      | 1 |        |      |
|   2 |   TABLE ACCESS FULL| TT2  |   247K|   896   (1)| 00:00:11 |
-------------------------------------------------------------------Statistics
----------------------------------------------------------1  recursive calls0  db block gets3244  consistent gets  --发生了3244次逻辑读--逻辑读:从内存中访问的块的次数,一个块访问一千次逻辑读是1,每个块访问一次访问一千个块,逻辑读也是10  physical reads --没有物理读说明我们给的sga足够大,所以分给data buffer cache的空间也足够大--物理读:把一个块从磁盘上读到内存中来,一次有可能读一个或多个块0  redo size528  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed


重新收集一下统计信息

SQL> exec dbms_stats.gather_table_stats('sys','tt2');PL/SQL procedure successfully completed.

num_rows变了,blocks没有变

统计信息变化的不明显是因为我们的机器性能还是算是ok,数据量太小,没有变化

SQL> select count(1) from tt2;Execution Plan
----------------------------------------------------------
Plan hash value: 1424956034-------------------------------------------------------------------
| Id  | Operation      | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 1 |   896   (1)| 00:00:11 |
|   1 |  SORT AGGREGATE    |      | 1 |        |      |
|   2 |   TABLE ACCESS FULL| TT2  |   235K|   896   (1)| 00:00:11 |
-------------------------------------------------------------------Statistics
----------------------------------------------------------0  recursive calls0  db block gets3244  consistent gets0  physical reads0  redo size528  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

下面降低高水位也就是dba_tables中的blocks,其实就是整理这个表中的数据段,最古老的办法就是exp/imp导入导出,这种方法太粗放
2.move(表空间变化,数据文件变化,物理位置变化,rowid变化)

SQL> alter table tt2 move tablespace xiha;Table altered.

但是这种方法会使表上的index失效,这是因为index中有rowid,现在rowid变化了

重新收集统计信息(不收集index上的统计信息)

SQL> exec dbms_stats.gather_table_stats('sys','tt2',cascade=>false);PL/SQL procedure successfully completed.

现在blocks就变小了,空块被释放了
看逻辑读也变小了

SQL> set autotrace traceonly exp stat
SQL> select count(1) from tt2;Execution Plan
----------------------------------------------------------
Plan hash value: 1424956034-------------------------------------------------------------------
| Id  | Operation      | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 1 |   564   (1)| 00:00:07 |
|   1 |  SORT AGGREGATE    |      | 1 |        |      |
|   2 |   TABLE ACCESS FULL| TT2  |   156K|   564   (1)| 00:00:07 |
-------------------------------------------------------------------Statistics
----------------------------------------------------------25  recursive calls  --因为刚刚执行了DDL命令(move),所以优化器统计信息也老化了,Oracle在执行sql的时候进行了重新解析所以这里有递归调用,递归调用是解析sql的时候要进行系统资源的消耗,比如查看数据字典有没有这个对象,有没有权限等0  db block gets2054  consistent gets  --在内存中访问了多少块0  physical reads116  redo size528  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client4  sorts (memory)0  sorts (disk)1  rows processed

在执行一次就没有recursive calls(递归调用)了

SQL> select count(1) from tt2;Execution Plan
----------------------------------------------------------
Plan hash value: 1424956034-------------------------------------------------------------------
| Id  | Operation      | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 1 |   564   (1)| 00:00:07 |
|   1 |  SORT AGGREGATE    |      | 1 |        |      |
|   2 |   TABLE ACCESS FULL| TT2  |   156K|   564   (1)| 00:00:07 |
-------------------------------------------------------------------Statistics
----------------------------------------------------------0  recursive calls0  db block gets2037  consistent gets0  physical reads0  redo size528  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

现在重建index
这种方式比drop之后create要快一点因为已经有了idx_tt2这个段,建索引加锁会阻塞DML操作,加上online参数不会阻塞DML操作,建议避免在业务高峰期加索引

SQL> alter index idx_tt2 rebuild online;Index altered.


总结:所以要在频繁删除而又没有及时插入的表想办法降低他的高水位

段的管理方式
assm:auto segment space managment
mssm:manual segment space managment
区的管理方式
local management tablespace
dictionary management tablespace
http://www.itpub.net/thread-909312-1-1.html中的LMT就是local,DMT就是dictionary

10G开始:
3.shrink(收缩),有条件:dba_segments中的segment_subtype必须是ASSMshrink的原理就是delete然后insert,在大表中操作的时候要注意undo表空间够不够大

实验:
删除一部分数据肯定又产生了空块

SQL> select count(1) from tt2;COUNT(1)
----------494272SQL> delete from tt2 where object_id > 15000;23040 rows deleted.SQL> commit;Commit complete.

现在高水位线(blocks)是6556

下面报错是因为在创建表的时候在元数据中是有记录的

SQL> alter table tt2 shrink space;
alter table tt2 shrink space
*
ERROR at line 1:
ORA-10636: ROW MOVEMENT is not enabled

默认情况下行移动是disabled的,disabled的意思是数据段中的数据在磁盘上没有特殊情况不能移动除非是删除,也就是一旦放在哪个地方就不能动了,因为变化了rowid就变化了为了防止index失效所以在元数据中标识不能行移动

激活行移动

SQL> alter table tt2 enable row movement;Table altered.


因为上面说的shrink原理是DML操作,DML操作会维护index

SQL> alter table tt2 shrink space;Table altered.

index没有失效

重新收集一下优化器统计信息

SQL> exec dbms_stats.gather_table_stats('sys','tt2');PL/SQL procedure successfully completed.

blocks降下来了

之前的实验都是全表扫描为的是访问所有块验证高水位
要是走index呢,下面的性能非常好,没有物理读,逻辑读是19也就是在内存中访问了19个块就结束了

SQL> set autotrace traceonly exp stat
SQL> select count(1) from tt2 where object_id = 2;Execution Plan
----------------------------------------------------------
Plan hash value: 1151720287-----------------------------------------------------------------------------
| Id  | Operation     | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |     |     1 |     5 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |     |     1 |     5 |        |      |
|*  2 |   INDEX RANGE SCAN| IDX_TT2 |    32 |   160 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("OBJECT_ID"=2)Statistics
----------------------------------------------------------22  recursive calls0  db block gets19  consistent gets0  physical reads0  redo size526  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client4  sorts (memory)0  sorts (disk)1  rows processed

Oracle在生成执行计划的时候依赖统计信息比如dba_tables中的num_rows、blocks、avg_row_len
下面通过实验验证手动修改了优化器统计信息之后对执行计划的影响
手动修改之前正确的执行计划是先走索引再走表

SQL> select count(object_name) from tt2 where object_id = 2;Execution Plan
----------------------------------------------------------
Plan hash value: 3949934342----------------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |         |     1 |    25 |    35   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE          |         |     1 |    25 |        |          |
|   2 |   TABLE ACCESS BY INDEX ROWID| TT2     |    32 |   800 |    35   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN      | IDX_TT2 |    32 |       |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------3 - access("OBJECT_ID"=2)Statistics
----------------------------------------------------------2  recursive calls0  db block gets38  consistent gets0  physical reads0  redo size536  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

手动修改优化器统计信息

SQL> exec dbms_stats.set_table_stats('sys','tt2',numrows=>10);PL/SQL procedure successfully completed.SQL> exec dbms_stats.set_table_stats('sys','tt2',numblks=>10);PL/SQL procedure successfully completed.

已经修改了

这个时候再看执行计划,因为他依赖统计信息,所以他以为这个表很小没有必要走index,所有产生了错误的执行计划

SQL> select count(object_name) from tt2 where object_id = 2;Execution Plan
----------------------------------------------------------
Plan hash value: 1424956034---------------------------------------------------------------------------
| Id  | Operation      | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      | 1 |    25 | 4   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |      | 1 |    25 |        |      |
|*  2 |   TABLE ACCESS FULL| TT2  | 1 |    25 | 4   (0)| 00:00:01 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - filter("OBJECT_ID"=2)Statistics
----------------------------------------------------------1  recursive calls0  db block gets39  consistent gets0  physical reads0  redo size536  bytes sent via SQL*Net to client524  bytes received via SQL*Net from client2  SQL*Net roundtrips to/from client0  sorts (memory)0  sorts (disk)1  rows processed

注意:上面的执行计划都是估算的

优化器统计信息_高水位_柱状图等相关推荐

  1. Oracle 12c数据库优化器统计信息收集的最佳实践

    Oracle 12c数据库优化器统计信息收集的最佳实践 转载自     沃趣科技(ID:woqutech) 作者         刘金龙(译) 原文链接   http://www.oracle.com ...

  2. oracle优化器统计信息相关

    优化器使用统计信息来生成每个sql语句最优的执行计划.准确的统计信息对于数据库的效率至关重要. dba和程序开发人员都应该了解一些统计信息相关知识,这可以使你更好的理解为什么会生成一个你看到的执行计划 ...

  3. mysql 8 配置参数优化_mysql8 参考手册--配置非持久性优化器统计参数

    本节介绍如何配置非持久性优化器统计信息.当innodb_stats_persistent=OFF或使用创建或更改单个表时,Optimizer统计信息不会保留在磁盘 上 STATS_PERSISTENT ...

  4. oracle stalestats_深入理解oracle优化器统计数据(Optimizer Statistics)

    理解oracle优化器统计数据 首先来介绍oracle数据库使用基于规则优化器(RBO)来决定如何执行一个sql语句.基于规则优化器顾名思义,它是遵循一组规则来判断一个sql语句的执行计划.这组规则是 ...

  5. 堪比N6705和Power Monitor AAA10F 的高精度_高采样率_低功耗测试电源mPower1203

    堪比N6705和Power Monitor AAA10F 的高精度_高采样率_低功耗测试电源mPower1203 提到低功耗测试,可穿戴设备则是首屈一指的硬需求.可穿戴设备市场出货量的年年增加,智能手 ...

  6. mysql降低高水位_[数据库]数据高水位分析

    [数据库]数据高水位分析 0 2014-10-16 11:02:12 2014-10-04 BaoXinjian 一.摘要 PLSQL_性能优化系列14_Oracle High Water Level ...

  7. oracle 抽样_oracle优化手段--统计信息导出和抽样提取数据

    11月份参加了Oracle嘉年华,分享心得一则: 我们经常会遇到这样的情况,生产环境一段SQL非常慢,而我们又没有生产的操作权限,这时候怎么办? 很多时候我们会选择在测试环境进行测试,但由于环境的不同 ...

  8. springcloud工作笔记096---springboot集成多线程_高并发_集成线程池的使用

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 在实际应用中有可能会用到,但是至今用到的还不多 在我们现实开发中肯定会遇到需要延时请求并且高并发的 ...

  9. Mycat高可用架构原理_Mycat集群搭建_HA高可用集群_高可用_单表存储千万级_海量存储_分表扩展---MyCat分布式数据库集群架构工作笔记0027

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 前面我们已经讲了,对于数据库来说,mycat可以,我们通过搭建一主一从,双主双从,来实现数据库集群 ...

最新文章

  1. 矢量合成和分解的法则_重点解析丨抛体运动 之 运动的合成与分解
  2. Python清屏小结
  3. IOS之Xcode之快捷键
  4. IP地址与MAC地址的区别
  5. GetSystemInfo()
  6. 网络安全习惯_健康习惯,确保良好的网络安全
  7. Java笔记-使用System.gc()进行内存回收
  8. web页面如何实现点击按钮进行手机拨号?
  9. sequelize怎么看插入的数据成功不成功_MySQL的4种事务隔离级别你还不清楚吗?
  10. 安装linux系统收费标准,LINUX操作系统安装标准规范.doc
  11. faster rcnn论文_【论文解读】精读Faster RCNN
  12. 深度学习之Ubuntu下安装caffe和TensorFlow的cpu版本
  13. mysql数据上传apache_配置Apache服务器 数据库mySQL
  14. linux终端中文方块,如何解决在Linux CLI终端界面中汉字方块乱码
  15. Python3 用turtle库学画画——(一)美国队长盾牌
  16. 穿孔发光字/外露发光字制作流程步骤
  17. 5星|戴蒙德《为什么有的国家富裕,有的国家贫穷》:为什么有的国家能发展出好制度...
  18. nrf51822 52832学习汇总
  19. 周鸿祎产品秘笈:小版本成就大产品
  20. RabbitMQ五种工作模式

热门文章

  1. Matlab 命令大全
  2. 活着感悟,加一堆各种想像
  3. TP-Link路由器桥接断电后无法重连问题分析与解决分享
  4. smo算法C语言,SMO算法详解
  5. 关于单片机位数的思考(8位、16位、32位)
  6. Vue-脚手架初始化电商后台
  7. 华蓥计算机培训机构,华蓥考研专业课培训班
  8. 青软产业项目集:基于金融建模的衍生品分析及量化投资分析项目
  9. 01背包问题详解(浅显易懂)
  10. 一门课程双开播放_因此,您已经注册了另一门在线课程-如何充分利用它?