ITPub博客

首页 > 数据库 > 国内数据库 > OceanBase函数索引实战指南:从创建到优化,解决查询性能痛点(附实战命令)

OceanBase函数索引实战指南:从创建到优化,解决查询性能痛点(附实战命令)

原创 国内数据库 作者:瑞蓝创_RLC_888 时间:2025-12-17 18:48:28 0 删除 编辑

“明明给字段建了索引,可带函数的查询还是走全表扫描,数据量大了直接卡到超时……”

如果你在使用 OceanBase 或 MySQL 时遇到过这种问题,大概率是没用到函数索引!当查询条件包含函数计算(比如LOWER(name)、MD5(customer_id))时,普通索引完全失效,而函数索引能直接基于计算结果建立索引,让查询效率飙升10倍+!

今天这篇干货,从定义、用法、避坑到实战场景,带你彻底掌握 OceanBase 函数索引的核心玩法~

1. 函数索引的定义

函数索引是 基于表达式或函数计算结果创建的索引,而非直接基于列值。

  • 在MySQL 8.0.13开始支持函数索引,主要通过索引计算后的值来提高查询性能。

  • OceanBase 支持版本:V4.2.0 及以上;

参考文档: MySQL 8.0 参考手册

2. 函数索引的作用

  • 当查询条件包含函数时,普通索引无法使用,优化函数表达式查询;
  • 对函数计算结果建立索引可以避免全表扫描;
  • 对于包含计算的查询条件能显著提高效率;

2.1 函数索引的创建

ps:普通索引为 [索引名](列名),函数索引为 [索引名]((列名));两层括号后开始填写函数表达式;

创建函数索引时,会向主表添加一个隐藏的虚拟生成列,定义为函数索引的索引键,然后再将虚拟生成列的值存储到索引表中。



/* 建表时创建*/

