3. 环境准备:搭建MySQL测试环境、准备样本数据集(订单表、用户表)

在开始SQL回测规则与灰度切换之前,必须构建一个隔离、可重复的测试环境。本章将指导你完成MySQL单机测试环境的搭建,并创建核心的订单表与用户表样本数据集,为后续的回测执行提供数据基础。

3.1 测试环境规格与版本选择

为保证回测结果的稳定性与可移植性,建议使用以下统一规格。生产环境与测试环境的版本差异应控制在次要版本内。

组件 推荐版本 说明
MySQL 8.0.32+ 支持窗口函数、CTE,便于回测规则编写
操作系统 CentOS 7.9 / Ubuntu 22.04 生产环境常用发行版
存储引擎 InnoDB 支持事务与行级锁,模拟真实并发
字符集 utf8mb4 避免emoji或特殊字符截断
时区 +08:00 (Asia/Shanghai) 订单时间字段依赖时区设置
环境隔离建议:使用Docker容器或独立的MySQL实例,避免与开发/生产库混用。回测过程中可能涉及大量临时表与索引变更,隔离环境可防止误操作。

3.2 搭建MySQL测试实例(Docker快速部署)

以下步骤使用Docker在本地快速拉起一个干净的MySQL 8.0测试实例,适用于个人笔记本或CI/CD流水线。

# 拉取官方镜像
docker pull mysql:8.0.32

# 启动容器,挂载数据目录与配置
docker run -d \
  --name mysql_retest \
  -p 3307:3306 \
  -e MYSQL_ROOT_PASSWORD=Retest@2025 \
  -e MYSQL_DATABASE=regression_db \
  -v /data/mysql_retest:/var/lib/mysql \
  mysql:8.0.32 \
  --character-set-server=utf8mb4 \
  --collation-server=utf8mb4_unicode_ci \
  --default-time_zone='+8:00'

# 验证连接
mysql -h 127.0.0.1 -P 3307 -u root -pRetest@2025
端口冲突注意:本地MySQL默认端口为3306,测试容器映射到3307,避免与已有服务冲突。若生产环境使用不同端口,请相应调整。

3.3 样本数据集设计:用户表与订单表

回测规则通常涉及用户维度与订单维度的关联分析。两张表的设计需覆盖主键、索引、时间戳、状态枚举等关键字段,以便后续测试索引选择、分区裁剪、JOIN优化等场景。

3.3.1 用户表(users)

CREATE TABLE `users` (
  `user_id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(64) NOT NULL COMMENT '用户名',
  `register_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间',
  `user_level` tinyint NOT NULL DEFAULT '1' COMMENT '用户等级:1-普通,2-VIP,3-至尊',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:1-正常,0-冻结',
  `last_login` datetime DEFAULT NULL COMMENT '最后登录时间',
  PRIMARY KEY (`user_id`),
  KEY `idx_register_date` (`register_date`),
  KEY `idx_user_level` (`user_level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

3.3.2 订单表(orders)

CREATE TABLE `orders` (
  `order_id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单ID',
  `user_id` int NOT NULL COMMENT '用户ID',
  `order_amount` decimal(12,2) NOT NULL COMMENT '订单金额',
  `order_status` tinyint NOT NULL DEFAULT '0' COMMENT '订单状态:0-待支付,1-已支付,2-已发货,3-已完成,4-已取消',
  `pay_time` datetime DEFAULT NULL COMMENT '支付时间',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`order_id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_create_time` (`create_time`),
  KEY `idx_order_status` (`order_status`),
  CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
设计要点:
  • 订单表使用bigint主键,避免int溢出(生产环境订单量级通常较大)。
  • 外键fk_user_id保证数据完整性,回测时可临时禁用外键检查以提升批量插入性能:SET foreign_key_checks = 0;。
  • 时间字段均使用datetime类型,配合+8:00时区,避免timestamp的2038年问题。

3.4 样本数据生成与导入

为模拟真实数据分布,使用存储过程批量生成100万用户与500万订单数据。数据生成策略需覆盖热点用户、时间倾斜、状态分布等特征,使回测规则能暴露真实性能问题。

-- 生成100万用户
DELIMITER $$
CREATE PROCEDURE generate_users(IN num INT)
BEGIN
  DECLARE i INT DEFAULT 1;
  SET @batch_size = 10000;
  WHILE i <= num DO
    INSERT INTO users (user_name, register_date, user_level, status)
    SELECT
      CONCAT('user_', i + seq),
      DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 365) DAY),
      FLOOR(1 + RAND() * 3),
      IF(RAND() < 0.95, 1, 0)
    FROM (SELECT @i := @i + 1 AS seq FROM (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) a,
         (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) b,
         (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) c,
         (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) d) tmp
    WHERE seq <= @batch_size;
    SET i = i + @batch_size;
  END WHILE;
END$$
DELIMITER ;

CALL generate_users(1000000);

-- 生成500万订单(关联用户ID 1~100万)
INSERT INTO orders (user_id, order_amount, order_status, pay_time, create_time)
SELECT
  FLOOR(1 + RAND() * 1000000),
  ROUND(RAND() * 5000 + 10, 2),
  FLOOR(0 + RAND() * 5),
  CASE WHEN RAND() < 0.8 THEN DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 180) DAY) ELSE NULL END,
  DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 200) DAY)
FROM
  (SELECT a.seq FROM (SELECT @i := @i + 1 AS seq FROM information_schema.COLUMNS a,
   information_schema.COLUMNS b LIMIT 5000000) a) tmp;
数据分布验证:生成完成后,执行以下查询确认数据倾斜度:
SELECT user_level, COUNT(*) FROM users GROUP BY user_level;
SELECT order_status, COUNT(*) FROM orders GROUP BY order_status;
若某状态占比过低(如已取消订单不足1%),可调整生成逻辑中的随机概率。

3.5 测试环境拓扑与数据流向

下图展示了测试环境的逻辑拓扑,以及回测过程中SQL语句的流转路径。数据从样本库出发,经过回测引擎解析后,在测试实例上执行并收集性能指标。

测试环境拓扑与数据流向 样本数据集 users (100万行) orders (500万行) MySQL测试实例 Docker / 独立实例 端口 3307 回测引擎 规则解析 + 执行 性能采集 回测输出 执行计划 / 耗时 / 扫描行数 环境隔离说明 样本数据集与测试实例部署在同一主机或容器网络内,减少网络延迟干扰。 回测引擎通过JDBC连接测试实例,每次回测前重置数据库至初始快照。

3.6 环境验证清单

完成搭建后,逐项确认以下检查点,确保环境符合回测要求:

  1. 连接测试:使用mysql -h 127.0.0.1 -P 3307 -u root -p成功登录。
  2. 数据库确认:SHOW DATABASES; 包含 regression_db。
  3. 表结构验证:DESC users; 与 DESC orders; 字段与设计一致。
  4. 数据量检查:SELECT COUNT(*) FROM users; 返回 1,000,000;SELECT COUNT(*) FROM orders; 返回 5,000,000。
  5. 索引状态:SHOW INDEX FROM orders; 确认包含 idx_user_id、idx_create_time、idx_order_status。
  6. 时区验证:SELECT NOW(); 返回当前东八区时间。
快照建议:在数据生成完成后,使用mysqldump或CLONE PLUGIN创建一份初始快照。每次回测前恢复快照,确保不同规则版本在完全相同的数据集上执行,消除数据变化带来的干扰。