039、TiDB特性_索引结构

唯一索引&主键(非聚簇表)

Key: tablePrefix{TableID}_indexPrefixSep{indexID}_indexedColumnsValue
Value: Rowid

indexPrefixSep: 索引位置。例如复合索引,2,表示第二个列

二级索引

Key: tablePrefix{TableID}_indexPrefixSep{indexID}_indexedColumnsValue_{RowID}
Value: null

二级索引它并不唯一, 所以后面还有个rowid

索引结构示例

在这里插入图片描述

创建索引

  • 与MySQL 索引创建语法保持兼容
  • 创建索引时不会阻塞表的数据读写
create table t1 (id int not null primary key auto_increment,c1 int not null,key idx_t1_c1(c1));
  • 创建普通索引
alter table t1 add index idx_t1_c2(c2);
  • 创建唯一索引
alter table t1 add unique index uidx_t1_id(`id`);

联合索引

联合索引在搜索使用时遵循最左匹配原则

create table t2(id int not null primary key auto_increment,
c1 int not null,
c2 int not null,
c3 int not null,
key idx_t2(c1,c2,c3)
);

减小开销: 建一个联合索引(col1,col2,col3),实际相当于建了col1,(col1,col2),(col1,col2,col3)三个索引

可以有效使用索引的场景
在这里插入图片描述

部分使用索引的场景
在这里插入图片描述

不能使用索引的场景
在这里插入图片描述
覆盖索引:当通过索引可以完整获取数据,则TiDB直接通过遍历索引获取数据,而无需回表,减少io操作。所以在真正的实际应用中,覆盖索引是主要的提升性能优化手段之一

索引表达式

索引表达式是一种特殊的索引,能将索引建立于表达式
create index idx1 on t1(lower(col1));

可以通过查询变量tidb_allow_function_for_expression_index可得知哪些函数可以用于表达式索引

mysql> select @@tidb_allow_function_for_expression_index;
+-----------------------------------------------------+
| @@tidb_allow_function_for_expression_index          |
+-----------------------------------------------------+
| lower, md5, reverse, tidb_shard, upper, vitess_hash |
+-----------------------------------------------------+
1 row in set (0.01 sec)

当查询语句中的表达式与表达式索引中的表达式一致时,优化器可以为该查询选择使用索引表达式

在这里插入图片描述

不可见索引

  • invisible indexes 不会被查询优化器使用
  • 不可见是仅仅对优化器而言的,不可见索引仍然可以被修改或删除
  • 不允许将主键索引设为不可见
  • alter index用于修改索引的可见性,设置为visible 或 invisible
create table t1 ( c1 int,c2 int,unique(c2));
create unique index c1 on t1(c1) visible;
alter table t1 alter index c1 invisible;

例如可以评估某个SQL语句把索引拿掉但不能立即直接删掉,看会不会影响性能。

MySQL 兼容性

  • 不支持fulltext,hash,spaital索引
  • 不支持降序索引
  • 无法向表中增删改clustered类型的主键
  • 不支持类似mysql中提供的优化器开关use_invisible_indexes=on(将不可见索引重新设计为可见)

查看索引的Region分布

show table [table_name] index [index_name] regions [where clauseoptions]

实验

创建主键索引、普通二级索引、联合唯一索引,并查看索引的分布情况
1、创建表

mysql> CREATE TABLE index_order (
    -> id bigint(20) unsigned NOT NULL AUTO_random,
    -> code varchar(30) NOT NULL,
    -> order_no varchar(200) NOT NULL DEFAULT '',
    -> status int(4) NOT NULL,
    -> cancel_flag int(4) DEFAULT NULL,
    -> create_time datetime DEFAULT NULL,
    -> create_user varchar(32) DEFAULT NULL,
    -> PRIMARY KEY (id) clustered
    -> ) ENGINE=InnoDB;
Query OK, 0 rows affected, 1 warning (0.11 sec)