CREATE  TABLE tst_tb (col1  int, col2  int, [ UNIQUE] { KEY /  INDEX} [索引名]((用户函数(col1)));

/* 使用 create index 创建 */
CREATE [ UNIQUE]  INDEX tst_tb_func_idx2  ON tst_tb((col1+ 3));

/* 使用 alter table 创建 */
ALTER  TABLE tst_tb  ADD [ UNIQUE] { INDEX |  KEY} [索引名] ((用户函数(col1)));

2.2 函数索引的查询



/* 

示例1:对名字的小写形式创建索引,使用与索引定义完全相同的表达式查询
*/

CREATE  INDEX idx_lower_name  ON tst_tb (( LOWER( name)));
SELECT *  FROM employees  WHERE  LOWER( name) =  'John';

/* 
示例2:对JSON字段的特定路径创建索引
从 JSON 文档中指定的路径返回数据 
*/

CREATE  INDEX idx_json_extract  ON tst_tb ((JSON_EXTRACT(person,  '$.weight')));
SELECT *  FROM tst_tb  WHERE JSON_EXTRACT(specs,  '$.weight') > 10;

3.函数索引的使用限制

> 1. 非确定性的系统函数禁止被用于创建函数索引;

> 2. 子查询、参数、变量、存储过程、自定义函数 function 不允许在函数索引上使用;

> 3. 函数索引的表达式结果受限于字段长度;

> 4. 函数索引无法作为主键使用;

> 5. 空间索引和全文索引不能定义为函数索引;

> 6. 函数索引不允许在外键中使用;

> 7. 某字段用于函数索引,删列前必须删除该索引,否则报错;



/* 1. 使用非确定性函数*/

create  index tst_01  on tst_tb(( now()));
失败原因:ErrorCode = 3758, SQLState = HY000, Details = Expression of functional index contains a disallowed function.
/*在创建函数索引时,使用了不支持的函数,索引函数使用 SYSDATE 或用户环境*/
create  index current_time_fun_idx  on tst_tb(( current_date()));
失败原因:ErrorCode = 3758, SQLState = HY000, Details = Expression of functional index contains a disallowed function.

/* 2.表达式过于复杂,函数索引中包括了子查询*/
CREATE  INDEX tst_02  ON tst_tb (( SELECT  MAX( id)  FROM tst_tb));
失败原因:ErrorCode = 1064, SQLState = 42000, Details = You have an error in your SQL syntax;  check the  manual that corresponds  to your OceanBase  version  for the  right syntax  to  use near  'SELECT MAX(id) FROM tst_tb))'  at line  1

/* 3.表达式结果太长,REPEAT 重复多次改字段字符串拼接*/
CREATE  INDEX idx_invalid  ON tst_tb (( REPEAT(customer_id,  100))); 
失败原因:ErrorCode = 3757, SQLState = HY000, Details = Cannot  create a functional  index  on an expression that  returns a  BLOB  or TEXT. Please  consider  using CAST.
/* 在创建函数索引时,使用了返回 BLOB 或 TEXT 类型的表达式,而 BLOB 或 TEXT 类型的表达式不能用于创建函数索引 */

/* 4.函数索引无法作为主键创建*/
CREATE  TABLE  `tst_tb` (
   `id`  bigint( 20)  unsigned  NOT  NULL AUTO_INCREMENT  COMMENT  '主键id,自动增长',
   `customer_id`  varchar( 50)  DEFAULT  NULL  COMMENT  '客户ID',
   `create_time` datetime  NOT  NULL  DEFAULT  CURRENT_TIMESTAMP  COMMENT  '创建时间',
   `update_time` datetime  DEFAULT  NULL  ON  UPDATE  CURRENT_TIMESTAMP  COMMENT  '更新时间',
   `product`  varchar( 10)  DEFAULT  NULL  COMMENT  '产品类型',
  PRIMARY  KEY  `pri_cust` (( lower( md5( concat( upper(customer_id),  'oceanbase'))))),
   KEY  `idx_create_time` ( `create_time`) BLOCK_SIZE  16384  LOCAL,
   KEY  `ob_idx_customer_id` ( `customer_id`) BLOCK_SIZE  16384  LOCAL
);
失败原因:ErrorCode = 1064, SQLState = 42000, Details = You have an error in your SQL syntax;  check the  manual that corresponds  to your OceanBase  version  for the  right syntax  to  use near  '(lower(md5(concat(upper(customer_id), 'oceanbase '))))), KEY `idx_create_time` '  at line  7

/* 5.空间索引和全文索引不能定义为函数索引*/
CREATE  TABLE tbl_func (c1  int, c2  int,  index tbl1_func_idx1 ((c1+ 1)), SPATIAL  KEY ((c1+c2)));
失败原因:ErrorCode = 3760, SQLState = HY000, Details = Spatial functional index is not supported.
/* 不支持空间索引套用函数索引*/
CREATE  TABLE tbl_func (c1  int, c2  varchar( 20),  index tbl1_func_idx1 ((c1+ 1)),  FULLTEXT  INDEX full_idx_func (( SUBSTR(c2, 1, 2)))  WITH PARSER ngram PARSER_PROPERTIES=(ngram_token_size= 3));
失败原因:ErrorCode = 1235, SQLState = 0A000, Details = Fulltext index on generated column is not supported
/* 不支持全文索引套用函数索引*/

/* 6.函数索引不允许在外键中使用*/
CREATE  TABLE products (
    product_id  INT PRIMARY  KEY,
    product_code  VARCHAR( 20)  NOT  NULL,  
    product_name  VARCHAR( 100)  NOT  NULL,
     INDEX idx_lower_product_code (( LOWER(product_code)))
);


CREATE  TABLE orders (
    order_id  INT PRIMARY  KEY,
    product_code_ref  VARCHAR( 20),   
     CONSTRAINT fk_order_product  FOREIGN  KEY (product_code_ref)  -- 创建外键引用函数索引 
     REFERENCES products ( LOWER(product_code))  
);

失败原因:ErrorCode = 1064, SQLState = 42000, Details = You have an error in your SQL syntax;  check the  manual that corresponds  to your OceanBase  version  for the  right syntax  to  use near  '(product_code)) )'  at line  7

/* 7. 某字段用于函数索引,删列前必须删除该索引,否则报错*/
ALTER  TABLE products  DROP  COLUMN product_code;
失败原因:ErrorCode = 3837, SQLState = HY000, Details = Column 'product_code' has a functional index dependency and cannot be dropped or renamed.

参考文档:

腾讯云:mysql函数索引_MySQL 函数索引 (Functional indexes)

函数索引支持的系统函数列表

函数索引不支持的系统函数列表

MySQL 函数索引测试分析

4. 无法创建函数索引的替代方案



/*表定义语句*/

CREATE  TABLE  `tst_tb` (
   `id`  bigint( 20)  unsigned  NOT  NULL AUTO_INCREMENT  COMMENT  '主键id,自动增长',
   `customer_id`  varchar( 50)  DEFAULT  NULL  COMMENT  '客户ID',
   `create_time` datetime  NOT  NULL  DEFAULT  CURRENT_TIMESTAMP  COMMENT  '创建时间',
   `update_time` datetime  DEFAULT  NULL  ON  UPDATE  CURRENT_TIMESTAMP  COMMENT  '更新时间',
   `product`  varchar( 10)  DEFAULT  NULL  COMMENT  '产品类型',
   `name`  varchar( 100)  DEFAULT  NULL,
  PRIMARY  KEY ( `id`),
   KEY  `idx_create_time` ( `create_time`) BLOCK_SIZE  16384  LOCAL,
   KEY  `ob_idx_customer_id` ( `customer_id`) BLOCK_SIZE  16384  LOCAL
);
explain  extended  select *  from tst_tb  where  name= 'Product One';
=================================================
|ID|OPERATOR       |NAME  |EST.ROWS|EST.TIME(us)|
-------------------------------------------------
|0 |TABLE FULL SCAN|tst_tb|1       |3           |
=================================================
Outputs & filters:
-------------------------------------
  0 - output([tst_tb.id(0x7ff8f1823480)], [tst_tb.customer_id(0x7ff8f18238d0)], [tst_tb.create_time(0x7ff8f1823d20)], [tst_tb.update_time(0x7ff8f1824170)],
       [tst_tb.product(0x7ff8f18245c0)], [tst_tb.name(0x7ff8f1822d60)]), filter([tst_tb.name(0x7ff8f1822d60) = 'Product One'(0x7ff8f1822000)(0x7ff8f1822490)]), rowset=16
      access([tst_tb.id(0x7ff8f1823480)], [tst_tb.name(0x7ff8f1822d60)], [tst_tb.customer_id(0x7ff8f18238d0)], [tst_tb.create_time(0x7ff8f1823d20)], [tst_tb.update_time(0x7ff8f1824170)],
       [tst_tb.product(0x7ff8f18245c0)]), partitions(p0)
      is_index_back=false, is_global_index=false, filter_before_indexback[false], 
      range_key([tst_tb.id(0x7ff8f1823480)]), range(MIN ; MAX)always true
      
/* 添加虚拟生成列 */
ALTER  TABLE tst_tb  ADD  COLUMN lower_name  VARCHAR( 100) 
GENERATED  ALWAYS  AS ( LOWER( name))  STORED;

/* 在虚拟生成列上创建索引 */
CREATE  INDEX idx_lower_name  ON tst_tb (lower_name);

/* 执行计划 */
explain  extended  select *  from tst_tb  where lower_name= 'Product One';
==================================================================
|ID|OPERATOR        |NAME                  |EST.ROWS|EST.TIME(us)|
------------------------------------------------------------------
|0 |TABLE RANGE SCAN|tst_tb(idx_lower_name)|1       |8           |
==================================================================
Outputs & filters:
-------------------------------------
  0 - output([tst_tb.id(0x7ff8bd22d120)], [tst_tb.customer_id(0x7ff8bd22d570)], [tst_tb.create_time(0x7ff8bd22d9c0)], [tst_tb.update_time(0x7ff8bd22de10)],
       [tst_tb.product(0x7ff8bd22e260)], [tst_tb.name(0x7ff8bd223840)], [tst_tb.lower_name(0x7ff8bd221bc0)]), filter(nil), rowset=16
      access([tst_tb.id(0x7ff8bd22d120)], [tst_tb.name(0x7ff8bd223840)], [tst_tb.lower_name(0x7ff8bd221bc0)], [tst_tb.customer_id(0x7ff8bd22d570)], [tst_tb.create_time(0x7ff8bd22d9c0)],
       [tst_tb.update_time(0x7ff8bd22de10)], [tst_tb.product(0x7ff8bd22e260)]), partitions(p0)
      is_index_back=true, is_global_index=false, 
      range_key([tst_tb.lower_name(0x7ff8bd221bc0)], [tst_tb.id(0x7ff8bd22d120)]), range(Product One,MIN ; Product One,MAX), 
      range_cond([tst_tb.lower_name(0x7ff8bd221bc0) = 'Product One'(0x7ff8bd2eb070)(0x7ff8bd2ea650)])

表数据

未走索引

走索引

客户使用场景

场景一:给表字段添加函数索引进行优化

  • 场景描述:客户有两张表,A 表是在线热更数据的,B 表是离线异步更新的,其中 A表中的 customer_id字段是应用程序加密过的字段值,B表中的 customer_id字段是原始数据,客户将该两张表创建了联合查询的视图,为了保持一致,对 B 表的 customer_id 字段做了 md5 加密,但查询视图的时候 B 表没有走索引;

  • 集群版本: OceanBase V4.2.1.10



/* 

A 表结构 
B 表与A表结构一致,且B表的数据是异步更新
*/

CREATE  TABLE  `tst_ta` (
   `id`  bigint( 20)  unsigned  NOT  NULL AUTO_INCREMENT  COMMENT  '主键id,自动增长',
   `customer_id`  varchar( 50)  DEFAULT  NULL  COMMENT  '客户ID',
   `create_time` datetime  NOT  NULL  DEFAULT  CURRENT_TIMESTAMP  COMMENT  '创建时间',
   `update_time` datetime  DEFAULT  NULL  ON  UPDATE  CURRENT_TIMESTAMP  COMMENT  '更新时间',
   `product`  varchar( 10)  DEFAULT  NULL  COMMENT  '产品类型',
  PRIMARY  KEY ( `id`,  `create_time`),
   KEY  `idx_create_time` ( `create_time`) BLOCK_SIZE  16384  LOCAL,
   KEY  `ob_idx_customer_id` ( `customer_id`) BLOCK_SIZE  16384  LOCAL
);

测试表模拟数据



INSERT 
INTO 
`tst_tb` (
`customer_id`, 
`update_time`, 
`product`) 
VALUES (
'CUST001', 
'2023-01-15 10:30:00', 
'A');

INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST002',  '2023-01-16 11:45:00',  'B');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST003',  '2023-01-17 09:15:00',  'C');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST004',  '2023-01-18 14:20:00',  'A');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST005',  '2023-01-19 16:30:00',  'B');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST006',  '2023-01-20 10:10:00',  'D');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST007',  '2023-01-21 13:25:00',  'A');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST008',  '2023-01-22 15:40:00',  'C');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST009',  '2023-01-23 08:50:00',  'B');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST010',  '2023-01-24 17:00:00',  'D');
INSERT  INTO  `tst_tb` ( `customer_id`,  `product`)  VALUES ( 'CUST011',  'E');
INSERT  INTO  `tst_tb` ( `customer_id`,  `product`)  VALUES ( 'CUST012',  'A');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST013',  '2023-01-27 12:15:00',  'B');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST014',  '2023-01-28 14:30:00',  'C');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST015',  '2023-01-29 09:45:00',  'D');
INSERT  INTO  `tst_tb` ( `customer_id`,  `product`)  VALUES ( 'CUST016',  'A');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST017',  '2023-01-31 11:20:00',  'B');
INSERT  INTO  `tst_tb` ( `customer_id`,  `product`)  VALUES ( 'CUST018',  'E');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST019',  '2023-02-02 16:10:00',  'C');
INSERT  INTO  `tst_tb` ( `customer_id`,  `update_time`,  `product`)  VALUES ( 'CUST020',  '2023-02-03 10:25:00',  'D');

