PolarDB-X 1.0-SQL 手册-拆分函数使用说明-STR_HASH

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 本文将介绍STR_HASH函数使用方式。

注意事项

使用STR_HASH做拆分的表仅适用于点查场景,如果在业务中范围查询,则会接直接触发全表扫描导致慢查询。

使用限制

  • 拆分键的数据类型需为字符串类型(CHAR或VARCHAR)。
  • 不支持在建表完成后再调整STR_HASH的参数。
  • PolarDB-X的实例版本需为5.3.5或以上,关于实例版本请参见版本说明

使用场景

  • 实现一个分表(或分库)只对应一个拆分表键的取值(字符串类型)的精准路由效果。例如,某个互联网金融应用是按年月(YYYYMM)分库,然后按订单号分表,该应用的订单号有个特点,就是订单号的最后3位字符串是一个整数,其取值范围是000~999。该应用的需求是需要在一个物理分库内,要将订单号后3位的每一个数值只单独路由到一个物理分表。那么,该应用分库采用YYYYMM,然后分表采用拆分函数STR_HASH,每个库1024个分表,就可以达到效果。具体的SQL语句如下:
create table test_str_hash_tb (    
    id int NOT NULL AUTO_INCREMENT,
    order_id varchar(30) NOT NULL, 
    create_time datetime DEFAULT NULL,
    primary key(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
dbpartition by YYYYMM(`create_time`) 
tbpartition by STR_HASH(`order_id`, -1, 3, 1) tbpartitions 1024;
  • 应用采用这样建表SQL,原因是分表的字符串截取后3位并转换为整数(整数范围是000~999)后再取模做分表路由(共1024个分表),其路由结果能保证每一个物理分表只对一个拆分建的取值。而原来PolarDB-X默认拆分函数HASH无法达到这样的效果,是因为字符串经过hashCode计算后的整数是不可预知的,有可能会出现一个物理分表要对应多个不同拆分建的取值。
  • 典型的点查场景STR_HASH拆分函数适用于使用字符串类型作为拆分键并且是绝大部分都是点查的场景,如根据ID查交易订单、物流订单等。

函数定义

STR_HASH函数通过指定字符串的开始位置下标与结束下标,以截取拆分键的字符串的某段子串,然后将其作为字符串(或整数)输入进行分库分表的路由计算,计算具体的物理分片,具体函数如下所示:

STR_HASH( shardKey [, startIndex, endIndex [, valType [, randSeed ] ] ] )

表 1. 参数说明

参数 说明
shardKey 拆分键列的列名。
startIndex 目标子串的开始位置的下标。取值从0开始(即原字符串的第1个字符的下标用0表示),默认值为-1(即不做任何截取)。
endIndex 目标子串的结束位置的下标。取值从0开始(即原字符串的第1个字符的下标用0表示),默认值为-1(即不做任何截取)。

说明startIndexendIndex时需注意如下几种取值情况:

  • startIndex == j && endIndex = k (j>=0, k>=0 ,k>j)时,表示截取原字符串的[ j, k )区间的字符串作为子串。例如:
    • 对于字符串ABCDEFG,子串区间[1,5)的值是BCDE
    • 对于字符串ABCDEFG,,子串区间[2,2)的值是''
    • 对于字符串ABCDEFG,子串区间[4,100)的值是EFG
    • 对于字符串 ABCDEFG,子串区间[100,105)的值是''
  • startIndex == -1 && endIndex = k (k>=0)时,表示截取原字符串最后k个字符作为子串,原字符串不足k个字符则直接获取整个字符串。
  • startIndex = k && endIndex == -1 (k>=0)时,表示截取原字符串开头k个字符作为子串,原字符串不足k个字符则直接获取整个字符串。
  • startIndex == -1 && endIndex == -1时, 表示不做任何截取,子串与原字符串完全一致。
valType 表示截取后的子串在计算分库分表时所使用的类型,取值范围如下:
  • 0(默认值):表示PolarDB-X将截取后的子串当作字符串类型来计算路由。
  • 1:表示PolarDB-X将截取后的子串当作整数类型来计算路由(子串面值的整数不能大于9223372036854775807,也不支持浮点数
randSeed 当子串以字符串类型来计算路由的哈希值时PolarDB-X所使用的随机种子的值,通常不用需要填写,仅当用于使用默认值随机种子(randSeed=31)的STR_HASH在实际业务中出现路由不均衡的场景,达到用哈希均衡数据的目的。该参数默认值为31,可取其他值(如131,13131,1313131等)。

说明

  • 仅当valType取值为0时,才支持配置该参数。
  • 该参数调整后您需要手动将所有数据导出来,再将新的拆分算法导入数据(即您需要对数据进行重分布)。

使用示例

假设order_id的类型为VARCHAR(32),现在需要将order_id作为拆分键,计划分4个库,分8个表。

  • 假设需要使用order_id的最后4位的字符串作为整数来计算分库分表路由,则您可以使用如下SQL进行建表。
create table test_str_hash_tb (    
    id int NOT NULL AUTO_INCREMENT,
    order_id varchar(32) NOT NULL, 
    create_time datetime DEFAULT NULL,
    primary key(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
dbpartition by STR_HASH(`order_id`, -1, 4, 1) 
tbpartition by STR_HASH(`order_id`, -1, 4, 1) tbpartitions 2;
  • 假设需要截取order_id的第3个字符(即starIndex=2)与第7个字符(即endIndex=7)之间子串来计算分库分表路由,则您可以使用如SQL进行建表。
create table test_str_hash_tb (    
    id int NOT NULL AUTO_INCREMENT,
    order_id varchar(32) NOT NULL, 
    create_time datetime DEFAULT NULL,
    primary key(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
dbpartition by STR_HASH(`order_id`, 2, 7) 
tbpartition by STR_HASH(`order_id`, 2, 7) tbpartitions 2;
  • 假设需要截取order_id的前5个字符串作为子串来计算分库分表路由,则您可以使用如SQL进行建表。
create table test_str_hash_tb (    
    id int NOT NULL AUTO_INCREMENT,
    order_id varchar(32) NOT NULL, 
    create_time datetime DEFAULT NULL,
    primary key(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 
dbpartition by STR_HASH(`order_id`, 5, -1) 
tbpartition by STR_HASH(`order_id`, 5, -1) tbpartitions 2;

常见问题

Q:dbpartition by STR_HASH(order\_id)dbpartition by HASH(order\_id)有什么区别?

A:两者虽然都是直接根据字符串取值做分库分表的哈希路由,但是两者的分库分表的路由算法实现不一样。前者支持用户建表时自行设定截取子串相关参数,且在根据字符串的哈希值计算分库分表路由时是基于UNI_HASH算法进行计算;而后者是只对字符串的哈希值做简单取模。

相关实践学习
快速体验PolarDB开源数据库
本实验环境已内置PostgreSQL数据库以及PolarDB开源数据库:PolarDB PostgreSQL版和PolarDB分布式版,支持一键拉起使用,方便各位开发者学习使用。
相关文章
|
1月前
|
SQL Oracle 关系型数据库
SQL优化-使用联合索引和函数索引
在一次例行巡检中,发现一条使用 `to_char` 函数将日期转换为字符串的 SQL 语句 CPU 利用率很高。为了优化该语句,首先分析了 where 条件中各列的选择性,并创建了不同类型的索引,包括普通索引、函数索引和虚拟列索引。通过对比不同索引的执行计划,最终确定了使用复合索引(包含函数表达式)能够显著降低查询成本,提高执行效率。
|
1月前
|
SQL 数据库 数据库管理
数据库SQL函数应用技巧与方法
在数据库管理中,SQL函数是处理和分析数据的强大工具
|
1月前
|
SQL 数据库 索引
SQL中COUNT函数结合条件使用的技巧与方法
在SQL查询中,COUNT函数是一个非常常用的聚合函数,用于计算表中满足特定条件的记录数
|
1月前
|
SQL 关系型数据库 MySQL
SQL日期函数
SQL日期函数
|
3月前
|
SQL 数据库
|
2月前
|
SQL 关系型数据库 C语言
PostgreSQL SQL扩展 ---- C语言函数(三)
可以用C(或者与C兼容,比如C++)语言编写用户自定义函数(User-defined functions)。这些函数被编译到动态可加载目标文件(也称为共享库)中并被守护进程加载到服务中。“C语言函数”与“内部函数”的区别就在于动态加载这个特性,二者的实际编码约定本质上是相同的(因此,标准的内部函数库为用户自定义C语言函数提供了丰富的示例代码)
|
3月前
|
SQL 数据采集 数据处理
如何在 SQL Server 中使用 LEN 函数
【8月更文挑战第9天】
160 1
如何在 SQL Server 中使用 LEN 函数
|
3月前
|
SQL 数据处理 数据库
SQL中的函数有哪些类型
【8月更文挑战第20天】SQL中的函数有哪些类型
38 1
|
3月前
|
SQL 监控 索引
如何在 SQL Server 中使用 `PATINDEX` 函数
【8月更文挑战第8天】
389 9
|
3月前
|
SQL 数据处理 数据库

相关产品

  • 云原生分布式数据库 PolarDB-X