会,但通常不明显——BIGINT索引因固定8字节,开销稳定;真正影响写入的是索引数量、字段更新频率及高并发下的页分裂,而非BIGINT本身。

bigint 字段加索引会不会拖慢写入?
会,但通常不明显——BIGINT 是固定 8 字节长度,B+ 树索引的比较和存储开销稳定,远小于 TEXT 或长 VARCHAR。真正影响写入性能的是索引数量、是否频繁更新该字段、以及是否在高并发 INSERT/UPDATE 场景下触发页分裂。
常见误判点:有人看到 INSERT 变慢就怀疑 BIGINT 索引本身重,其实更可能是没用好主键或二级索引顺序。比如在自增 id BIGINT PRIMARY KEY 后,再对另一个 user_id BIGINT 建单独索引,若查询常带 WHERE user_id = ? AND status = ?,那单列 user_id 索引效率反而不如联合索引 (user_id, status)。
- 高频写入表慎用多个单列
BIGINT索引,优先合并为复合索引 - 如果该
BIGINT字段极少被WHERE或JOIN使用,加索引纯属冗余 -
ALTER TABLE ADD INDEX期间会锁表(5.6+ 支持ALGORITHM=INPLACE,但仍需元数据锁)
什么时候必须用 bigint 而不是 int?
不是“想存大数就用 BIGINT”,而是看业务增长预期。MySQL 的 INT 有符号上限是 2147483647(约 21 亿),一旦主键或计数器接近这个量级,就会报 ERROR 1062 (23000): Duplicate entry '2147483647' for key 'PRIMARY' 或直接溢出变负数。
典型场景:
- 订单号、流水号采用时间戳 + 自增拼接,64 位时间戳已占 ~10 位数字,再叠加序列很容易超
INT范围 - 社交类应用的粉丝数、互动数,头部用户可能达数十亿次操作
- 分库分表后全局唯一 ID(如雪花算法生成的 64 位整数)必须用
BIGINT UNSIGNED
注意:BIGINT 占用更多内存和磁盘空间,InnoDB 的主键会作为聚簇索引,所有二级索引叶子节点都包含主键值——所以主键用 BIGINT 会让所有二级索引变大。
create index 时要不要指定长度?
不需要,也不能。MySQL 不支持对整数类型(包括 TINYINT、INT、BIGINT)指定前缀长度,像 CREATE INDEX idx_uid ON t (user_id(10)) 这种写法会直接报错:ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string。
只有字符串类型(CHAR、VARCHAR、TEXT)才允许用括号指定前缀,例如 INDEX (title(100))。对 BIGINT 加索引就是全字段参与排序和查找,没有“截断”概念。
顺带提醒:如果字段定义为 BIGINT UNSIGNED,索引自动按无符号处理;但如果查询里写成 WHERE user_id = -123,MySQL 会隐式转成无符号值(变成极大正数),导致索引失效且查不到数据。
explain 显示 type=range 但实际很慢?检查这几个点
当 EXPLAIN 中 type 是 range,说明用了 BIGINT 索引做范围扫描(如 WHERE id BETWEEN 1000 AND 2000),但响应仍慢,大概率不是索引本身问题,而是:
- 扫描行数太多:
rows列显示预估扫描 50 万行?哪怕每行只要 0.1ms,也得 50 秒 —— 这时候应考虑加过滤条件或改用覆盖索引 - 回表代价高:如果
SELECT *且二级索引不包含所有需要字段,InnoDB 得根据主键反复回聚簇索引取数据,随机 IO 拉垮性能 - 统计信息过期:
ANALYZE TABLE没跑过,优化器误判了选择性,可能本该走其他索引却选了这个BIGINT字段的索引 - 隐式类型转换:
WHERE user_id = '12345'(字符串)会导致索引失效,type降级为ALL,但有时因字符集或 collation 问题表现诡异,务必用SHOW WARNINGS看真实执行计划
最稳妥的做法:用 SELECT ... FROM t WHERE user_id = ? 测试单值等值查询是否走索引,确认基础有效性后再拓展到范围或组合条件。