tst_ta.customer_id 加密后的表数据

tst_tb.customer_id 加密前的表数据



/*

将 customer_id 字段的值统一大写后与'oceanbase'拼接,然后经过 md5 算法加密后统一小写后记录
*/

CREATE  VIEW  `tst_view`  AS
(  select  id,customer_id,create_time,update_time,product  from tst_ta)
union  all 
( select  id,
   lower( md5( concat( upper(customer_id),  'oceanbase')))  AS customer_id,
  create_time,update_time,product  from tst_tb
);

未走索引



/*

CREATE TABLE `tst_ta` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id,自动增长',
  `customer_id` varchar(50) DEFAULT NULL COMMENT '客户ID',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `product` varchar(10) DEFAULT NULL COMMENT '产品类型',
  PRIMARY KEY (`id`, `create_time`),
  KEY `idx_create_time` (`create_time`) BLOCK_SIZE 16384 LOCAL,
  KEY `ob_idx_customer_id` (`customer_id`) BLOCK_SIZE 16384 LOCAL
);

*/

explain  extended  select *  from tst_view  where customer_id= '366330e31189acd28639de9dd7b29cb1';
========================================================================
|ID|OPERATOR          |NAME                      |EST.ROWS|EST.TIME(us)|
------------------------------------------------------------------------
|0 |UNION ALL         |                          |2       |11          |
|1 |├─TABLE RANGE SCAN|tst_ta(ob_idx_customer_id)|1       |7           |
|2 |└─TABLE FULL SCAN |tst_tb                    |1       |4           |
========================================================================
Outputs & filters:
-------------------------------------
  0 - output([UNION([1])(0x7ff9ce07efa0)], [UNION([2])(0x7ff9ce07f360)], [UNION([3])(0x7ff9ce07f720)], [UNION([4])(0x7ff9ce07fae0)], [UNION([5])(0x7ff9ce07fea0)]), filter(nil), rowset=16
  1 - output([tst_ta.id(0x7ff9ce064850)], [tst_ta.customer_id(0x7ff9ce065120)], [tst_ta.create_time(0x7ff9ce0659f0)], [tst_ta.update_time(0x7ff9ce0662c0)],
       [tst_ta.product(0x7ff9ce066b90)]), filter(nil), rowset=16
      access([tst_ta.__pk_increment(0x7ff9ce084030)], [tst_ta.id(0x7ff9ce064850)], [tst_ta.customer_id(0x7ff9ce065120)], [tst_ta.create_time(0x7ff9ce0659f0)],
       [tst_ta.update_time(0x7ff9ce0662c0)], [tst_ta.product(0x7ff9ce066b90)]), partitions(p0)
      is_index_back=true, is_global_index=false, 
      range_key([tst_ta.customer_id(0x7ff9ce065120)], [tst_ta.__pk_increment(0x7ff9ce084030)]), range(366330e31189acd28639de9dd7b29cb1,MIN ; 366330e31189acd28639de9dd7b29cb1,
      MAX), 
      range_cond([tst_ta.customer_id(0x7ff9ce065120) = '366330e31189acd28639de9dd7b29cb1'(0x7ff8f0484a00)(0x7ff8f0483fe0)])
  2 - output([tst_tb.id(0x7ff9ce0797e0)], [lower(md5(concat(upper(tst_tb.customer_id(0x7ff9ce07ce60))(0x7ff9ce07b6b0), 'oceanbase')(0x7ff9ce07ade0))(0x7ff9ce07a510))(0x7ff9ce079c40)],
       [tst_tb.create_time(0x7ff9ce07d870)], [tst_tb.update_time(0x7ff9ce07e140)], [tst_tb.product(0x7ff9ce07ea10)]), filter([lower(md5(concat(upper(tst_tb.customer_id(0x7ff9ce07ce60))(0x7ff9ce07b6b0),
       'oceanbase')(0x7ff9ce07ade0))(0x7ff9ce07a510))(0x7ff9ce079c40) = '366330e31189acd28639de9dd7b29cb1'(0x7ff9ce0813f0)(0x7ff9ce0991d0)]), rowset=16
      access([tst_tb.id(0x7ff9ce0797e0)], [tst_tb.create_time(0x7ff9ce07d870)], [tst_tb.customer_id(0x7ff9ce07ce60)], [tst_tb.update_time(0x7ff9ce07e140)],
       [tst_tb.product(0x7ff9ce07ea10)]), partitions(p0)
      is_index_back=false, is_global_index=false, filter_before_indexback[false], 
      range_key([tst_tb.id(0x7ff9ce0797e0)], [tst_tb.create_time(0x7ff9ce07d870)]), range(MIN,MIN ; MAX,MAX)always true

