TDengine 存储引擎剖析:数据文件与索引设计(一)
TDengine 存储引擎简介
在物联网、工业互联网等快速发展的今天,时间序列数据呈爆发式增长。这些数据具有产生频率高、依赖采集时间、测点多信息量大等特点,对数据存储和处理提出了极高要求。TDengine 作为一款高性能、分布式、支持 SQL 的时序数据库,应运而生,在众多领域得到了广泛应用。其卓越的性能很大程度上得益于精心设计的存储引擎,该存储引擎针对时序数据的特性进行了深度优化,能够高效地处理海量时间序列数据的存储与查询,为相关应用提供了强大的数据支持 。
TDengine 数据文件设计
数据文件结构剖析
TDengine 的数据文件采用了独特的四位一体的文件组结构,这种设计是其高效存储和快速查询的关键。每个文件组包含 .data、.last(在 3.0 版本中已更名为 .stt 文件 )、.head 和 .sma 这四类文件,它们各自承担着不同的职责,相互协作,共同完成数据的存储与管理。
.data 文件是核心的数据存储文件,它以列存储的方式存放实际的时序数据。这些数据被划分为多个数据块,每个数据块仅属于一张表,这使得数据的存储和读取更加高效。例如,在一个物联网场景中,众多传感器产生的数据会分别存储在各自对应的表的数据块中,这样在查询某个传感器的数据时,可以直接定位到相应的数据块,减少了数据扫描的范围。同时,每个数据块还记录着预计算中的行数数据,也就是预计算中的 count 函数计算结果,这为一些统计查询提供了便利。
.stt 文件(3.0 前为 .last 文件)主要用于保存每一张表从内存落盘到磁盘时的碎片数据,即小于 minrows 的数据。在 2.x 版本中,.last 文件存在一些局限性,比如当文件小于 32k 时,即便其中某表的碎片数据已满足行数要求可合并到 .data 文件,.last 文件也只是追加写入,不会清理这部分数据。而在 3.0 版本中,.stt 文件有了改进,属于同一个超级表的数据会存储在同一个数据块中,且数据块中的数据按照 (uid(表的唯一标识), timestamp, version)递增排列。每次落盘,数据文件组都会生成一个新的 stt 文件,用来存放本次落盘中的散碎数据。当 .stt 文件个数超过一定的阈值 (由建库参数 stt_trigger 控制),则首先将多个 .stt 文件的碎片数据合并后,再根据实际情况决定写入 .data 文件,或写入新的 .stt 文件中。这一改进有效减少了文件碎片化对性能的影响。
.head 文件存储着 .data 文件中数据块的索引信息。在查询时,系统会先加载 .head 文件中的索引信息,通过这些索引可以快速定位到 .data 文件中对应的时序数据,从而返回给用户。BRIN 索引(Block Range Index)在其中发挥了重要作用,它适用于具有天然顺序的数据集,由于不需要再做排序,资源耗费少,非常契合时序数据的查询特点。例如,当查询某个时间段内的数据时,.head 文件中的索引可以帮助系统迅速确定包含该时间段数据的数据块在 .data 文件中的位置,大大提高了查询效率。但需要注意的是,.head 文件的大小会影响查询性能,maxrows 和 minrows 以及 duration 等参数都会对其大小产生影响。比如,同样 1000 行数据,maxrows = 200 需要 5 个数据块,maxrows 为 1000 时只需要 1 块,而每个数据块都需要一条索引信息存储在 .head 文件中;duration 越大,单个数据文件存储的数据量越大,数据块越多,.head 文件也会越大。在实际应用中,曾出现过因 duration 参数设置为 1000 多天,导致数据查询性能严重下降的情况 。
.sma 文件存储着数据块中每列数据的预计算数据。预计算的目的是为了加速查询,尽可能避免从硬盘中读取原始数据。.sma 文件相当于 2.x 后期版本中的 smad 文件,而 smal 文件在 3.0 版本中被移除。通过预计算,在进行一些聚合查询时,如 sum、max、min 等操作,可以直接从 .sma 文件中获取结果,而无需读取大量的原始数据,从而提高了查询速度。
为了更直观地理解,以下是 TDengine 数据文件结构的示意图:
数据写入流程与分区策略
TDengine 的数据写入流程涉及从内存到硬盘的多个步骤,并且采用了基于建库参数 duration(days) 的数据分区策略,这对数据管理和查询有着重要影响。
当数据到达 TDengine 时,首先会被写入内存中的 Vnode Buffer。在这个阶段,数据会按照表进行组织,并在内存中以跳表(skiplist)结构进行索引,以便快速定位和处理。同时,为了保证数据的持久性和一致性,数据也会被写入预写式日志(WAL,Write-Ahead Log)中。WAL 记录了数据到达数据库的顺序,在系统出现故障时,可以通过 WAL 进行数据恢复,确保数据不丢失。
当内存中的数据量达到一定阈值或者满足特定的时间条件时,数据会触发落盘操作,从内存写入硬盘的数据文件中。在落盘过程中,数据会根据建库时设置的 duration(days) 参数进行分区。假设某库 duration 设置为 10 日,那么从 1970 年 1 月 1 日 0 时起,每隔 10 天就会划分一个数据文件组。写入的数据时间戳归属于哪个时间范围,便会写入哪个数据文件组中,即每个数据文件组中都包含了固定时间范围内的数据。例如,2024 年 1 月 1 日到 1 月 10 日的数据会被写入一个数据文件组,1 月 11 日到 1 月 20 日的数据会被写入另一个数据文件组。这种分区策略使得数据的管理更加有序,在进行数据查询和删除时,可以快速定位到相应的数据文件组,提高了操作效率。比如,当需要查询 2024 年 1 月 5 日的数据时,系统可以直接定位到包含 1 月 1 日到 1 月 10 日数据的数据文件组,而无需遍历整个数据库。
在数据写入硬盘的数据文件时,会按照 .data 文件的结构要求,将数据划分为数据块进行存储。每个数据块只属于一张表,并且会记录相关的预计算信息。同时,如果存在小于 minrows 的碎片数据,会被写入 .stt 文件中,等待后续的合并和处理。
乱序数据处理机制
在时序数据库场景下,乱序数据是指时间戳不按照递增顺序到达数据库的数据。虽然在理想情况下,数据应该按照时间顺序依次到达,但在实际应用中,由于各种原因,如设备损坏断电、网络异常、数据补录等,乱序数据的出现是不可避免的。TDengine 针对乱序数据进行了专门的处理,以保证数据存储时的顺序性和查询性能。
TDengine 将乱序数据分为两类:内存乱序数据和硬盘乱序数据。内存乱序数据是指在同一张表的范畴内,时间戳与内存数据的时间范围相交的数据。对于这类乱序数据,TDengine 会在内存中通过为每张表建立一个跳表结构做好排序。例如,创建某表后,先写入了从 1970 年到 2023 年的一小批数据(由于数据量较少不足以触发落盘),当再写入一条 1998 年时间戳的乱序数据时,跳表会对其进行排序,使得数据在内存中以 “1970 - 1998 - 2023” 的顺序有序存在。该排序操作的成本由写入操作承担,但由于内存中保留的只是极少数数据,因此对整体性能影响极小。
硬盘乱序数据是指在同一张表的范畴内,时间戳与硬盘数据的时间范围相交的数据。在硬盘数据写入时,由于 TDengine 通过建库参数 duration(days) 做数据分区,每个数据文件组包含固定时间范围内的数据。当数据落盘时,会根据其时间戳判断所属的数据文件组,并与该数据文件组中已有的数据块的时间范围进行比较,来判断数据是否乱序。例如,假设某表的数据文件组按照 10 天进行分区,当一条数据落盘时,如果其时间戳与当前数据文件组中已有数据块的时间范围没有交集,那么它就是正常数据;如果有交集,则可能是乱序数据。
在 2.0 版本中,如果落盘时的数据和已有数据块时间戳相交,乱序数据会形成一个子块追加在数据文件中,查询时需要把子块的数据读到内存中再做排序。当子块比较多的时候,会影响查询性能。而在 3.0 版本中,经过重新设计,乱序数据和原有数据将会合并重写为新的数据块,以追加的方式写入数据文件中并且重写索引,而旧的数据块则被视为碎片文件。这样一来,处理数据的成本就被转嫁给了落盘操作,对后续的查询基本没有影响。考虑到乱序数据通常是业务上的偶发场景,这种处理方式基本不会造成性能负担。即便是产生了少部分由于乱序带来的碎片数据、无效数据块,也都可以由企业版功能 compact 清除或者重组 。
相关文章:
TDengine 存储引擎剖析:数据文件与索引设计(一)
TDengine 存储引擎简介 在物联网、工业互联网等快速发展的今天,时间序列数据呈爆发式增长。这些数据具有产生频率高、依赖采集时间、测点多信息量大等特点,对数据存储和处理提出了极高要求。TDengine 作为一款高性能、分布式、支持 SQL 的时序数据库&am…...
CentOS更换yum源
CentOS更换yum源 视频教程: https://www.bilibili.com/video/BV1yWaSepE6z/?spm_id_from333.1007.top_right_bar_window_history.content.click 步骤: 第一步: cd /etc/yum.repos.d第二步:cp CentOS-Base.repo CentOS-Base.repo…...
【Kubernetes基础--持久化存储原理】--查阅笔记5
目录 持久化存储机制PV 详解PV 关键配置参数PV 生命周期的各个阶段 PVC 详解PVC 关键配置参数PV 和 PVC 的生命周期 StorageClass 详解StorageClass 关键配置参数设置默认的 StorageClass 持久化存储机制 k8s 对于有状态的容器应用或对数据需要持久化的应用,不仅需…...
数据库子查询实验全解析
目录 一、验证性实验:夯实基础(一)查询同班学生信息(二)查询成绩相关信息(三)查询课程选课人数(四)相关子查询(五)EXISTS嵌套子查询(六…...
HTML:表格数据展示区
<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>人员信息表</title><link rel"styl…...
webgl入门实例-08索引缓冲区的基本概念
WebGL 索引缓冲区 (Index Buffer) 索引缓冲区(也称为元素数组缓冲区)是WebGL中一种优化渲染性能的重要机制,它允许您重用顶点数据来绘制复杂的几何图形。 基本概念 索引缓冲区的工作原理: 您创建一个顶点缓冲区(包含所有顶点数据)然后创建一个索引缓…...
大数据应用开发——大数据平台集群部署
目录 前言 目录 基础环境 安装虚拟机 基础环境 VMware Workstation 虚拟机版本 : centos7 主机名 ip 用户名 密码 master192.168.245.100root123456slave1192.168.245.101root123456slave2192.168.245.102root123456 安装虚拟机 安装 名称、路径自己改 我有16核&…...
GPT对话UI--通义千问API
GPT对话UI 项目介绍 一个基于 GPT 的智能对话界面,提供简洁优雅的用户体验。本项目使用纯前端技术栈实现,无需后端服务器即可运行。 功能特点 💬 实时对话:支持与 AI 进行实时对话交互🌓 主题切换:支持…...
智能体数据分析
数据概览: 展示智能体的累计对话次数、累计对话用户数、对话满意度、累计曝光次数。数据分析: 统计对话分析、流量分析、用户分析、行为分析数据指标,帮助开发者完成精准的全面分析。 ps:数据T1更新,当日12点更新前一天…...
泛型算法——只读算法(一)
在 C 标准库中,泛型算法的“只读算法”指那些 不会改变它们所操作的容器中的元素,仅用于访问或获取信息的算法,例如查找、计数、遍历等操作。 accumulate std::accumulate()是 C 标准库**numeric**头文件中提供的算法,用于对序列…...
树莓派超全系列教程文档--(29)config.txt介绍
config.txt介绍 什么是 config.txt ?文件格式高级功能include条件过滤 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 什么是 config.txt ? Raspberry Pi 设备使用名为 config.txt 的配置文件,而不是传统 PC …...
第十六届蓝桥杯大赛软件赛省赛 C++ 大学 B 组 部分题解
赛时参加的是Python组,这是赛后写的题解,还有两题暂时还不会,待更新 题目链接题目列表 - 洛谷 | 计算机科学教育新生态 A 移动距离 答案:1576 C 可分解的正整数 Python3 import itertools from functools import cmp_to_ke…...
C++栈与堆内存详解:Visual Studio实战指南
C++栈与堆内存详解:Visual Studio实战指南 IDE环境:Visual Studio 2022 一、内存分区与核心概念 在C++程序中,内存分为**栈(Stack)和堆(Heap)**两大核心区域,两者的管理方式、生命周期和适用场景差异显著。 1. 栈内存(Stack Memory) • 特性: • 自动管理:由编…...
在Ubuntu服务器上部署xinference
一、拉取镜像 docker pull xprobe/xinference:latest二、启动容器(GPU) docker run -d --name xinference -e XINFERENCE_MODEL_SRCmodelscope -p 9997:9997 --gpus all xprobe/xinference:latest xinference-local -H 0.0.0.0 # 启动一个新的Docker容…...
非洲电商争夺战:中国闪电战遭遇本土游击队的降维打击
2024年5月,南非电商市场爆发史诗级对决——Temu闪电突袭下载量破百万,却在30天内遭遇Takealot的本土化反击致留存率腰斩。这场价值500亿美元市场的攻防战,揭开了非洲电商最残酷的生存法则:低价利刃砍不动本土化铁壁。 一、跨境模式…...
亚瑟阿伦36问
问 36 个问题,你就能爱上一个人,对方也能爱上你。 第一组 聚焦个人背景与价值观 例如“你最感激生命中的什么?”、“如果可以改变成长经历,你会改变什么?” 1、如果可以跟世上任何人共进晚餐,你会选择谁&…...
Ubuntu 20.04.6编译安装COMFAST CF-AX90无线网卡驱动
目录 0 前言 1 CF-AX90无线网卡驱动 1.1 驱动下载 1.2 驱动准备 2 编译安装驱动 2.1 拷贝驱动依赖到系统 2.2 驱动安装编译 3 重启 0 前言 COMFAST CF-AX90或者说AIC8800D80的Linux版本驱动不支持高版本的linux内核,实测目前仅支持最高5.15的内核。Ubuntu2…...
函数的极限与连续(强化和真题)
强化错题如下:...
4.15【Q】netsafe
我正在学习网络空间安全,” Cookie:使用防hash技术防御SYN泛洪攻击,减少服务器内存消耗“什么意思?什么是SYN泛洪攻击?什么又是防hash技术防御? ?详细解释,越细节越好 连接成功率 …...
多个路由器互通(静态路由)无单臂路由(简单版)
多个路由器互通(静态路由)无单臂路由(简单版) 开启端口并配ip地址 维护1 Router>en Router#conf t Router(config)#int g0/0 Router(config-if)#no shutdown Router(config-if)#ip address 192.168.10.254 255.255.255.0 Ro…...
opencv HSV的具体描述
色调H: 使用角度度量,取值范围为0\~360,从红色开始按逆时针方向计算,红色为0,绿色为120,蓝色为240。它们的补色是:黄色为60,青色为180,紫色为300。通过改变H的值&#x…...
ubuntu磁盘挂载
1、查看磁盘设备及分区 命令:列出所有块设备(磁盘及分区) lsblk 0表示此块未挂载 2、格式化分区 sudo mkfs.ext4 /dev/sdb 注意sdb换成自己的块名称 3、创建挂载点目录 sudo mkdir -p /mnt/data4、永久挂载 sudo blkid /dev…...
Visual Studio C++引入第三方库
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要整理visual studio C导入第三方库的注意事项与操作 bilibili配套视频:【visual studio C导入第三方库-哔哩哔哩】 https://b23.tv/vphfXnv 运行库选项 右键项目 -> 属性 -> C/C ->代码生成->…...
2025中国移动云智算大会回顾:云智变革,AI+跃迁
4月10日,2025中国移动云智算大会在苏州举办。会上,中国移动开启“由云向智”新范式,以“智”为核心开辟算网新生态,彰显其在AI新时代的战略远见与技术引领力。 “云智算”将如何通过算网基础设施与人工智能核心技术的深度融合&am…...
海珠区公示人工智能大模型应用示范区第二批资金奖励企业名单,助力产业蓬勃发展
2025 年 4 月 15 日,广州琶洲人工智能与数字经济试验区管理委员会在广州市海珠区人民政府门户网站发布重要通知,对人工智能大模型应用示范区政策兑现工作(第二批)(大模型专题)资金奖励企业名单予以公示。这…...
golang处理时间的包time一次性全面了解
本文旨在对官方time包有个全面学习了解。不钻抠细节,但又有全面了解,重点介绍常用的内容,一些低频的可能这辈子可能都用不上。主打一个花最少时间办最大事。 Duration对象: 两个time实例经过的时间,以长度为int64的纳秒来计数。 常见的durati…...
文件的加密与解密学习笔记
一些可能想知道的: cryptography库:密码学工具包 Fernet 是crytography 里的一个模块,用于对称加密 with open() as file #为了保证无论是否出错都能正确地关闭文件,与try...finally...相同 open() #用于读文件(默认…...
《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端
《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端 《TCP/IP网络编程》学习笔记 | Chapter 24:制作 HTTP 服务器端HTTP 概要理解 Web 服务器端无状态的 Stateless 协议请求消息(Request Message)的结构响应消息&#x…...
Apache POI(笔记)
介绍: 坐标: 写入Excel表格: 读取Excel表格:...
Table类型的表单
形如下面的图片 1 label与prop属性 const columns[{label: "文件名",prop: "fileName",scopedSlots: "fileName",},{ label: "删除时间",prop: "recoveryTime",width: "200",},{ label: "大小",prop:…...
Spring 中的验证、数据绑定和类型转换
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
【技术派后端篇】canal实现MySQL/Redis缓存一致性
1 前言 在探讨如何利用canal实现MySQL/Redis缓存一致性之前,强烈建议大家先阅读以下几篇相关文章,因为本文是基于这些文章的基础上展开的: 《深度剖析 MySQL 与 Redis 缓存一致性:理论、方案与实战》 :该文详细阐述了…...
华清远见STM32F103智能小车重磅上线!循迹避障红外遥控WiFi远程控制,0基础小白从入门到单片机软硬件项目实战!
STM32F103智能云控小车是由华清远见倾力打造的一款多功能智能小车,专为高校教学、学生毕业设计、创新竞赛、单片机入门学习及项目实践量身定制。这款小车集红外遥控、远程物联网控制、智能巡线、高精度避障和交互式显示屏五大核心功能于一体,融合了物联网…...
李飞飞团队新作WorldScore:“世界生成”能力迎来统一评测,3D/4D/视频模型同台PK
从古老神话中对世界起源的幻想,到如今科学家们在实验室里对虚拟世界的构建,人类探索世界生成奥秘的脚步从未停歇。如今,随着人工智能和计算机图形学的深度融合,我们已站在一个全新的起点,能够以前所未有的精度和效率去…...
seaborn库详解
Seaborn 是一个基于 Python 的统计数据可视化库,它建立在 matplotlib 之上,旨在提供更高级、更美观、更具统计意义的可视化功能。 CONTENT 1. 单变量分布可视化功能代码 2. 双变量联合分布可视化功能代码 3. 分类数据柱状图可视化功能代码 4. 箱线图可视…...
UNACMS PHP对象注入漏洞复现(CVE-2025-32101)(附脚本)
免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 前言…...
应用篇02-镜头标定(上)
本节主要介绍相机的标定方法,包括其内、外参数的求解,以及如何使用HALCON标定助手实现标定。 计算机视觉——相机标定(Camera Calibration)_摄像机标定-CSDN博客 1. 原理 本节介绍与相机标定相关的理论知识,不一定全,可以参考相…...
游戏引擎学习第230天
回顾并为今天的内容定下基调 今天是我们进行“排序”工作的第二天。昨天我们在渲染器中实现了排序功能。这其实是从一开始就知道必须做的事情,只是一直没有合适的时机。而昨天终于迎来了这个时机,不知道为什么,可能就是突然有了冲动和想法&a…...
3.串口通信之SPI
—>1.串口通信之UART见这篇<— —>2.串口通信之IIC见这篇<— 1.SPI特点 SPI(Serial Peripheral Interface)即串行外设接口,有4条总线,分别是SCLK(SPI Clock),MISO(Master Input Slave Output),MOSI(Mast…...
无人机姿态稳定与动态控制模块概述!
一、设计难点 1. 动态算力需求与硬件能力的不匹配** 无人机边缘计算设备通常受限于体积和重量,导致其计算单元(如CPU、GPU)的算力有限,难以应对突发的高负载任务(如实时图像处理、AI推理)。 挑战&am…...
【shell】终端文本的颜色和样式打印
在Shell脚本中,\033[XXm 是 ANSI转义序列,用于控制终端文本的颜色和样式。以下是完整的颜色和样式代码列表: 1. 基本格式 echo -e "\033[CODEm你的文本\033[0m"\033[:转义序列开始(\e[ 或 \x1b[ 等效&#…...
模型加载常见问题
safetensors_rust.SafetensorError: Error while deserializing header: HeaderTooLarge 问题代码: model AutoModelForVision2Seq.from_pretrained( "/data-nvme/yang/Qwen2.5-VL-32B-Instruct", trust_remote_codeTrue, torch_dtypetorc…...
HCIA-Access V2.5_16_3_数据业务维护
查询ONT上的业务配置 查询ONU上的业务配置 查询OLT上网业务 查询上网业务流量 查询上网业务相关MAC地址 删除故障ONT 删除故障ONU...
Java设计开发商城抢票功能
在开发一个商城抢购功能时,需要考虑几个关键方面,包括并发控制、数据一致性、用户体验以及系统的可扩展性。下面我将通过一个简单的步骤指南来介绍如何设计这样一个功能。 1. 需求分析 首先,明确抢购功能的需求: 限制购买数量。…...
【APM】Build an environment for Traces, Metrics and Logs of App by OpenTelemetry
系列文章目录 此系列文章介绍如何搭建Observability(可观测性)环境(Opentelemetry-Collector、Tempo、Prometheus、Loki和Grafana),以及应用。 【APM】Observability Solution 【APM】Build an environment for Traces, Metrics and Logs …...
全自动驾驶(FSD,Full Self-Driving)自动驾驶热点技术的成熟之处就是能判断道路修复修路,能自动利用类似“人眼”的摄像头进行驾驶!值得学习!
全自动驾驶(FSD,Full Self-Driving)软件是自动驾驶领域中的热点技术,其核心目标是实现车辆在各种复杂交通环境下的安全、稳定、高效自动驾驶。FSD软件的技术核心涉及多个方面的交叉技术,下面将详细分析说明其主要核心技…...
需要处理哪些响应数据?
在调用淘宝商品搜索 API 时,响应数据通常是一个 JSON 对象,包含了搜索结果的详细信息。以下是需要处理的主要响应数据字段及其说明: 响应数据结构 示例 JSON 数据 JSON {"code": "0","errorMessage": &quo…...
【NLP 63、大模型应用 —— Agent】
人与人最大的差距就是勇气和执行力,也是唯一的差距 —— 25.4.16 一、Agent 相关工作 二、Agent 特点 核心特征: 1.专有场景(针对某个垂直领域) 2.保留记忆(以一个特定顺序做一些特定任务,记忆当前任务的前…...
Windows 图形显示驱动开发-WDDM 1.2功能—Windows 8 中的 DirectX 功能改进(三)
一、与目标无关的光栅化 (TIR) 独立于目标的光栅化 (TIR) 为涉及结构化图形的高质量抗锯齿的 Direct2D 使用方案提供高性能抗锯齿路径。 TIR 使 Direct2D 能够将光栅化步骤从 CPU 移动到 GPU,同时保留 Direct2D 抗锯齿语义和质量。 使用此功能,软件层可…...
总结【过往部分项目经历二(计算机图形学方向)】
过往部分项目经历二 1.加强杆自动生成算法2.牙龈线序列批量算法3.光伏多阵列排布算法 1.加强杆自动生成算法 介绍: 主要用于牙科正畸定制化应用。采用纯数字化技术,一键导入加强杆后,自动摆放、加强杆结构设计、网格重建、接触部分自动定位、…...