Oracle CBO优化模式中的5种索引访问方法浅析

本文主要讨论以下几种索引访问方法:

1.索引唯一扫描(INDEX UNIQUE SCAN)
2.索引范围扫描(INDEX RANGE SCAN)
3.索引全扫描(INDEX FULL SCAN)
4.索引跳跃扫描(INDEX SKIP SCAN)
5.索引快速全扫描(INDEX FAST FULL SCAN)

索引唯一扫描(INDEX UNIQUE SCAN)

通过这种索引访问数据的特点是对于某个特定的值只返回一行数据,通常如果在查询谓语中使用UNIQE和PRIMARY KEY索引的列作为条件的时候会选用这种扫描;访问的高度总是索引的高度加一,除了某些特殊的情况,如另外存储的LOB对象。

代码如下:

SQL> set autotrace traceonly explain
SQL> select * from hr.employees where employee_id = 100;

Execution Plan
----------------------------------------------------------
Plan hash value: 1833546154

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |    69 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES     |     1 |    69 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | EMP_EMP_ID_PK |     1 |       |     0   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("EMPLOYEE_ID"=100)

索引范围扫描(INDEX RANGE SCAN)

谓语中包含将会返回一定范围数据的条件时就会选用索引范围扫描,索引可以是唯一的亦可以是不唯一的;所指定的条件可以是(<,>,LIKE,BETWEEN,=)等运算符,不过使用LIKE的时候,如果使用了通配符%,极有可能就不会使用范围扫描,因为条件过于的宽泛了,下面是一个示例:

代码如下:

SQL> select * from hr.employees where DEPARTMENT_ID = 30;

6 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 2056577954

-------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                   |     6 |   414 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |     6 |   414 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |     6 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("DEPARTMENT_ID"=30)

Statistics
----------------------------------------------------------
          8  recursive calls
          0  db block gets
          7  consistent gets
          1  physical reads
          0  redo size
       1716  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          6  rows processed

范围扫描的条件需要准确的分析返回数据的数目,范围越大就越可能执行全表扫描;

代码如下:

SQL> select department_id,count(*) from hr.employees group by department_id order by count(*);

DEPARTMENT_ID   COUNT(*)
------------- ----------
           10          1
           40          1
                       1
           70          1
           20          2
          110          2
           90          3
           60          5
           30          6
          100          6
           80         34
           50         45

12 rows selected.

-- 这里使用数值最多的50来执行范围扫描
SQL> set autotrace traceonly explain
SQL> select * from hr.employees where DEPARTMENT_ID = 50;

45 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 1445457117

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    45 |  3105 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMPLOYEES |    45 |  3105 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("DEPARTMENT_ID"=50)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         10  consistent gets
          0  physical reads
          0  redo size
       4733  bytes sent via SQL*Net to client
        545  bytes received via SQL*Net from client
          4  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         45  rows processed

可以看到在获取范围数据较大的时候,优化器还是执行了全表扫描方法。

一种对于索引范围扫描的优化方法是使用升序排列的索引来获得降序排列的数据行,这种情况多发生在查询中包含有索引列上的ORDER BY子句的时候,这样就可避免一次排序操作了,如下:

代码如下:

SQL> set autotrace traceonly explain
SQL> select * from hr.employees
  2  where department_id in (90, 100)
  3  order by department_id desc;

Execution Plan
----------------------------------------------------------
Plan hash value: 3707994525

---------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                   |     9 |   621 |     2   (0)| 00:00:01 |
|   1 |  INLIST ITERATOR              |                   |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID | EMPLOYEES         |     9 |   621 |     2   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN DESCENDING| EMP_DEPARTMENT_IX |     9 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("DEPARTMENT_ID"=90 OR "DEPARTMENT_ID"=100)

上例中,索引条目被相反的顺序读取,避免了排序操作。

索引全扫描(INDEX FULL SCAN)

