clickhouse数据库表和doris数据库表迁移starrocks数据库时建表注意事项总结

目录

    • 零、前言
    • 一、clickhouse数据库表在starrocks数据库建表时问题总结
      • [1.1 数据类型类问题:](#1.1 数据类型类问题:)
      • [1.2 数据导出阶段:](#1.2 数据导出阶段:)
    • [二、doris 数据库表在starrocks数据库建表时问题总结](#二、doris 数据库表在starrocks数据库建表时问题总结)
      • [2.1 properties不支持的属性(直接删除):](#2.1 properties不支持的属性(直接删除):)
      • [2.2 properties需修改属性](#2.2 properties需修改属性)
      • [2.3 properties:doris建表语句分区明细,starrocks数据不需要明确设定,会自动更新](#2.3 properties:doris建表语句分区明细,starrocks数据不需要明确设定,会自动更新)
      • [2.4 分桶设置问题](#2.4 分桶设置问题)
      • [2.5 索引设置问题](#2.5 索引设置问题)
      • [2.6 python程序针对上述问题解决程序](#2.6 python程序针对上述问题解决程序)
    • 三、小结

零、前言

这可能是个技术选型的问题,前期各自为营,所以整个企业内部,数据库类型五花八门,相互之间数据也很难对齐引用。随着业务等等大势所趋,需要整合全公司资源,因此由来了这个数据资源迁移。针对迁移过程中的建表方面,作一总结,以备后续问题原因排查和进一步整改,让过程有迹可循。

一、clickhouse数据库表在starrocks数据库建表时问题总结

1.1 数据类型类问题:

  1. 字符类型varchar需要指定位数,默认位数为1,会导致 导入数据为空;
  2. 其它的类型映射遇到的映射关系,遇到的类型处理映射关系整理如下,其中key为clickhouse中的数据类型,value为对应的starrocks数据库类型:

{

'Date': 'DATE',

'Nullable(Date)': 'DATE NULL',

'DateTime': 'DATETIME',

'Nullable(DateTime)': 'DATETIME NULL',

'Float64': 'FLOAT',

'Float32': 'FLOAT',

'Nullable(Float32)': 'FLOAT NULL',

'Nullable(Float64)': 'FLOAT NULL',

'Int32': 'INT', 'UInt32': 'INT',

'UInt16': 'INT',

'Int64': 'INT',

'Nullable(Int32)': 'INT NULL',

'Nullable(Int8)': 'INT NULL',

'Nullable(UInt32)': 'INT NULL',

'Nullable(Int64)': 'INT NULL',

'String': 'varchar(65535)',

'Nullable(String)': 'varchar(65535) NULL'

}

1.2 数据导出阶段:

  1. 默认通过【select * from table_name limit num offset offnum 】的形式进行大文件分拆,不指定排序会导致数据导出重复。这应该是大部分数据库的通病,需要注意先对数据按指定字段排序,再移动分块,就可以避免,当然就需要对该表多少有一些熟悉度,诸如主键等进行了解;
  2. clickhouse数据库通过【clickhouse-client】导出parquet文件,对于 日期时间类型 ,不明确通过 cast(字段名称 as datetime) 进行设定,会将日期时间转换为时间戳;

二、doris 数据库表在starrocks数据库建表时问题总结

doris数据库表DDL在starrocks中存在最主要的问题就是 properties属性 修改适配,字段类型目前所用类型全部可以在starrocks数据库中适配使用,所以无需更改。问题总结集中在properties方面。

2.1 properties不支持的属性(直接删除):

复制代码
	"is_being_synced" = "false",
	"disable_auto_compaction" = "false",
	"enable_single_replica_compaction" = "false"
	"light_schema_change" = "true" 
	"dynamic_partition.create_history_partition" = "false",
	"dynamic_partition.storage_medium" = "HDD",
	"dynamic_partition.storage_policy" = "",
	"dynamic_partition.hot_partition_num" = "0",
	"dynamic_partition.reserved_history_periods" = "NULL",
	"enable_mow_light_delete" = "false"
	"light_schema_change" = "true"

2.2 properties需修改属性

复制代码
	"replication_allocation" = "tag.location.default: 3"     				改为 "replication_num" = "3",
	"dynamic_partition.replication_allocation" = "tag.location.default: 3"  改为 "dynamic_partition.replication_num" = "3" 
	"dynamic_partition.history_partition_num" = "1200" starrocks数据库默认动态分区上限500,目前直接删除该属性

2.3 properties:doris建表语句分区明细,starrocks数据不需要明确设定,会自动更新

复制代码
	a.PARTITION BY RANGE(`xxx`) 之后的明细分区,全部删除,不需指定,但括号需要保留。如:PARTITION BY RANGE(`xxx`)()
	b."dynamic_partition.start" = "-2147483648"  删除,不需指定

2.4 分桶设置问题

复制代码
	DISTRIBUTED BY HASH(`vin`) BUCKETS AUTO ,starrocks不支持auto属性,直接设定具体数字,eg:10

2.5 索引设置问题

复制代码
	索引类型:INDEX idx_vin (vin) USING INVERTED COMMENT '',starrocks不支持 INVERTED ,将索引类型修改为: USING BITMAP 即可。

2.6 python程序针对上述问题解决程序

python 复制代码
# 删除分区明细
# 匹配分区定义部分,从(PARTITION开始到三个连续的右括号结束
# re.IGNORECASE:使正则表达式匹配时忽略大小写。 
# re.DOTALL:使 . 匹配任意字符,包括换行符。
pattern = r"\(PARTITION.*\){3}"
# step_one_sql = re.sub(pattern, "", sql, flags=re.IGNORECASE | re.DOTALL) # 这个会将分区明细全部剔除,且没有保留RANGE之后的明细需要的括号
step_one_sql = re.sub(pattern, "()", sql, flags=re.IGNORECASE | re.DOTALL) # 对上述sql的修正

# 正则表达式匹配并替换 BUCKETS AUTO 为 BUCKETS 10
step_one_sql = re.sub(r" BUCKETS AUTO", r" BUCKETS 10", step_one_sql) 

# 正则表达式匹配索引类型:并替换 
step_one_sql = re.sub(r" USING INVERTED ", r" USING BITMAP ", step_one_sql) 

# 正则表达式匹配 PROPERTIES 部分
pattern = r"(PROPERTIES\s*\([\s\S]*?\);)"
match = re.search(pattern, step_one_sql)    
if match:
	# 提取 PROPERTIES 部分
	properties_content = match.group(1)

	# 删除不支持的属性
	properties_content = re.sub(r'"is_being_synced"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"disable_auto_compaction"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"enable_single_replica_compaction"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"light_schema_change"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"dynamic_partition\.create_history_partition"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"dynamic_partition\.storage_medium"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"dynamic_partition\.storage_policy"\s*=\s*""\s*,?', '', properties_content)
	properties_content = re.sub(r'"dynamic_partition\.hot_partition_num"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"dynamic_partition\.reserved_history_periods"\s*=\s*"\w+"\s*,?', '', properties_content)
	properties_content = re.sub(r'"dynamic_partition\.start"\s*=\s*"[\w\d-]*"\s*,?', '', properties_content)
	properties_content = re.sub(r'"dynamic_partition\.history_partition_num"\s*=\s*"[\w\d-]*"\s*,?', '', properties_content)
	properties_content = re.sub(r'"enable_mow_light_delete"\s*=\s*"\w+"\s*,?', '', properties_content)
	

	# 修改属性
	properties_content = re.sub(
		r'"replication_allocation"\s*=\s*"tag\.location\.default:\s*\d+"',
		'"replication_num" = "3"',
		properties_content
	)
	# properties_content = re.sub(
	#     r'"light_schema_change"\s*=\s*"\w+"',
	#     '"enable_light_schema_change" = "true"',
	#     properties_content
	# )
	properties_content = re.sub(
		r'"dynamic_partition.replication_allocation"\s*=\s*"tag\.location\.default:\s*\d+"',
		'"dynamic_partition.replication_num" = "3"',
		properties_content
	)
	# properties_content = re.sub(
	#     r'"dynamic_partition.history_partition_num" = "-1"',
	#     '"dynamic_partition.history_partition_num" = "30"',
	#     properties_content
	# )

	# 清理多余的逗号和空白行
	properties_content = re.sub(r",\s*,", ",", properties_content)  # 清理多余的逗号
	properties_content = re.sub(r"\n\s*\n", "\n", properties_content)  # 清理空白行


	"""最后一个属性后 会有逗号,进行替换"""
	# 正则表达式:匹配 PROPERTIES 块中的最后一个逗号
	pattern = r'(?s)(PROPERTIES\s*\(.*?)(,\s*\);)'  # (?s) 表示单行模式,匹配换行符
	# 使用 re.sub 进行替换
	def remove_last_comma(match):
		# 如果匹配到逗号,则删除
		return match.group(1) + match.group(2).replace(',', '')
	
	properties_content = re.sub(pattern, remove_last_comma, properties_content)
	
	# 更新回 SQL 语句
	updated_sql = step_one_sql.replace(match.group(1), properties_content)

三、小结

初步测试上述问题解决方案运行可行,后续遇到新问题再进行补充更新。现有的豆包之类的工具,着实提高了问题解决的效率,从而让我们有了更多的思考时间。拥抱新工具,喜迎新未来。

相关推荐
互联网搬砖老肖2 小时前
运维打铁: MongoDB 数据库集群搭建与管理
运维·数据库·mongodb
典学长编程3 小时前
数据库Oracle从入门到精通!第四天(并发、锁、视图)
数据库·oracle
极限实验室4 小时前
搭建持久化的 INFINI Console 与 Easysearch 容器环境
数据库
白仑色5 小时前
Oracle PL/SQL 编程基础详解(从块结构到游标操作)
数据库·oracle·数据库开发·存储过程·plsql编程
程序猿小D6 小时前
[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的个人财务管理系统,推荐!
java·数据库·mysql·spring·毕业论文·ssm框架·个人财务管理系统
钢铁男儿7 小时前
C# 接口(什么是接口)
java·数据库·c#
__风__8 小时前
PostgreSQL kv(jsonb)存储
数据库·postgresql
轩情吖8 小时前
Qt的第一个程序(2)
服务器·数据库·qt·qt creator·qlineedit·hello world·编辑框
Databend8 小时前
Databend 产品月报(2025年6月)
数据库