目录
-
- 零、前言
- 一、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 数据类型类问题:
- 字符类型varchar需要指定位数,默认位数为1,会导致 导入数据为空;
- 其它的类型映射遇到的映射关系,遇到的类型处理映射关系整理如下,其中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 数据导出阶段:
- 默认通过【select * from table_name limit num offset offnum 】的形式进行大文件分拆,不指定排序会导致数据导出重复。这应该是大部分数据库的通病,需要注意先对数据按指定字段排序,再移动分块,就可以避免,当然就需要对该表多少有一些熟悉度,诸如主键等进行了解;
- 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)
三、小结
初步测试上述问题解决方案运行可行,后续遇到新问题再进行补充更新。现有的豆包之类的工具,着实提高了问题解决的效率,从而让我们有了更多的思考时间。拥抱新工具,喜迎新未来。