varchar(255)不一定比varchar(64)慢,因实际存储可变,但索引比较仍按最大长度预留空间;int比bigint更优,因4字节宽度使索引页容纳键值更多、树高更低、i/o更少。

为什么 VARCHAR(255) 不一定比 VARCHAR(64) 慢,但 INT 比 BIGINT 更值得优先考虑
索引性能不只看“有没有”,更取决于「数据类型宽度」和「比较开销」。MySQL 在 B+ 树索引中逐行比较键值,类型越宽、越复杂,CPU 比较越慢,缓存命中率越低。
-
VARCHAR实际存储长度可变,但索引排序和比较时仍需按最大声明长度预留空间(尤其在utf8mb4下,1 个字符最多占 4 字节) -
INT固定 4 字节,BIGINT固定 8 字节 —— 同样数量的索引页,前者能容纳约 2 倍多的键值,减少树高和磁盘 I/O - 对
ENUM或SET类型建索引要格外小心:内部转为整数比较,但查询时若用字符串字面量,可能触发隐式类型转换,导致索引失效
WHERE 条件中的类型强制转换会让索引完全失效
常见于字段定义为 VARCHAR,但查询时传入数字(如 WHERE user_id = 123),或反过来:字段是 INT,却用字符串查询(WHERE status = '1')。MySQL 会尝试将列转为目标类型,从而跳过索引查找路径。
v1.13更新:1.增加产品讨论功能(ProductMsg备注字段)2.修正页面中的js错误数处。3.删除后的拍卖产品在回收站中统一管理。4.版面图标的DIY..自己更换,表格颜色自由调配。5.无限分类结构优化。6.产品说明支持HTML.7.网页界面优化.8.修正产品上下跳转的条数错误。9.完善邮件群发功能,可选择发送给不同类型的商城用户。10.修正拍卖信息中错误的交易完成Bug。11.去掉搜索用
- 用
EXPLAIN查看type是否为ALL或index,同时检查Extra列是否含Using where; Using index—— 若只有Using where,大概率发生了类型转换 - 显式保持一致:
WHERE user_id = '123'(当user_id是VARCHAR)或WHERE status = 1(当status是TINYINT) - 避免在索引列上套函数或表达式,例如
WHERE UPPER(name) = 'JOHN',即使name有索引也用不上
日期类字段该用 DATE 还是 DATETIME?TIMESTAMP 的隐式行为很危险
三者都支持索引,但语义与存储差异直接影响查询效率与结果正确性。
-
DATE占 3 字节,适合仅需年月日的场景(如生日、合同生效日);DATETIME占 8 字节,范围大(1001–9999),无时区转换,适合记录精确时间点(如订单创建时间) -
TIMESTAMP占 4 字节,但写入时自动转为 UTC 存储,读取时再转回 session 时区 —— 若应用跨多个时区且未统一处理,WHERE created_at > '2024-01-01'可能因时区偏移返回意外结果 - 范围查询(如
BETWEEN)对DATE和DATETIME效果接近,但TIMESTAMP的自动转换逻辑会让执行计划更难预测,尤其配合CONVERT_TZ()时
JSON 字段加索引必须用虚拟列 + 函数索引,否则等于没建
MySQL 5.7+ 支持对 JSON 字段建索引,但不能直接在 json_col 上建,必须提取路径值到虚拟列,再对该列建索引。
ALTER TABLE orders ADD COLUMN customer_id_virtual INT AS (json_unquote(json_extract(data, '$.customer_id'))) STORED, ADD INDEX idx_customer_id (customer_id_virtual);
- 漏掉
STORED关键字会导致无法索引(MySQL 要求虚拟列必须是STORED才能建索引) -
json_extract()返回的是 JSON 字符串,需用json_unquote()去掉双引号,否则查123会匹配不到"123" - 虚拟列本身不额外占用行存储空间,但索引结构照常生成 —— 所以仍需评估该路径是否高频查询,避免为低频字段堆砌索引
CREATE TABLE 或 WHERE 条件时都得下意识核对的细节。









