面试题mysql 2000万数据怎么建表

面试耻辱柱

      • [一、mysql varchar 是字节还是字符?](#一、mysql varchar 是字节还是字符?)
      • 二、场景(2000万数据表:id、姓名、年龄、爱好) 主键用啥类型 id 主键用啥类型 id)
      • [三、bigint 8 个字节最多存多少数据,2000万够吗?](#三、bigint 8 个字节最多存多少数据,2000万够吗?)
      • [四、如果2000万这个只会用到 where name = xx 或者 where age = xx ,where name =xx and age = xx,该如建立索引](#四、如果2000万这个只会用到 where name = xx 或者 where age = xx ,where name =xx and age = xx,该如建立索引)
      • [四、如果2000万 name 用啥类型合适,名字包含中文名字和英文名字](#四、如果2000万 name 用啥类型合适,名字包含中文名字和英文名字)

一、mysql varchar 是字节还是字符?

VARCHAR 在 MySQL 中是以字符为单位计算的,而不是字节。

  • 当创建 VARCHAR(10) 字段时,表示可以存储最多 10个字符
  • 但实际存储占用的字节数取决于字符编码和具体存储的内容

二、场景(2000万数据表:id、姓名、年龄、爱好) 主键用啥类型 id

强烈推荐使用 BIGINT 作为主键(不是使用varchar)

  • 性能优势
bash 复制代码
-- BIGINT 比较是简单的 8 字节整数比较
-- VARCHAR 比较需要逐字符比对,更耗时
SELECT * FROM users WHERE id = 12345678; -- BIGINT: 快速
SELECT * FROM users WHERE id = 'USER_12345678'; -- VARCHAR: 较慢
  • 存储效率
    BIGINT:固定 8 字节,存储 2000万条数据 ≈ 160MB(仅ID字段
    VARCHAR(20):假设平均 12 字节,2000万条 ≈ 240MB + 额外开销
  • 索引性能
    BIGINT 主键的 B+树索引更浅,因为每个节点能存储更多键值
    VARCHAR 索引更大,可能导致更多的磁盘 I/O
  • 推荐的表结构
bash 复制代码
CREATE TABLE users (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,  -- 推荐
    name VARCHAR(50) NOT NULL,
    age TINYINT UNSIGNED,
    hobby VARCHAR(200),
    INDEX idx_name (name),
    INDEX idx_age (age)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 预计 2000万数据量:约 2-3GB(包含索引)

什么情况下用 VARCHAR 作为 ID?

1.自然键:如用户名、邮箱、身份证号(已有业务含义)

2.分布式系统:需要 UUID(但可存储为 BINARY(16) 性能更好)

bash 复制代码
-- 如果必须用字符串ID,考虑压缩存储
id CHAR(32) -- UUID 去除了连字符
-- 或更好的方案
id BINARY(16) -- 存储为二进制,性能好很多

三、bigint 8 个字节最多存多少数据,2000万够吗?


为什么2000万数据还用 BIGINT?

1.未来扩展性

bash 复制代码
-- 今天:2000万用户
-- 明年:可能5000万
-- 五年后:可能2亿
-- BIGINT:完全无压力
-- INT:42亿上限,长期看可能不够

2.分区和分表友好

bash 复制代码
-- 使用 BIGINT 可以轻松做范围分区
PARTITION BY RANGE (id) (
    PARTITION p0 VALUES LESS THAN (10000000),
    PARTITION p1 VALUES LESS THAN (20000000),
    PARTITION p2 VALUES LESS THAN (30000000),
    -- ... 可以分很多区
)

3.分布式系统兼容

  • 如果未来需要分库分表,BIGINT 提供更大的 ID 空间
  • Snowflake 等分布式 ID 算法生成的也是 64 位整数

实际存储示例(算出2000万的id 就是约等于160MB)

bash 复制代码
-- 创建表
CREATE TABLE users (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50),
    age TINYINT UNSIGNED,
    hobby VARCHAR(200)
) ENGINE=InnoDB;

-- 查看存储信息
SELECT 
    table_name AS '表名',
    table_rows AS '行数',
    data_length/1024/1024 AS '数据大小(MB)',
    index_length/1024/1024 AS '索引大小(MB)'
FROM information_schema.tables 
WHERE table_name = 'users';

-- 2000万数据预估:
-- ID字段占用:20,000,000 × 8字节 ≈ 160 MB
-- 整表(含索引)估计:2-4 GB

4.性能考虑

bash 复制代码
-- 插入性能
INSERT INTO users (name, age, hobby) VALUES ('张三', 25, '篮球');
-- BIGINT 自增:直接内存操作,极快

-- 查询性能
SELECT * FROM users WHERE id = 15372849;
-- BIGINT 比较:单次CPU指令
-- VARCHAR 比较:需要字符串解析和逐字符比较

四、如果2000万这个只会用到 where name = xx 或者 where age = xx ,where name =xx and age = xx,该如建立索引

  • 方案一:最推荐方案(复合索引 + 单列索引)
bash 复制代码
-- 创建复合索引(最常用查询)
CREATE INDEX idx_name_age ON users(name, age);

-- 创建单列索引(用于单独按age查询)
CREATE INDEX idx_age ON users(age);

为什么这样设计?

复合索引 idx_name_age(name, age) 可以覆盖

  • 查询1: WHERE name = 'xx' ✅ (使用索引前缀)
  • 查询3: WHERE name = 'xx' AND age = xx ✅ (完全使用索引)
  • 查询2: WHERE age = xx ❌ (不能使用,因为age不是索引最左列)

单列索引 idx_age 专门用于:

  • 查询2: WHERE age = xx ✅

四、如果2000万 name 用啥类型合适,名字包含中文名字和英文名字

对于包含中文和英文的名字,推荐使用 VARCHAR 配合合适的字符集和长度。

bash 复制代码
name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
  1. 字符集选择:UTF8MB4

  2. 长度设置:VARCHAR(50)

长度分析

bash 复制代码
-- 中文名:通常 2-4 个汉字
'张三'           -- 2字符
'欧阳修'         -- 3字符  
'司马相如'       -- 4字符
'慕容复'         -- 3字符

-- 英文名:通常较长
'John'          -- 4字符
'John Smith'    -- 10字符(含空格)
'Christopher'   -- 11字符
'Christopher Alexander Smith'  -- 24字符

-- 特殊情况:
'Jean-Claude Van Damme'  -- 21字符
'María José'             -- 10字符(含重音)
'أحمد بن حنبل'           -- 11字符(阿拉伯文)

为什么是 VARCHAR(50):

  • 足够容纳绝大多数名字:99.9%的名字在50字符内
  • 考虑复姓和长英文名:Christopher Alexander Montgomery Smith ≈ 35字符
  • 考虑中间名和尊称:Dr. John H. Smith Jr. ≈ 20字符
  • 国际化考虑:某些语言名字较长
相关推荐
952365 分钟前
MySQL存储过程和触发器
数据库·mysql
x***r1517 分钟前
phpstudy_x64_8.1.1.3安装教程(含Apache/MySQL启动与端口修改)
数据库·mysql·apache
cjl_8520081 小时前
MySQL-递归查询
数据库·windows·mysql
laplace01232 小时前
第二章 字符串和文本 下
服务器·数据库·python·mysql·agent
念越2 小时前
MySQL 联合查询执行原理:多表笛卡尔积
数据库·mysql
·云扬·12 小时前
MySQL 主从复制实战:Xtrabackup 高效部署方案
数据库·mysql
Ama_tor13 小时前
从零开始MySQL|F盘安装,配置,简单应用以及基础语句
数据库·mysql
程序边界1 天前
数据库MySQL兼容版权限隔离深度体验:从兼容到安全增强的实战之路
数据库·mysql·安全
Victoria.a1 天前
Mysql基础
数据库·mysql
_codemonster1 天前
MySQL驱动(8.x版本)和MySQL驱动(5.x版本)区别
数据库·mysql