乐趣区

关于索引:技术分享-OceanBase-使用全局索引的必要性

作者:杨涛涛

资深数据库专家,专研 MySQL 十余年。善于 MySQL、PostgreSQL、MongoDB 等开源数据库相干的备份复原、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相干技术支持、MySQL 相干课程培训等工作。

本文起源:原创投稿

* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。


OceanBase 从索引和主表的关系来讲,有两种索引:部分索引和全局索引。

部分索引等价于咱们通常说的本地索引,与主表的数据结构放弃一对一的关系。部分索引没有独自分区的概念,一般来讲,主表的分区形式决定部分索引的分区形式,也就是说假如主表有 10 个分区,那么对于每个分区来讲,都有一个对应的部分索引。

全局索引区别于部分索引,与主表数据结构放弃一对多、多对多的关系,全局索引次要利用于分区表。对于分区表来讲,一个非分区全局索引对应主表的多个分区;一个分区全局索引也对应主表的多个分区,同时主表每个分区也对应多个全局索引的索引分区。

引入全局索引的指标就是补救部分索引在数据过滤上的一些有余,比方防止分区表的全分区扫描,把过滤条件下压到匹配的表分区中。

针对查问过滤条件来讲,部分索引和全局索引的简略应用场景总结如下:
1. 带分区键的查问,适宜用部分索引。这也是分区表设计的初衷,以过滤条件来反推分区表的设计。

比方语句:select * from p1 where id = 9; id 为分区键,能够间接定位到具体的表分区 partitions(p9),仅需扫描一行记录。

<mysql:5.6.25:ytt>explain select  * from p1 where id = 9\G
*************************** 1. row ***************************
Query Plan: ==================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
----------------------------------
|0 |TABLE GET|p1  |1        |46  |
==================================

Outputs & filters: 
-------------------------------------
0 - output([p1.id], [p1.r1], [p1.r2]), filter(nil), 
access([p1.id], [p1.r1], [p1.r2]), partitions(p9)

1 row in set (0.005 sec)
2. 不带分区键的查问有两个思考方向,次要在于是否克服全局索引的毛病:全局索引势必会带来查问的分布式执行!

(1)表的并发写不大,能够思考用全局索引。

(2)表的并发写很大,用全局索引与否就有待商讨,能够依据以后的业务模型做个压力测试,取一个折中点。

比方以下语句,全局索引 idx_r2_global 基于非分区字段 r2,执行打算如下:算子 1 须要去底层各个节点分布式扫描(DISTRIBUTED TABLE SCAN)。

<mysql:5.6.25:ytt>explain select * from p1 where r2 = 30\G
*************************** 1. row ***************************
Query Plan: =============================================================

|ID|OPERATOR               |NAME             |EST. ROWS|COST|
-------------------------------------------------------------

|0 |TABLE LOOKUP           |p1               |101      |395 |

|1 | DISTRIBUTED TABLE SCAN|p1(idx_r2_global)|101      |48  |
=============================================================
...
3. 对于须要在非主键、非分区键的字段上建设惟一索引的业务来讲,能够有两个思考方向:

(1)给这个字段创立部分索引,然而须要带上残缺的分区键。不举荐这种形式,一来是须要更改过滤条件,减少分区键;二来减少索引自身的数据冗余。

比方在 MySQL 租户下创立这样的索引会报错:

<mysql:5.6.25:ytt>create unique index udx_r1 on p1(r1) local;
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function

如果创立本地索引,则须要加上残缺分区键:

<mysql:5.6.25:ytt>create unique index udx_r1_local on p1(r1,id) local;
Query OK, 0 rows affected (3.012 sec)

(2)给这个字段创立全局索引,不须要带上残缺的分区键。强烈推荐的形式!

<mysql:5.6.25:ytt>create unique index udx_r1_global on p1(r1) global;
Query OK, 0 rows affected (1.950 sec)
退出移动版