一、核心区别

二、详细对比
2.1、存储机制
char定长存储
-- CHAR(10) 总是占用 10 个字节空间
CREATE TABLE char_test (
char_field CHAR(10)
);
-- 插入数据,不足10字符会用空格填充
INSERT INTO char_test (char_field) VALUES ('hello');
-- 实际存储:'hello '(5个字母 + 5个空格)
变长存储
-- VARCHAR(10) 按实际数据长度分配空间
CREATE TABLE varchar_test (
varchar_field VARCHAR(10)
);
-- 插入数据,只占用实际字符数
INSERT INTO varchar_test (varchar_field) VALUES ('hello');
-- 实际存储:'hello'(5个字节,不含尾部空格)2.2、数据长度对比
-- 创建测试表
CREATE TABLE string_comparison (
char_10 CHAR(10),
varchar_10 VARCHAR(10),
char_20 CHAR(20),
varchar_20 VARCHAR(20)
);
-- 插入测试数据
INSERT INTO string_comparison VALUES
('hello', 'hello', 'hello', 'hello'), -- 短字符串
('abcdefghij', 'abcdefghij', 'abcdefghij', 'abcdefghij'), -- 正好10字符
('abcdefghijklmnopqrst', 'abcdefghijklmnopqrst', 'abcdefghijklmnopqrst', 'abcdefghijklmnopqrst'); -- 20字符2.3、实际空间占用
-- 检查实际存储长度 SELECT char_length(char_10) as char_length_10, length(char_10) as storage_bytes_10, char_length(varchar_10) as varchar_length_10, length(varchar_10) as storage_bytes_10_var, char_length(char_20) as char_length_20, length(char_20) as storage_bytes_20, char_length(varchar_20) as varchar_length_20, length(varchar_20) as storage_bytes_20_var FROM string_comparison;
三、使用案例
案例1:用户注册表
-- 使用VARCHAR存储用户信息(推荐) CREATE TABLE users ( user_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, -- 用户名长度不固定 email VARCHAR(100) NOT NULL, -- 邮箱长度变化较大 phone VARCHAR(20) NOT NULL, -- 手机号相对固定 bio VARCHAR(500), -- 个人简介长度变化大 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 使用CHAR存储固定长度信息 CREATE TABLE users_char ( user_id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, -- 用户名不固定 gender CHAR(1) NOT NULL, -- 固定单字符:M/F/U marital_status CHAR(1) NOT NULL, -- 固定单字符:S/M/D/W created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
案例2:产品管理系统
-- 产品信息表 CREATE TABLE products ( product_id INT AUTO_INCREMENT PRIMARY KEY, product_code CHAR(10) NOT NULL, -- 产品编码固定长度 product_name VARCHAR(100) NOT NULL, -- 产品名称长度不固定 brand VARCHAR(50) NOT NULL, -- 品牌名称 category VARCHAR(50) NOT NULL, -- 分类名称 unit CHAR(10) NOT NULL, -- 单位固定长度:个/箱/公斤 barcode CHAR(13) NOT NULL, -- 条形码固定13位 description TEXT, -- 详细描述使用TEXT类型 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY (product_code) );
-- 检查CHAR和VARCHAR的实际存储 INSERT INTO products VALUES (1, 'P001234567', '智能手机', '苹果', '电子产品', '个', '1234567890123', '最新款智能手机'), (2, 'P002345678', '笔记本电脑', '戴尔', '电子产品', '台', '2345678901234', '高性能办公笔记本');
案例3:订单管理系统
-- 订单表 CREATE TABLE orders ( order_id BIGINT AUTO_INCREMENT PRIMARY KEY, order_number VARCHAR(20) NOT NULL, -- 订单号长度相对固定但不固定 order_date DATE NOT NULL, customer_id INT NOT NULL, payment_method CHAR(10) NOT NULL, -- 支付方式:支付宝/微信/现金 status CHAR(10) NOT NULL DEFAULT 'pending', -- 订单状态固定长度 shipping_address TEXT NOT NULL, -- 地址长度变化大 total_amount DECIMAL(10,2) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY (order_number), FOREIGN KEY (customer_id) REFERENCES customers(customer_id) );
案例4:字符串处理对比
-- 演示CHAR和VARCHAR在字符串处理上的区别 CREATE TABLE string_test ( char_field CHAR(10), varchar_field VARCHAR(10) );
-- 插入数据
INSERT INTO string_test VALUES ('hello ', 'hello');
-- 字符串连接测试
UPDATE string_test SET
char_field = char_field || ' world', -- MySQL 8.0+ 支持 || 连接符
varchar_field = varchar_field || ' world';
-- 查看结果
SELECT
'原始数据' as test_case,
char_field as char_value,
varchar_field as varchar_value,
LENGTH(char_field) as char_length,
LENGTH(varchar_field) as varchar_length,
CHAR_LENGTH(char_field) as char_char_length,
CHAR_LENGTH(varchar_field) as varchar_char_length
FROM string_test;四、性能对比分析
4.1、索引性能测试
-- 创建性能测试表
CREATE TABLE char_performance (
id INT AUTO_INCREMENT PRIMARY KEY,
char_field CHAR(50) NOT NULL,
varchar_field VARCHAR(50) NOT NULL,
INDEX idx_char (char_field),
INDEX idx_varchar (varchar_field)
);
-- 插入测试数据
INSERT INTO char_performance (char_field, varchar_field)
SELECT
REPEAT('A', FLOOR(1 + RAND() * 50)), -- 生成1-50个字符的字符串
REPEAT('B', FLOOR(1 + RAND() * 50))
FROM information_schema.tables LIMIT 10000;
-- 性能对比查询
EXPLAIN SELECT * FROM char_performance WHERE char_field = REPEAT('A', 30);
EXPLAIN SELECT * FROM char_performance WHERE varchar_field = REPEAT('B', 30);4.2、查询性能
-- 测试CHAR的固定长度优势 SELECT SQL_NO_CACHE * FROM products WHERE product_code = 'P001234567'; -- 测试VARCHAR的变长查询 SELECT SQL_NO_CACHE * FROM products WHERE product_name LIKE '%智能手机%';