LLEARNING NOTES

技术 · 思考 · 实践 · 成长

首页/MySQL8专栏/正文

MySQL 8 CHAR 和 VARCHAR 的区别

MySQL8专栏3 次阅读

一、核心区别

image.png

二、详细对比

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 '%智能手机%';



凡人做一事,便须全副精神注在此一事,首尾不懈,不可见异思迁,做这样,想那样,坐这山,望那山。人而无恒,终身一无所成。——曾国藩《曾国藩家书》

评论交流

理性讨论,共同进步
验证码

相关文章

继续阅读