TiDB 新手建表通关宝典
TiDB 建表规范与最佳实践 (V1.0)核心设计哲学忘记顺序拥抱离散在开始之前请把这句话刻在你的 DNA 里TiDB 第一天条打散打散还是打散一切为了避免热点Hotspot想象一下TiDB 是一个有无数窗口同时办理业务的大厅分布式而热点就是所有人都挤在1号窗口排队其他窗口都空着。我们的目标就是把人流数据写入均匀引导到所有窗口。一、 主键设计规范 (The MOST IMPORTANT Part!)主键是数据在 TiDB 中物理分布的决定性因素也是最容易产生热点的地方。[ 1.1 ]【强制】高频写入的表主键必须使用AUTO_RANDOM。说明这是解决写入热点的最佳、最简单、最常用的手段。AUTO_RANDOM会生成离散的、随机的 ID将写入请求自然地分散到不同的 TiKV 节点上。反例禁止在高频写入的表中使用AUTO_INCREMENT作为主键。连续递增的 ID 是写入热点的万恶之源。[ 1.2 ]【强制】所有表都必须有显式的主键。说明如果没有主键TiDB 会使用一个隐式的、自增的_tidb_row_id作为行 ID这同样会引发严重的写入热点。定义一个显式主键即使是业务无用是良好实践。[ 1.3 ]【推荐】当主键为非整数类型如VARCHAR,UUID或联合主键时使用SHARD_ROW_ID_BITSPRE_SPLIT_REGIONS来打散数据。说明这种场景下无法使用AUTO_RANDOMSHARD_ROW_ID_BITS成为我们打散隐式_tidb_row_id的武器。用法SHARD_ROW_ID_BITS N将数据打散到2^N个逻辑分片上。通常建议N的取值为4到6之间。PRE_SPLIT_REGIONS M在建表时预先创建M个空的 Region。M的值应略小于2^N。例如SHARD_ROW_ID_BITS 4(16个分片)可以设置PRE_SPLIT_REGIONS 3或4。二、 索引设计规范索引也会产生热点特别是当索引键是时间、状态等具有单调递增属性的字段时。[ 2.1 ]【推荐】避免在索引的第一列使用单调递增的字段。说明例如在create_time字段上建索引所有新的写入都会集中更新索引的末尾部分形成索引热点。解决方案组合索引将离散度高的列如user_id放在前面create_time放在后面如KEY(user_id, create_time)。函数索引 (v6.2.0)对索引列进行处理如KEY((REVERSE(user_id)))。[ 2.2 ]【建议】单个表的索引数量不宜过多建议不超过 5 个。说明索引越多写入时需要维护的开销就越大影响写入性能。请只创建真正需要且高效的索引。三、 字段类型与约束规范[ 3.1 ]【强制】所有字段都必须指定为NOT NULL并提供DEFAULT值。说明NULL值会带来额外的存储开销和逻辑复杂性在分布式环境下明确的默认值是更优的选择。[ 3.2 ]【推荐】使用VARCHAR代替TEXT或BLOB。说明如果字段长度可控如小于 64KB优先使用VARCHAR。TiDB 对VARCHAR的处理性能优于TEXT/BLOB。[ 3.3 ]【强制】统一使用utf8mb4字符集。说明utf8mb4是未来的标准支持 Emoji 等各类字符避免后续字符集转换的痛苦。四、 表参数与其他[ 4.1 ]【强制】所有表和字段都必须添加COMMENT注释。说明今天你偷的懒就是明天同事骂你的原因。清晰的注释是团队协作的基石。TiDB 建表示例与模板 (抄作业区✍️)下面是两个最经典的场景你可以直接复制粘贴然后修改表名和字段名模板一最佳实践 - 使用AUTO_RANDOM主键90% 的场景都用它CREATETABLEt_user_info(idBIGINTNOTNULLPRIMARYKEYAUTO_RANDOM,-- 魔法在这里user_idVARCHAR(64)NOTNULLDEFAULTCOMMENT用户唯一标识,nicknameVARCHAR(100)NOTNULLDEFAULTCOMMENT用户昵称,create_timeDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT创建时间,update_timeDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT更新时间,KEYidx_userid(user_id)-- 业务需要可以创建普通索引)ENGINEInnoDBDEFAULTCHARSETutf8mb4COLLATEutf8mb4_binCOMMENT用户信息表;模板二备选方案 - 非整数主键或无主键表CREATETABLEt_operation_log(log_idVARCHAR(128)NOTNULLPRIMARYKEY,-- 使用 UUID 或其他非整数做主键operatorVARCHAR(100)NOTNULLDEFAULTCOMMENT操作人,contentTEXTCOMMENT操作内容,create_timeDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT创建时间)ENGINEInnoDBDEFAULTCHARSETutf8mb4COLLATEutf8mb4_binCOMMENT操作日志表-- 魔法在这里SHARD_ROW_ID_BITS4PRE_SPLIT_REGIONS3;错误示例千万不要这样建表(MySQL 老习惯)-- 这是一个典型的反面教材CREATETABLEt_hotspot_orders(idBIGINTNOTNULLAUTO_INCREMENT,-- ❌ 热点元凶user_idBIGINTNOTNULL,amountDECIMAL(10,2),create_timeTIMESTAMP,PRIMARYKEY(id),-- ❌ 把自增列做主键KEYidx_createtime(create_time)-- ❌ 在时间列上单独建索引也是索引热点);总结好了这份宝典的核心精髓已经传授给你了。记住在 TiDB 的世界里“随机”和“离散”是最高贵的品质。每次CREATE TABLE前都默念一遍“打散大法好”你就离 TiDB 大神又近了一步