什么是global索引,什么是local索引?
如果表分区后,索引分区与表分区是一样的,就是local索引;表分区后,索引不分区就是global索引。
主键可以创建为local索引吗?
不可以。因为如果是local的索引,不能保证主键的唯一性,所以一般主键都是global的。
1、如何考虑创建global还是local索引?
从性能角度考虑来说,建global索引;从维护性角度来说,建local索引;但如果where条件在分区字段里面,就必须创建local索引,如果创建global索引的话,索引高度很高,会扫描很多的叶子块。
2、有前缀的分区索引和无前缀的分区索引(这里说的都是local索引)
首先,只要where条件中有出现分区字段,那么就一定能分区裁剪;
前缀索引指的就是,分区字段包含在索引或者组合索引中;无前缀索引指的是,分区字段不包含在索引或者组合索引中。
举例:
一张按月分区的分区表,一个月新增300w数据,分区字段是date类型的tdate字段。
where tdate>=2023.10.11 and tdate<=2023.10.12,过滤出来的数据大约是2天10几w的数据,肯定是走分区索引的好,建一个tdate的local索引,这个就是有前缀的索引。
where tdate>=2023.10.11 and tdate<=2023.10.12 and owner='xxx',那么就该建一个包含tdate和owner的组合local索引,也是有前缀的索引。
where tdate>=2023.10.11 and tdate<=2023.11.10 and owner='xxx',此时的数据是跨越分区了,就不该把tdate的列放到索引中,只需要创建一个owner列的local索引,这个就是无前缀的索引。因为在where条件中是有出现分区字段的,会自动做分区裁剪,数据会自动扫描10和11月的,千万不能创建global的索引。
总结:
1、SQL的where条件中,没有分区字段,并且where条件能过滤很多数据,where这个列就该创建索引了,但是是创建global还是local的呢?
基于性能考虑,得建global的索引,因为假如这张表有2000个分区,那么如果是local索引,那么也会有2000个索引分区,此时因为前提是where中没有分区字段,所以不会做分区裁剪,那么会扫描所有的索引分区,一个索引分区起码包含root、branch、leaf块,那2000个起码逻辑读都得6000往上,但如果用global索引的话可能就几十,至少绝对比local逻辑读少。
2、where条件里有分区字段
那么必须就建local索引。此时分两种情况创建local索引:
第一种是过滤的数据跨区了,那么此时分区字段不要放到组合索引里面,没什么用(本身就有分区裁剪了),放进去了反而会加大索引的体积以及多扫描叶子块。
第二种是过滤出来的数据没跨区,那么分区字段就必须放在组合索引里面了。
SQL很多都是绑定变量,谁知道跨不跨月,可以抓下绑定变量跨没跨;并且提醒下业务设计时,不要搞跨区的。