`
修补匠
  • 浏览: 8974 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

SQL要怎么写才会调用到复合索引和分区

阅读更多

本文讨论复合索引以及分区的简单使用,也即是SQL语句要如何写才会调用到复合索引以及分区。在此只作为新手交流。

 

Titles表的设计:

 

CREATE TABLE `titles` (
  `emp_no` int(11) NOT NULL,
  `title` varchar(50) NOT NULL,
  `from_date` date NOT NULL,
  `to_date` date DEFAULT NULL,
  PRIMARY KEY (`emp_no`,`title`,`from_date`),
  KEY `emp_no` (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
 PARTITION BY RANGE (to_days(from_date))(
 PARTITION p01 VALUES LESS THAN (725371) ENGINE = InnoDB,
 PARTITION p02 VALUES LESS THAN (725736) ENGINE = InnoDB,
 PARTITION p03 VALUES LESS THAN (726101) ENGINE = InnoDB,
 PARTITION p04 VALUES LESS THAN (726467) ENGINE = InnoDB,
 PARTITION p05 VALUES LESS THAN (726832) ENGINE = InnoDB,
 PARTITION p06 VALUES LESS THAN (727197) ENGINE = InnoDB,
 PARTITION p07 VALUES LESS THAN (727562) ENGINE = InnoDB,
 PARTITION p08 VALUES LESS THAN (727928) ENGINE = InnoDB,
 PARTITION p09 VALUES LESS THAN (728293) ENGINE = InnoDB,
 PARTITION p10 VALUES LESS THAN (728658) ENGINE = InnoDB,
 PARTITION p11 VALUES LESS THAN (729023) ENGINE = InnoDB,
 PARTITION p12 VALUES LESS THAN (729389) ENGINE = InnoDB,
 PARTITION p13 VALUES LESS THAN (729754) ENGINE = InnoDB,
 PARTITION p14 VALUES LESS THAN (730119) ENGINE = InnoDB,
 PARTITION p15 VALUES LESS THAN (730484) ENGINE = InnoDB,
 PARTITION p16 VALUES LESS THAN (730850) ENGINE = InnoDB,
 PARTITION p17 VALUES LESS THAN (731215) ENGINE = InnoDB,
 PARTITION p18 VALUES LESS THAN (731580) ENGINE = InnoDB,
 PARTITION p19 VALUES LESS THAN (1096092) ENGINE = InnoDB)

 

从该表的定义上可以看到,有两个索引:(`emp_no`,`title`,`from_date`)主键索引(复合索引)和`emp_no`索引(单列索引)。还按照to_days(from_date)做了range分区。

 

先来了解下该表所拥有的数据量(44万):



 

一、复合索引的使用

 

这里就不讨论什么是索引,以及索引有什么好处之类的,就只说明SQL语句要怎么写才会调用到复合索引。

 

1.       什么情况下会调用到主键索引(复合索引

 

从表设计中可以看到主键索引是一个复合索引,由(`emp_no`,`title`,`from_date`)三列构成,那当我们写SQL的时候,where条件后面加上哪一列才会使用到主键索引(复合索引)呢?我们一个一个来试一下:

 

1)  where条件使用了emp_no

 



 

 

 

从执行计划中可以看到,只要where条件中使用了emp_no列,那不管后面还有没有其他条件,都会使用到主键索引。

 

 

 

1)  where条件中没有使用emp_no列,但使用了复合主键中的titlefrom_date

 

 

 



 
 

从执行计划中可以看到,虽然复合索引是由(`emp_no`,`title`,`from_date`)三列构成的,但由于没有使用emp_no列作为查询条件,所以MySQL优化器在做执行计划的时候,没有使用到任何索引。

 

为什么会出现这种情况?为什么一定要用到emp_no列才会使用到我们定义的复合索引? titlefrom_date不也是索引的一部分吗?原因是我们在定义复合索引的时候,把emp_no放在了前面,可以看下前面的定义:PRIMARY KEY (`emp_no`,`title`,`from_date`)。复合索引定义的顺序也有关系吗?要说明这个问题,先来看下复合索引是怎么组织的,以及优化器是如何查找的。

 

 

 

当我们建立了复合索引(`emp_no`,`title`,`from_date`)后,实际上MySQL执行引擎会生成一张索引表,结构类似上图所示,(`emp_no`,`title`,`from_date`)作为一行的标识,后面紧跟实际数据的地址。

 

你可以看到emp_no都在索引表中每行的最左边,当执行引擎查找数据的时候,它会从最左边开始查找数据,就是从emp_no列开始查找数据,如:

 



 

如果它发现where条件中包含了emp_no列,它就会查找索引表,否则则不使用索引。这又有两种情况:

-1where条件只包含emp_no

 

执行引擎会按emp_no去搜索索引表,查出所有符合条件的索引列,然后通过后面的数据地址(Oracle其实就是rowid),直接到数据表(titles)中去获取符合条件的数据。

 

-2where条件中除了emp_no,还包含了复合索引中的其他列

 

执行引擎就会按照(emp_no + 其他索引列)去查找索引表,查出符合条件的索引列,然后通过后面的数据地址(Oracle其实就是rowid),直接到数据表(titles)中去获取符合条件的数据。

 

由此可见我们在创建复合索引的时候,第一列的选择非常重要,其关系到执行引擎会不会使用该复合索引。

 

那我们为什么不直接就使用单列索引呢,如这里的emp_no,因为无论如何,我们要使用索引,都必须要使用到emp_no才行,那干脆就不要titlefrom_date了。

 

那是因为单独使用titlefrom_date时虽然不会使用到索引,但是通过tmp_no + title + from_date组合后,缩小了查找的范围。如emp_no = ‘100001’,如果我们只通过100001来查找数据,那可能会有很多数据,但是如果通过emp_no = ‘100001’title=’Engineer’来查找,由于多了一个条件,这样数据量就变小很多。道理就是这样。

 

 

现在回到最初表的设计上,当时我们不是也创建了一个单列索引(KEY `emp_no` (`emp_no`))吗?怎么之前的测试没有使用到?都是走的复合索引。那是因为在这里复合索引就是主键索引,主键索引是唯一性的,对数据的查找更精确,所以优化器优先选择了主键索引。所以这就说明了一个问题,在建索引时要考虑周全,不要建立无用的索引(当然emp_no单列索引在这里另有用处,但这里暂不讨论),无用的索引不仅用不到,而且还会增加ADDUPDATEDELETE的负担。

 

 

二,分区的使用

 

   这里也只讨论SQL语句要怎么写,才会使用到分区。

 

从最初的titles表设计中可以了解到,titles表按照to_days(from_date)做了range分区。那怎样才能让执行引擎按分区查找数据呢?

 



  

当只使用emp_no来搜索数据时,使用到了所有的分区,也就是查找了所有分区(当然在这里emp_no是先走了索引,然后再查分区。但如果是其他列,那么这里就会是全表扫描了)。而当使用到了from_date列来作为搜索条件时,才会到具体的分区中去查找数据,这里只搜索到了p15分区。

 

所以只有当where条件中包含了分区列(这里是from_date)时,执行引擎才会只搜索包含了所需数据的分区,而不去做耗时耗能的全表扫描。

 

分享到:
评论

相关推荐

    Oracle数据库设计策略及规范.docx

    例如,如果对一个5万多条记录的流水表以日期和流水号为序建立复合索引,由于在该表中日期的重复值接近整个表的记录数,用流水号进行查询所用的时间接近3秒;而如果以流水号为索引字段建立索引进行相同的查询,所用...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    SQL(Structured Query Language)结构化查询语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。同时也是数据库脚本文件的扩展名。  SQL语言主要包含5个部分  数据定义...

    数据库基础

    §5.2.4 维护表分区和索引分区 167 §5.3 簇与分区有关的数据字典 169 §5.3.1 分区、簇数据字典列表 169 §5.3.2 基本的分区、簇信息查询 169 第六章 使用SQL 进行数据操作 170 §6.1 INSERT操作 170 §6.1.1 用...

    Oracle8i_9i数据库基础

    §5.2.4 维护表分区和索引分区 167 §5.3 簇与分区有关的数据字典 169 §5.3.1 分区、簇数据字典列表 169 §5.3.2 基本的分区、簇信息查询 169 第六章 使用SQL 进行数据操作 170 §6.1 INSERT操作 170 §6.1.1 用...

    MySQL 5.1中文手冊

    9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规字符集...

    MYSQL中文手册

    9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. ...

    MySQL 5.1参考手册

    9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规字符集...

    mysql官方中文参考手册

    9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规字符集...

    MySQL 5.1参考手册中文版

    9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规...

    MySQL5.1参考手册官方简体中文版

    9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规字符集...

    MySQL 5.1参考手册 (中文版)

    9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规字符集...

    Access+2000中文版高级编程

    6.6.2 使用字段和索引创建新表 133 6.6.3 通过加入索引来修改现有表 136 6.7 小 结 136 第7章 使用VBA处理Access中的错误 138 7.1 Access中的错误消息 138 7.2 使用错误处理程序的不同方法 139 7.3 ...

    Access 2000中文版高级编程(part1)

    Access2000中文版高级编程 目录 第一部分 编程基础 1 第1章 宏与代码 3 ...15.4.2 剪切和粘贴API Viewer中的调用 476 15.4.3 在Win32api.txt文件中查找API调用 477 15.5 使用API调用的注意事项 479 15.5.1 ...

Global site tag (gtag.js) - Google Analytics