mysql> show create table index_order;
| index_order | CREATE TABLE `index_order` (
  `id` bigint(20) unsigned NOT NULL /*T![auto_rand] AUTO_RANDOM(5) */,
  `code` varchar(30) NOT NULL,
  `order_no` varchar(200) NOT NULL DEFAULT '',
  `status` int(4) NOT NULL,
  `cancel_flag` int(4) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `create_user` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin |

2、表中插入数据

mysql> insert into index_order(code,order_no,status,create_user,create_time) values(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now());
Query OK, 5 rows affected (0.02 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> insert into index_order(code,order_no,status,create_user,create_time) values(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now()),(concat('CODE_',LPAD(round(rand()*1000),5,0)),uuid(),round((rand()*100)),concat('USERID_',LPAD(round(rand()*1000),5,0)),now());
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0


mysql> select count(*) from index_order;
+----------+
| count(*) |
+----------+
|       10 |
+----------+
1 row in set (0.01 sec)

3、将表index_order的regions手工打散

mysql> split table index_order between (0) and (9223372036854775807) regions 3;
+--------------------+----------------------+
| TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO |
+--------------------+----------------------+
|                  2 |                    1 |
+--------------------+----------------------+
1 row in set (0.22 sec)

4、查看表index_order的regions分布

mysql> show table index_order regions;
+-----------+----------------------------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| REGION_ID | START_KEY                  | END_KEY                    | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS |
+-----------+----------------------------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
|      5003 | t_74_                      | t_74_r_3074457345618258602 |      5004 |            1001 | 5004  |          0 |             0 |          0 |                    1 |                0 |
|      5005 | t_74_r_3074457345618258602 | t_74_r_6148914691236517204 |      5006 |            1001 | 5006  |          0 |             0 |          0 |                    1 |                0 |
|      1002 | t_74_r_6148914691236517204 |                            |      1003 |            1001 | 1003  |          0 |             0 |          0 |                    1 |                0 |
+-----------+----------------------------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
3 rows in set (0.00 sec)

5、创建普通二级索引

mysql> create index id_index_order_create_user on index_order(create_user);
Query OK, 0 rows affected (2.80 sec)

6、查看索引regions的分布

mysql> show table index_order index id_index_order_create_user regions;
+-----------+-----------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| REGION_ID | START_KEY | END_KEY                    | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS |
+-----------+-----------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
|      5003 | t_74_     | t_74_r_3074457345618258602 |      5004 |            1001 | 5004  |          0 |          5188 |       4220 |                    1 |               10 |
+-----------+-----------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
1 row in set (0.00 sec)

7、创建联合唯一索引 idx_index_order_unique

mysql> create unique index idx_index_order_unique on index_order(code,order_no,id);
Query OK, 0 rows affected (2.81 sec)

8、查看联合唯一索引的Regions分布

mysql> show table index_order index idx_index_order_unique regions;
+-----------+-----------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| REGION_ID | START_KEY | END_KEY                    | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS |
+-----------+-----------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
|      5003 | t_74_     | t_74_r_3074457345618258602 |      5004 |            1001 | 5004  |          0 |             0 |          0 |                    1 |               10 |
+-----------+-----------+----------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
1 row in set (0.00 sec)

9、对联合唯一索引的regions进行split

mysql> split table index_order index idx_index_order_unique between ('CODE_00000') and ('CODE_99999') regions 4;
+--------------------+----------------------+
| TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO |
+--------------------+----------------------+
|                  5 |                    1 |
+--------------------+----------------------+
1 row in set (0.51 sec)

10、查看联合唯一索引的Region分布:

mysql> show table index_order index idx_index_order_unique regions;
+-----------+---------------------------------------+---------------------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| REGION_ID | START_KEY                             | END_KEY                               | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS |
+-----------+---------------------------------------+---------------------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
|      5009 | t_74_i_2_                             | t_74_i_2_01434f44455f3272733f32724000 |      5010 |            1001 | 5010  |          0 |             0 |          0 |                    1 |                1 |
|      5011 | t_74_i_2_01434f44455f3272733f32724000 | t_74_i_2_01434f44455f34b4b57f34b48000 |      5012 |            1001 | 5012  |          0 |             0 |          0 |                    1 |                1 |
|      5013 | t_74_i_2_01434f44455f34b4b57f34b48000 | t_74_i_2_01434f44455f36f6f7bf36f6c000 |      5014 |            1001 | 5014  |          0 |             0 |          0 |                    1 |                1 |
|      5015 | t_74_i_2_01434f44455f36f6f7bf36f6c000 | t_74_i_3_                             |      5016 |            1001 | 5016  |          0 |             0 |          0 |                    1 |                1 |
+-----------+---------------------------------------+---------------------------------------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
4 rows in set (0.01 sec)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值