索引全扫描的操作将会扫描索引结构的每一个叶子块,读取每个条目的的行编号,并取出数据行,既然是访问每一个索引叶子块,那么它相对的全表扫描的优势在哪里呢?实际上在索引块中因为包含的信息列数较少,通常都是索引键和ROWID,所以对于同一个数据块和索引块,包含的索引键的条目数通常都是索引块中居多,因此如果查询字段列表中所有字段都是索引的一部分的时候,就可以完全跳过对表数据的访问了,这种情况索引全扫描的方法会获得更高的效率。

发生索引全扫描的情况有很多,几种典型的场景:

1,查询总缺少谓语,但获取的列可以通过索引直接获得

代码如下:

SQL> select email from hr.employees;

Execution Plan
----------------------------------------------------------
Plan hash value: 2196514524

---------------------------------------------------------------------------------
| Id  | Operation        | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |              |   107 |   856 |     1   (0)| 00:00:01 |
|   1 |  INDEX FULL SCAN | EMP_EMAIL_UK |   107 |   856 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------

2,查询谓语中包含一个位于索引中非引导列上的条件(其实也取决于引导列值的基数大小,如果引导列的唯一值较少,也可能出现跳跃扫描的情况)

代码如下:

SQL> select first_name, last_name from hr.employees
  2  where first_name like 'A%' ;

Execution Plan
----------------------------------------------------------
Plan hash value: 2228653197

--------------------------------------------------------------------------------
| Id  | Operation        | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |             |     3 |    45 |     1   (0)| 00:00:01 |
|*  1 |  INDEX FULL SCAN | EMP_NAME_IX |     3 |    45 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("FIRST_NAME" LIKE 'A%')
       filter("FIRST_NAME" LIKE 'A%')

SQL> SET LONG 2000000
SQL> select dbms_metadata.get_ddl('INDEX','EMP_NAME_IX','HR') from dual;

DBMS_METADATA.GET_DDL('INDEX','EMP_NAME_IX','HR')
--------------------------------------------------------------------------------

CREATE INDEX "HR"."EMP_NAME_IX" ON "HR"."EMPLOYEES" ("LAST_NAME", "FIRST_NAME"
)
  PCTFREE 10 INITRANS 2 MAXTRANS 255 NOLOGGING COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DE
FAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "EXAMPLE"
-- 可以看到EMP_NAME_IX索引是建立在列(("LAST_NAME", "FIRST_NAME")上的,使用了带非引导列FIRST_NAME的谓语

3,数据通过一个已经排序的索引获得从而省去单独的排序操作

代码如下:

SQL> select * from hr.employees order by employee_id ;

Execution Plan
----------------------------------------------------------
Plan hash value: 2186312383

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |   107 |  7383 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES     |   107 |  7383 |     3   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN           | EMP_EMP_ID_PK |   107 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

-- 同样可以使用升序索引返回降序数据
SQL> select employee_id from hr.employees order by employee_id desc ;

Execution Plan
----------------------------------------------------------
Plan hash value: 753568220

--------------------------------------------------------------------------------------------
| Id  | Operation                  | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |               |   107 |   428 |     1   (0)| 00:00:01 |
|   1 |  INDEX FULL SCAN DESCENDING| EMP_EMP_ID_PK |   107 |   428 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

在上面的例子中可以看出,索引全扫描也可以想范围扫描一样,通过升序索引返回降序数据,而它的优化不止这一种,当我们查询某一列的最大值或最小值而这一列又是索引列的时候,索引全扫描就会获得非常显著的优势,因为这时的优化器并没有对索引的数据进行全部叶子节点的检索,而只是对一个根块,第一个或最后一个叶子块的扫描,这无疑会显著的提高性能!!

代码如下:

-- 索引全扫描获得最小值
SQL> select min(department_id) from hr.employees ;

Execution Plan
----------------------------------------------------------
Plan hash value: 613773769

------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                   |     1 |     3 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE            |                   |     1 |     3 |            |          |
|   2 |   INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX |     1 |     3 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------

-- 如果同时包含MAX和MIN的求值,优化器并不会主动选择效率较高的索引全扫描方法
SQL> select min(department_id), max(department_id) from hr.employees ;

Execution Plan
----------------------------------------------------------
Plan hash value: 1756381138

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |     3 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |           |     1 |     3 |            |          |
|   2 |   TABLE ACCESS FULL| EMPLOYEES |   107 |   321 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------
-- 一种替代的优化方案
SQL> select
  2  (select min(department_id) from hr.employees) min_id,
  3  (select max(department_id) from hr.employees) max_id
  4  from dual;

Execution Plan
----------------------------------------------------------
Plan hash value: 2189307159

------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                   |     1 |       |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE            |                   |     1 |     3 |            |          |
|   2 |   INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX |     1 |     3 |     1   (0)| 00:00:01 |
|   3 |  SORT AGGREGATE            |                   |     1 |     3 |            |          |
|   4 |   INDEX FULL SCAN (MIN/MAX)| EMP_DEPARTMENT_IX |     1 |     3 |     1   (0)| 00:00:01 |
|   5 |  FAST DUAL                 |                   |     1 |       |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------

索引跳跃扫描(INDEX SKIP SCAN)

这种扫描方式也是一种特例,因为在早期的版本中,优化器会因为使用了非引导列而拒绝使用索引。跳跃扫描的前提有着对应的情景,当谓语中包含索引中非引导列上的条件,并且引导列的唯一值较小的时候,就有极有可能使用索引跳跃扫描方法;同索引全扫描,范围扫描一样,它也可以升序或降序的访问索引;不同的是跳跃扫描会根据引导列的唯一值数目将复合索引分成多个较小的逻辑子索引,引导列的唯一值数目越小,分割的子索引数目也就越少,就越可能达到相对全表扫描较高的运算效率。

代码如下:

-- 创建测试表,以dba_objects表为例
SQL> create table test as select * from dba_objects;

Table created.

-- 创建一个复合索引,这里选取了一个唯一值较少的owner列作为引导列
SQL> create index i_test on test(owner,object_id,object_type) ;

Index created.

-- 分析表收集统计信息
SQL> exec dbms_stats.gather_table_stats('SYS','TEST');

PL/SQL procedure successfully completed.

-- 先看一下引导列的唯一值的比较
SQL> select count(*),count(distinct owner) from test;

COUNT(*) COUNT(DISTINCTOWNER)
---------- --------------------
     72482                   29

-- 使用非引导列的条件查询来访问触发SKIP SCAN
SQL> select * from test where object_id = 46;

Execution Plan
----------------------------------------------------------
Plan hash value: 1001786056

--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    97 |    31   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST   |     1 |    97 |    31   (0)| 00:00:01 |
|*  2 |   INDEX SKIP SCAN           | I_TEST |     1 |       |    30   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

2 - access("OBJECT_ID"=46)
       filter("OBJECT_ID"=46)

Statistics
----------------------------------------------------------
        101  recursive calls
          0  db block gets
         38  consistent gets
          0  physical reads
          0  redo size
       1610  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          3  sorts (memory)
          0  sorts (disk)
          1  rows processed

-- 来看看这条语句全扫描的效率
SQL> select /*+ full(test) */ * from test where object_id = 46;

Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    97 |   282   (1)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| TEST |     1 |    97 |   282   (1)| 00:00:04 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("OBJECT_ID"=46)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1037  consistent gets
          0  physical reads
          0  redo size
       1607  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

分析上面的查询可以看出,我们使用的索引中引导列有29个唯一值,也就是说在执行索引跳跃扫描的时候,分割成了29个逻辑子索引来查询,只产生了38次逻辑读;而相对全表扫描的1037次逻辑读,性能提升非常明显!

索引快速全扫描(INDEX FAST FULL SCAN)

这种访问方法在获取数据上和全表扫描相同,都是通过无序的多块读取来进行的,因此也就无法使用它来避免排序代价了;索引快速全扫描通常发生在查询列都在索引中并且索引中一列有非空约束时,当然这个条件也容易发生索引全扫描,它的存在多可用来代替全表扫描,比较数据获取不需要访问表上的数据块。

代码如下:

-- 依旧使用上面创建的test表
SQL> desc test
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OWNER                                              VARCHAR2(30)
 OBJECT_NAME                                        VARCHAR2(128)
 SUBOBJECT_NAME                                     VARCHAR2(30)
 OBJECT_ID                                 NOT NULL NUMBER
 DATA_OBJECT_ID                                     NUMBER
 OBJECT_TYPE                                        VARCHAR2(19)
 CREATED                                            DATE
 LAST_DDL_TIME                                      DATE
 TIMESTAMP                                          VARCHAR2(19)
 STATUS                                             VARCHAR2(7)
 TEMPORARY                                          VARCHAR2(1)
 GENERATED                                          VARCHAR2(1)
 SECONDARY                                          VARCHAR2(1)
 NAMESPACE                                          NUMBER
 EDITION_NAME                                       VARCHAR2(30)

-- 在object_id列上创建索引
SQL> create index pri_inx on test (object_id);

Index created.

-- 直接执行全表扫描
SQL> select object_id from test;

72482 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 72482 |   353K|   282   (1)| 00:00:04 |
|   1 |  TABLE ACCESS FULL| TEST | 72482 |   353K|   282   (1)| 00:00:04 |
--------------------------------------------------------------------------

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       5799  consistent gets
          0  physical reads
          0  redo size
    1323739  bytes sent via SQL*Net to client
      53675  bytes received via SQL*Net from client
       4834  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      72482  rows processed

-- 修改object_id为not null
SQL> alter table test modify (object_id not null);

Table altered.

-- 再次使用object_id列查询就可以看到使用了快速全扫描了
SQL> select object_id from test;

72482 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 3806735285

--------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |         | 72482 |   353K|    45   (0)| 00:00:01 |
|   1 |  INDEX FAST FULL SCAN| PRI_INX | 72482 |   353K|    45   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
        167  recursive calls
          0  db block gets
       5020  consistent gets
        161  physical reads
          0  redo size
    1323739  bytes sent via SQL*Net to client
      53675  bytes received via SQL*Net from client
       4834  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
      72482  rows processed

PS,这个INDEX FAST FULL SCAN的例子真是不好模拟,上面的例子弄了好久。。。。。

(0)

相关推荐

  • oracle 索引的相关介绍(创建、简介、技巧、怎样查看) .

    一.索引简介 1.索引相当于目录 2.索引是通过一组排序后的索引键来取代默认的全表扫描检索方式,从而提高检索效率. 3.索引的创建要适度,多了会影响增删改的效率,少了会影响查询的效率,索引最好创建在取值分散的列上,避免对同一张表创建过多的索引 4.索引的使用对用户来说是透明的,由系统来决定什么时候使用索引. 5.Oracle支持多种类型的索引,可以按列的多少.索引值是否唯一和索引数据的组织形式对索引进行分类,以满足各种表和查询条件的要求.(请见附件) a. 单列索引和复合索引 b.B树索引(cr

  • oracle分区索引的失效和重建代码示例

    上一篇文章中我们了解了oracle普通表转化为分区表的方法的相关内容,接下来的这篇文章,我们将探讨oracle分区索引的失效和重建问题,提供了相关代码示例供大家参考,具体如下. --创建测试表 SQL> create table t as select object_id,object_name from dba_objects; 表已创建. SQL> select min(object_id),max(object_id) from t; MIN(OBJECT_ID) MAX(OBJECT_

  • Oracle外键不加索引引起死锁示例

    --创建一个表,此表作为子表 create table fk_t as select *from user_objects; delete from fk_t where object_id is null; commit; --创建一个表,此表作为父表 create table pk_t as select *from user_objects; delete from pk_t where object_id is null; commit; --创建父表的主键 alter table PK

  • Oracle CBO优化模式中的5种索引访问方法浅析

    本文主要讨论以下几种索引访问方法: 1.索引唯一扫描(INDEX UNIQUE SCAN) 2.索引范围扫描(INDEX RANGE SCAN) 3.索引全扫描(INDEX FULL SCAN) 4.索引跳跃扫描(INDEX SKIP SCAN) 5.索引快速全扫描(INDEX FAST FULL SCAN) 索引唯一扫描(INDEX UNIQUE SCAN) 通过这种索引访问数据的特点是对于某个特定的值只返回一行数据,通常如果在查询谓语中使用UNIQE和PRIMARY KEY索引的列作为条件的

  • 详解JavaScript中的4种类型识别方法

    具体内容如下: 1.typeof [输出]首字母小写的字符串形式 [功能] [a]可以识别标准类型(将Null识别为object) [b]不能识别具体的对象类型(Function除外) [实例] console.log(typeof "jerry");//"string" console.log(typeof 12);//"number" console.log(typeof true);//"boolean" console

  • JS中的四种数据类型判断方法

    目录 1.typeof 2.instanceof 3.constructor 4.toString() 本文总结了四种判断方法: 1.typeof typeof是一个运算符,其有两种使用方式:(1)typeof(表达式); (2)typeof 变量名;返回值是一个字符串,用来说明变量的数据类型;所以可以用此来判断number, string, object, boolean, function, undefined, symbol 这七种类型,每种情况返回的内容如下表所示: // 字符串 con

  •  分享Python 中的 7 种交叉验证方法

    目录 一.什么是交叉验证? 二.它是如何解决过拟合问题的? 1.HoldOut交叉验证 2.K折交叉验证 3.分层K折交叉验证 4.LeavePOut交叉验证 5.留一交叉验证 6.蒙特卡罗交叉验证(ShuffleSplit) 7.时间序列交叉验证 在任何有监督机器学习项目的模型构建阶段,我们训练模型的目的是从标记的示例中学习所有权重和偏差的最佳值. 如果我们使用相同的标记示例来测试我们的模型,那么这将是一个方法论错误,因为一个只会重复刚刚看到的样本标签的模型将获得完美的分数,但无法预测任何有用

  • pd.DataFrame中的几种索引变换的实现

    目录 01 索引简介与样例数据 02 reindex和rename 03 index.map 04 set_index与reset_index 05 stack与unstack 导读:pandas中最常用的数据结构是DataFrame,而DataFrame相较于嵌套list或者二维numpy数组更好用的原因之一在于其提供了行索引和列名.本文主要介绍行索引的几种变换方式,包括rename与reindex.index.map.set_index与reset_index.stack与unstack等.

  • R语言中的五种常用统计分析方法

    1.分组分析aggregation 根据分组字段,将分析对象划分为不同的部分,以进行对比分析各组之间差异性的一种分析方法. 常用统计指标: 计数 length 求和 sum 平均值 mean 标准差 var 方差 sd 分组统计函数 aggregate(分组表达式,data=需要分组的数据框,function=统计函数) 参数说明 formula:分组表达式,格式:统计列~分组列1+分组列2+... data=需要分组的数据框 function:统计函数 aggregate(name ~ cla

  • javascript中的3种继承实现方法

    使用Object.create实现类式继承 下面是官网的一个例子 //Shape - superclass function Shape() { this.x = 0; this.y = 0; } Shape.prototype.move = function(x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() {

  • Java中的2种集合排序方法介绍

    直接上代码: import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * * <p> * ClassName CollectionsSort * </p> * <p> * Description 主要介绍两种集合的排序算法<br/> * 第一:java.util.Collections.s

  • JavaScript 中的12种循环遍历方法【总结】

    1.for 循环 let arr = [1,2,3]; for (let i=0; i<arr.length; i++){ console.log(i,arr[i]) } // 0 1 // 1 2 // 2 3 for 循环是 Js 中最常用的一个循环工具,经常用于数组的循环遍历. 2.for in 循环 let obj = {name:'zhou',age:'**'} for(let i in obj){ console.log(i,obj[i]) } // name zhou // age

  • Python OOP类中的几种函数或方法总结

    概述 实例方法 使用实例调用时,默认传递实例本身到实例方法的第一个参数self 使用类调用时,必须传递一个实例对象到实例方法的第一个参数 静态方法 使用实例调用和类调用效果相同; 类方法 装饰器版: 使用实例调用和类调用效果相同; classmethod(function)版: 在类中,尽量不要使用classmethod(function)实现类方法,会将其当做实例方法使用; 使用实例调用时,会默认传递实例本身到函数的第一个参数,如果函数的参数个数为0,则报错; 如果必须这样做,就使用类调用.

随机推荐