走索引



/*添加索引 1*/

create  index tst_tb_fun_idx  on tst_tb(( lower( md5( concat( upper(customer_id),  'oceanbase')))));

/*
执行 select * from tst_view where customer_id='366330e31189acd28639de9dd7b29cb1'; 
相当于
select id,customer_id,create_time,update_time,product from tst_ta where customer_id='366330e31189acd28639de9dd7b29cb1'
union all
select id,
  lower(md5(concat(upper(customer_id), 'oceanbase'))) AS customer_id,
  create_time,update_time,product from tst_tb where lower(md5(concat(upper(customer_id), 'oceanbase')))='366330e31189acd28639de9dd7b29cb1';

而不是 select * from tst_tb where customer_id='366330e31189acd28639de9dd7b29cb1';
*/


/* 执行计划 */
explain  extended  select *  from tst_view  where customer_id= '366330e31189acd28639de9dd7b29cb1';
============================================================================
|ID|OPERATOR              |NAME                      |EST.ROWS|EST.TIME(us)|
----------------------------------------------------------------------------
|0 |EXCHANGE IN REMOTE    |                          |2       |22          |
|1 |└─EXCHANGE OUT REMOTE |                          |2       |19          |
|2 |  └─UNION ALL         |                          |2       |14          |
|3 |    ├─TABLE RANGE SCAN|tst_ta(ob_idx_customer_id)|1       |7           |
|4 |    └─TABLE RANGE SCAN|tst_tb(tst_tb_fun_idx)    |1       |8           |
============================================================================
Outputs & filters:
-------------------------------------
  0 - output([UNION([1])(0x7fd63d894110)], [UNION([2])(0x7fd63d8944d0)], [UNION([3])(0x7fd63d894890)], [UNION([4])(0x7fd63d894c50)], [UNION([5])(0x7fd63d895010)]), filter(nil)
  1 - output([UNION([1])(0x7fd63d894110)], [UNION([2])(0x7fd63d8944d0)], [UNION([3])(0x7fd63d894890)], [UNION([4])(0x7fd63d894c50)], [UNION([5])(0x7fd63d895010)]), filter(nil)
  2 - output([UNION([1])(0x7fd63d894110)], [UNION([2])(0x7fd63d8944d0)], [UNION([3])(0x7fd63d894890)], [UNION([4])(0x7fd63d894c50)], [UNION([5])(0x7fd63d895010)]), filter(nil), rowset=16
  3 - output([tst_ta.id(0x7fd63d864850)], [tst_ta.customer_id(0x7fd63d865120)], [tst_ta.create_time(0x7fd63d8659f0)], [tst_ta.update_time(0x7fd63d8662c0)],
       [tst_ta.product(0x7fd63d866b90)]), filter(nil), rowset=16
      access([tst_ta.__pk_increment(0x7fd63d8a5180)], [tst_ta.id(0x7fd63d864850)], [tst_ta.customer_id(0x7fd63d865120)], [tst_ta.create_time(0x7fd63d8659f0)],
       [tst_ta.update_time(0x7fd63d8662c0)], [tst_ta.product(0x7fd63d866b90)]), partitions(p0)
      is_index_back=true, is_global_index=false, 
      range_key([tst_ta.customer_id(0x7fd63d865120)], [tst_ta.__pk_increment(0x7fd63d8a5180)]), range(366330e31189acd28639de9dd7b29cb1,MIN ; 366330e31189acd28639de9dd7b29cb1,
      MAX), 
      range_cond([tst_ta.customer_id(0x7fd63d865120) = '366330e31189acd28639de9dd7b29cb1'(0x7fd76aeda000)(0x7fd76aed95e0)])
  4 - output([tst_tb.id(0x7fd63d886840)], [lower(md5(concat(upper(tst_tb.customer_id(0x7fd63d87ddf0))(0x7fd63d888710), 'oceanbase')(0x7fd63d887e40))(0x7fd63d887570))(0x7fd63d886ca0)],
       [tst_tb.create_time(0x7fd63d88a480)], [tst_tb.update_time(0x7fd63d88ad50)], [tst_tb.product(0x7fd63d88b620)]), filter(nil), rowset=16
      access([tst_tb.id(0x7fd63d886840)], [tst_tb.create_time(0x7fd63d88a480)], [tst_tb.customer_id(0x7fd63d87ddf0)], [tst_tb.update_time(0x7fd63d88ad50)],
       [tst_tb.product(0x7fd63d88b620)]), partitions(p0)
      is_index_back=true, is_global_index=false, 
      range_key([tst_tb.SYS_NC21$(0x7fd63d879390)], [tst_tb.id(0x7fd63d886840)], [tst_tb.create_time(0x7fd63d88a480)]), range(366330e31189acd28639de9dd7b29cb1,
      MIN,MIN ; 366330e31189acd28639de9dd7b29cb1,MAX,MAX), 
      range_cond([tst_tb.SYS_NC21$(0x7fd63d879390) = '366330e31189acd28639de9dd7b29cb1'(0x7fd76aedaeb0)(0x7fd76aeda490)])

tst_tb.customer_id='...'的执行计划

tst_tb.lower(md5(concat(upper(customer_id), 'oceanbase')))='...'的执行计划

以上就是 OceanBase 函数索引的核心内容, 如果你在操作中遇到问题,或是有独到的优化建议,欢迎在评论区留言分享,后续我们还会分享更多OceanBase / MySQL 性能优化秘籍,下次见~

更多技术分享可关注



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047467/viewspace-3105536/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
专注于企业信息科技战略咨询、数据中心规划及运维、智能化软件产品研发,致力于为金融、能源、电信、制造等行业提供智能的业务永续及流程自动化解决方案。

注册时间:2025-09-08

  • 博文量
    89
  • 访问量
    86707