本文讨论复合索引以及分区的简单使用,也即是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列,但使用了复合主键中的title和from_date列
从执行计划中可以看到,虽然复合索引是由(`emp_no`,`title`,`from_date`)三列构成的,但由于没有使用emp_no列作为查询条件,所以MySQL优化器在做执行计划的时候,没有使用到任何索引。
为什么会出现这种情况?为什么一定要用到emp_no列才会使用到我们定义的复合索引? title和from_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列,它就会查找索引表,否则则不使用索引。这又有两种情况:
-1)where条件只包含emp_no列
执行引擎会按emp_no去搜索索引表,查出所有符合条件的索引列,然后通过后面的数据地址(Oracle其实就是rowid),直接到数据表(titles)中去获取符合条件的数据。
-2)where条件中除了emp_no,还包含了复合索引中的其他列
执行引擎就会按照(emp_no + 其他索引列)去查找索引表,查出符合条件的索引列,然后通过后面的数据地址(Oracle其实就是rowid),直接到数据表(titles)中去获取符合条件的数据。
由此可见我们在创建复合索引的时候,第一列的选择非常重要,其关系到执行引擎会不会使用该复合索引。
那我们为什么不直接就使用单列索引呢,如这里的emp_no,因为无论如何,我们要使用索引,都必须要使用到emp_no才行,那干脆就不要title和from_date了。
那是因为单独使用title和from_date时虽然不会使用到索引,但是通过tmp_no + title + from_date组合后,缩小了查找的范围。如emp_no = ‘100001’,如果我们只通过100001来查找数据,那可能会有很多数据,但是如果通过emp_no = ‘100001’和title=’Engineer’来查找,由于多了一个条件,这样数据量就变小很多。道理就是这样。
现在回到最初表的设计上,当时我们不是也创建了一个单列索引(KEY `emp_no` (`emp_no`))吗?怎么之前的测试没有使用到?都是走的复合索引。那是因为在这里复合索引就是主键索引,主键索引是唯一性的,对数据的查找更精确,所以优化器优先选择了主键索引。所以这就说明了一个问题,在建索引时要考虑周全,不要建立无用的索引(当然emp_no单列索引在这里另有用处,但这里暂不讨论),无用的索引不仅用不到,而且还会增加ADD、UPDATE和DELETE的负担。
二,分区的使用
这里也只讨论SQL语句要怎么写,才会使用到分区。
从最初的titles表设计中可以了解到,titles表按照to_days(from_date)做了range分区。那怎样才能让执行引擎按分区查找数据呢?
当只使用emp_no来搜索数据时,使用到了所有的分区,也就是查找了所有分区(当然在这里emp_no是先走了索引,然后再查分区。但如果是其他列,那么这里就会是全表扫描了)。而当使用到了from_date列来作为搜索条件时,才会到具体的分区中去查找数据,这里只搜索到了p15分区。
所以只有当where条件中包含了分区列(这里是from_date)时,执行引擎才会只搜索包含了所需数据的分区,而不去做耗时耗能的全表扫描。
相关推荐
同时,对索引的支持也更加丰富,如函数索引、位图索引和复合索引等,提高了查询性能。 5. 游标和事务:游标功能得到增强,支持动态和静态游标,以及在游标中进行更新和删除操作。在事务处理上,SQL99提供了四种隔离...
-索引和分区:理解如何设计和使用索引来优化查询。 -PL/SQL代码优化技巧:避免不必要的计算,减少磁盘I/O,提高程序效率。 8. **PL/SQL与Oracle特性结合**: - 权限和角色:理解PL/SQL中的权限管理,包括GRANT和...
2. 分区和分片:介绍Oracle中的高级特性,如范围分区、列表分区、哈希分区和复合分区,以及数据分片的策略。 3. 存储优化:讨论索引的类型(B树、位图、函数索引)和创建,以及如何通过分析和统计优化查询性能。 4. ...
单列索引、复合索引、唯一索引和非唯一索引都是常见的索引类型。位图索引适用于低基数(低独特性)的列,而函数索引允许对索引列应用函数。分区技术是另一个提高大表性能的方法,可以通过范围、列表、哈希等方式将大...
脚本可能涉及到创建、管理索引和分区的实践操作,帮助你理解如何优化数据库结构。 7. **数据库对象管理** 脚本还可能涵盖表、视图、索引、同义词等数据库对象的创建、修改和删除,以及权限和角色的管理,这对于...
6. 分区与分片:Oracle 10g提供高级的分区技术,如范围分区、列表分区、哈希分区和复合分区,以优化大型表的查询性能。分片则是将数据分布在多个物理数据库上,以实现更高级别的可扩展性和容错性。 7. 数据库对象:...
- 复合索引时,SQL语句应使用主索引列。 - 尽量避免NULL值在索引中。 - 避免使用NOT等于操作。 - 确保查询和排序列与索引列顺序一致。 8. **WHERE子句过滤原则**:将过滤出最多记录的条件放在最前面,以减少...
8. **索引优化和性能调优**:深入研究如何利用PL/SQL进行性能分析,以及如何通过索引、物化视图、表分区等手段提升查询性能。 9. **并发控制**:介绍PL/SQL中的锁定机制,如ROWLOCK和SHARE锁,以及如何避免死锁。 ...
为了充分利用这个存储过程,数据库管理员需要理解分区的基本概念,包括范围分区、列表分区、哈希分区和复合分区等。同时,还需要熟悉PL/SQL编程,以便根据实际需求定制和调用这个存储过程。在实际应用中,还需要考虑...
11索引:学习如何创建和使用索引以提高查询性能,包括唯一索引、复合索引和全文索引。 在实际应用中,SQL还常常与数据库管理系统(如MySQL、Oracle、SQL Server、PostgreSQL等)结合,每种DBMS可能有自己的特性和...
7. 索引优化:学习如何创建和管理索引,以提高查询性能,包括唯一性索引、复合索引和全文索引。 8. 事务和并发控制:理解ACID属性,掌握事务的开始、提交、回滚,以及并发问题的解决方案,如死锁和锁定机制。 9. ...
5. **索引**:索引是提升数据库查询性能的关键,书中有专门章节解释了如何创建、管理和优化索引,包括唯一索引、复合索引、全文索引等。 6. **事务处理(Transaction)**:SQL支持事务的概念,保证数据的一致性和...
- 如果使用复合索引,只有索引顺序上的第一个字段才适合作为过滤条件。 - `DISTINCT`、`ORDER BY`等语法尽量在查询结果需要时才使用。 - 使用`UNION ALL`代替`UNION`以提高性能。 ##### Insert、Delete和Update - ...
10. **索引(Indexes)**:索引是提高查询性能的关键,Oracle提供了B树、位图、函数索引等多种类型的索引,以及复合、唯一、反向和分区索引的概念。 11. **分区(Partitioning)**:对于大型表,分区是提高查询和...
7. **记录和复合类型**:PL/SQL支持自定义记录类型和复合类型,这增强了对复杂数据结构的操作能力。学习如何声明和使用这些类型可以提升编程灵活性。 8. **索引和性能优化**:针对Oracle 10g,书中还会讲解如何利用...
### PL/SQL用户指南与参考知识点汇总 #### 第一章:PL/SQL一览 ##### 一、理解PL/SQL的主要特性 PL/SQL(Procedural Language for SQL)是一种过程化语言,它允许...Oracle提供了一系列性能优化特性,如索引、分区等。
- 索引与分区:如何利用索引来加速查询,以及如何对表进行分区以提高性能。 - 执行计划:理解查询执行计划的重要性及其优化方法。 - 性能诊断工具:使用Oracle提供的工具(如DBMS_SQL_MONITOR)来监控和分析性能...
8. **索引**:理解索引的作用,学习如何创建和管理索引以提高查询性能,包括唯一索引、主键索引和复合索引。 9. **事务处理**:掌握SQL中的事务概念,包括开始事务、提交事务、回滚事务,以及事务隔离级别。 10. *...