Key: tablePrefix{TableID}_indexPrefixSep{indexID}_indexedColumnsValue
Value: Rowid
indexPrefixSep: 索引位置。例如复合索引,2,表示第二个列
Key: tablePrefix{TableID}_indexPrefixSep{indexID}_indexedColumnsValue_{RowID}
Value: null
二级索引它并不唯一, 所以后面还有个rowid
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)
当查询语句中的表达式与表达式索引中的表达式一致时,优化器可以为该查询选择使用索引表达式
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语句把索引拿掉但不能立即直接删掉,看会不会影响性能。
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)