Files
hfb_sys/scripts/load_test_data_optimized.sql
T
2026-06-09 19:04:11 +08:00

511 lines
19 KiB
SQL

-- ============================================
-- 优化的压力测试数据生成脚本
-- 使用批量生成 + 临时表,避免循环中的随机查询
-- ============================================
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ============================================
-- 1. 批量生成用户数据
-- ============================================
DROP PROCEDURE IF EXISTS generate_users_batch;
DELIMITER $$
CREATE PROCEDURE generate_users_batch(IN batch_size INT)
BEGIN
DECLARE batch_limit INT DEFAULT 1000;
DECLARE batches INT;
DECLARE current_batch INT DEFAULT 0;
DECLARE batch_start INT;
DECLARE batch_end INT;
DECLARE current_limit INT;
SET batches = CEIL(batch_size / batch_limit);
WHILE current_batch < batches DO
SET batch_start = current_batch * batch_limit + 1;
SET batch_end = LEAST((current_batch + 1) * batch_limit, batch_size);
SET current_limit = batch_end - batch_start + 1;
-- 使用 INSERT ... SELECT 批量生成
INSERT INTO users (phone, nickname, realname_status, risk_status, credit_score, status, created_at)
SELECT
CONCAT('138', LPAD(seq, 8, '0')) as phone,
CONCAT('测试用户', seq) as nickname,
CASE WHEN seq % 10 = 0 THEN 'unverified' ELSE 'verified' END as realname_status,
CASE WHEN seq % 100 = 0 THEN 'frozen' ELSE 'normal' END as risk_status,
80 + (seq % 20) as credit_score,
'active' as status,
DATE_SUB(NOW(), INTERVAL (seq % 365) DAY) as created_at
FROM (
SELECT @row := @row + 1 AS seq
FROM
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT @row := batch_start - 1) r
LIMIT current_limit
) seqs
ON DUPLICATE KEY UPDATE id=id;
SET current_batch = current_batch + 1;
COMMIT;
END WHILE;
-- 批量生成实名记录(为已实名用户)
INSERT INTO user_realname (user_id, provider, status, masked_name, masked_id_no, verified_at)
SELECT
u.id,
'mock',
'success',
CONCAT('张*', CHAR(65 + (u.id % 26))),
CONCAT('3301**********', LPAD(u.id % 10000, 4, '0')),
DATE_SUB(NOW(), INTERVAL (u.id % 300) DAY)
FROM users u
WHERE u.realname_status = 'verified'
AND NOT EXISTS (SELECT 1 FROM user_realname WHERE user_id = u.id);
-- 批量生成钱包账户
INSERT INTO wallet_accounts (user_id, available_balance_cent, frozen_balance_cent, status)
SELECT
u.id,
(u.id % 10) * 10000,
(u.id % 5) * 5000,
'active'
FROM users u
WHERE NOT EXISTS (SELECT 1 FROM wallet_accounts WHERE user_id = u.id);
COMMIT;
END$$
DELIMITER ;
-- ============================================
-- 2. 批量生成游戏账号和商品
-- ============================================
DROP PROCEDURE IF EXISTS generate_listings_batch;
DELIMITER $$
CREATE PROCEDURE generate_listings_batch(IN batch_size INT)
BEGIN
DECLARE batch_limit INT DEFAULT 1000;
DECLARE batches INT;
DECLARE current_batch INT DEFAULT 0;
DECLARE verified_user_count INT DEFAULT 0;
-- 创建临时表存储已实名用户ID
DROP TEMPORARY TABLE IF EXISTS tmp_verified_users;
CREATE TEMPORARY TABLE tmp_verified_users (
id BIGINT PRIMARY KEY,
row_num INT
);
INSERT INTO tmp_verified_users (id, row_num)
SELECT id, (@rn := @rn + 1) as row_num
FROM users, (SELECT @rn := 0) init
WHERE realname_status = 'verified'
ORDER BY id;
SELECT COUNT(*) INTO verified_user_count FROM tmp_verified_users;
SET batches = CEIL(batch_size / batch_limit);
WHILE current_batch < batches DO
-- 批量生成游戏账号
INSERT INTO game_accounts (
owner_id, game_name, server_region, login_platform,
title, description, rank_level, haf_coin_amount, status
)
SELECT
u.id as owner_id,
'delta_force',
CASE (seq % 4)
WHEN 0 THEN '亚服'
WHEN 1 THEN '美服'
WHEN 2 THEN '欧服'
ELSE '国服'
END,
CASE (seq % 3)
WHEN 0 THEN 'Steam'
WHEN 1 THEN 'Epic'
ELSE 'WeGame'
END,
CONCAT('账号', seq, ' 高分段'),
CONCAT('这是一个测试账号,编号', seq),
CASE (seq % 5)
WHEN 0 THEN '青铜'
WHEN 1 THEN '白银'
WHEN 2 THEN '黄金'
WHEN 3 THEN '铂金'
ELSE '钻石'
END,
(seq % 100) * 10000,
'published'
FROM (
SELECT @row2 := @row2 + 1 AS seq
FROM
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT @row2 := current_batch * batch_limit) r
LIMIT batch_limit
) seqs
INNER JOIN tmp_verified_users u ON u.row_num = (seq % verified_user_count) + 1
WHERE seq <= batch_size;
-- 批量生成租号商品
INSERT INTO rental_listings (
listing_no, account_id, owner_id, price_cent, deposit_amount_cent,
in_transaction, status, review_status, published_at
)
SELECT
CONCAT(
DATE_FORMAT(DATE_SUB(NOW(), INTERVAL (ga.id % 90) DAY), '%Y%m%d'),
LPAD(FLOOR((ga.id - 1) / 90) + 1, 4, '0')
) as listing_no,
ga.id as account_id,
ga.owner_id,
500 + ((ga.id % 20) * 50) as price_cent,
10000 + ((ga.id % 10) * 5000) as deposit_amount_cent,
CASE WHEN ga.id % 10 = 0 THEN 1 ELSE 0 END as in_transaction,
CASE
WHEN ga.id % 20 = 0 THEN 'offline'
WHEN ga.id % 15 = 0 THEN 'draft'
ELSE 'published'
END as status,
CASE
WHEN ga.id % 15 = 0 THEN 'pending'
WHEN ga.id % 30 = 0 THEN 'rejected'
ELSE 'approved'
END as review_status,
DATE_SUB(NOW(), INTERVAL (ga.id % 90) DAY) as published_at
FROM game_accounts ga
WHERE ga.id > (SELECT COALESCE(MAX(account_id), 0) FROM rental_listings)
LIMIT batch_limit;
SET current_batch = current_batch + 1;
COMMIT;
END WHILE;
INSERT INTO listing_no_sequences (biz_date, next_seq)
SELECT LEFT(listing_no, 8), MAX(CAST(SUBSTRING(listing_no, 9) AS UNSIGNED))
FROM rental_listings
GROUP BY LEFT(listing_no, 8)
ON DUPLICATE KEY UPDATE next_seq = GREATEST(next_seq, VALUES(next_seq));
COMMIT;
DROP TEMPORARY TABLE IF EXISTS tmp_verified_users;
END$$
DELIMITER ;
-- ============================================
-- 3. 批量生成订单数据(优化版)
-- ============================================
DROP PROCEDURE IF EXISTS generate_orders_batch;
DELIMITER $$
CREATE PROCEDURE generate_orders_batch(IN batch_size INT)
BEGIN
DECLARE batch_limit INT DEFAULT 1000;
DECLARE batches INT;
DECLARE current_batch INT DEFAULT 0;
DECLARE available_listing_count INT DEFAULT 0;
DECLARE verified_user_count INT DEFAULT 0;
-- 创建临时表:可用商品
DROP TEMPORARY TABLE IF EXISTS tmp_available_listings;
CREATE TEMPORARY TABLE tmp_available_listings (
id BIGINT PRIMARY KEY,
account_id BIGINT,
owner_id BIGINT,
price_cent BIGINT,
deposit_amount_cent BIGINT,
row_num INT
);
INSERT INTO tmp_available_listings (id, account_id, owner_id, price_cent, deposit_amount_cent, row_num)
SELECT id, account_id, owner_id, price_cent, deposit_amount_cent, (@rn := @rn + 1)
FROM rental_listings, (SELECT @rn := 0) init
WHERE status IN ('published', 'active') AND review_status = 'approved'
ORDER BY id;
SELECT COUNT(*) INTO available_listing_count FROM tmp_available_listings;
-- 创建临时表:已实名用户
DROP TEMPORARY TABLE IF EXISTS tmp_verified_users;
CREATE TEMPORARY TABLE tmp_verified_users (
id BIGINT PRIMARY KEY,
row_num INT
);
INSERT INTO tmp_verified_users (id, row_num)
SELECT id, (@rn2 := @rn2 + 1)
FROM users, (SELECT @rn2 := 0) init
WHERE realname_status = 'verified'
ORDER BY id;
SELECT COUNT(*) INTO verified_user_count FROM tmp_verified_users;
SET batches = CEIL(batch_size / batch_limit);
WHILE current_batch < batches DO
INSERT INTO rental_orders (
order_no, listing_id, account_id, owner_id, renter_id,
estimated_duration_hours, rent_amount_cent, owner_rent_amount_cent,
deposit_amount_cent, deposit_original_amount_cent, platform_fee_cent, status, handoff_status,
settlement_status, rented_at, created_at
)
SELECT
CONCAT('ORD', DATE_FORMAT(NOW(), '%Y%m%d'), LPAD(seq, 8, '0')) as order_no,
l.id as listing_id,
l.account_id,
l.owner_id,
r.id as renter_id,
24 as estimated_duration_hours,
l.price_cent * 24 as rent_amount_cent,
ROUND(l.price_cent * 24 * 0.95) as owner_rent_amount_cent,
l.deposit_amount_cent,
l.deposit_amount_cent,
ROUND(l.price_cent * 24 * 0.05) as platform_fee_cent,
CASE (seq % 10)
WHEN 0 THEN 'pending_payment'
WHEN 1 THEN 'cancelled'
WHEN 2 THEN 'closed'
ELSE 'completed'
END as status,
CASE (seq % 10)
WHEN 0 THEN 'none'
WHEN 1 THEN 'none'
WHEN 2 THEN 'owner_delivered'
ELSE 'owner_received'
END as handoff_status,
CASE (seq % 10)
WHEN 0 THEN 'unsettled'
WHEN 1 THEN 'unsettled'
ELSE 'settled'
END as settlement_status,
DATE_SUB(NOW(), INTERVAL (seq % 60) DAY) as rented_at,
DATE_SUB(NOW(), INTERVAL (seq % 60) DAY) as created_at
FROM (
SELECT @row3 := @row3 + 1 AS seq
FROM
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT @row3 := current_batch * batch_limit) r
LIMIT batch_limit
) seqs
INNER JOIN tmp_available_listings l ON l.row_num = (seq % available_listing_count) + 1
INNER JOIN tmp_verified_users r ON r.row_num = (seq % verified_user_count) + 1
WHERE seq <= batch_size AND r.id != l.owner_id
LIMIT batch_limit;
SET current_batch = current_batch + 1;
COMMIT;
END WHILE;
DROP TEMPORARY TABLE IF EXISTS tmp_available_listings;
DROP TEMPORARY TABLE IF EXISTS tmp_verified_users;
END$$
DELIMITER ;
-- ============================================
-- 4. 批量生成钱包流水
-- ============================================
DROP PROCEDURE IF EXISTS generate_wallet_ledger_batch;
DELIMITER $$
CREATE PROCEDURE generate_wallet_ledger_batch(IN batch_size INT)
BEGIN
DECLARE batch_limit INT DEFAULT 1000;
DECLARE batches INT;
DECLARE current_batch INT DEFAULT 0;
DECLARE user_count INT DEFAULT 0;
DECLARE order_count INT DEFAULT 0;
-- 创建临时表:用户列表
DROP TEMPORARY TABLE IF EXISTS tmp_users;
CREATE TEMPORARY TABLE tmp_users (
id BIGINT PRIMARY KEY,
row_num INT
);
INSERT INTO tmp_users (id, row_num)
SELECT id, (@rn := @rn + 1)
FROM users, (SELECT @rn := 0) init
ORDER BY id;
SELECT COUNT(*) INTO user_count FROM tmp_users;
-- 创建临时表:订单列表
DROP TEMPORARY TABLE IF EXISTS tmp_orders;
CREATE TEMPORARY TABLE tmp_orders (
id BIGINT PRIMARY KEY,
row_num INT
);
INSERT INTO tmp_orders (id, row_num)
SELECT id, (@rn2 := @rn2 + 1)
FROM rental_orders, (SELECT @rn2 := 0) init
ORDER BY id;
SELECT COUNT(*) INTO order_count FROM tmp_orders;
SET batches = CEIL(batch_size / batch_limit);
WHILE current_batch < batches DO
INSERT INTO wallet_ledger (
ledger_no, user_id, order_id, direction, amount_cent,
balance_after_cent, balance_type, biz_type, biz_no, remark, created_at
)
SELECT
CONCAT('LDG', DATE_FORMAT(NOW(), '%Y%m%d%H%i%s'), LPAD(seq, 6, '0')) as ledger_no,
u.id as user_id,
IF(seq % 2 = 0, o.id, NULL) as order_id,
CASE WHEN seq % 2 = 0 THEN 'in' ELSE 'out' END as direction,
((seq % 500) * 100) + seq as amount_cent,
100000 + ((seq % 1000) * 100) as balance_after_cent,
CASE WHEN seq % 5 = 0 THEN 'frozen' ELSE 'available' END as balance_type,
CASE (seq % 6)
WHEN 0 THEN 'rent_payment'
WHEN 1 THEN 'deposit_freeze'
WHEN 2 THEN 'settlement'
WHEN 3 THEN 'refund'
WHEN 4 THEN 'recharge'
ELSE 'withdraw'
END as biz_type,
CONCAT('BIZ', LPAD(seq, 10, '0')) as biz_no,
CONCAT('测试流水', seq) as remark,
DATE_SUB(NOW(), INTERVAL (seq % 180) DAY) as created_at
FROM (
SELECT @row4 := @row4 + 1 AS seq
FROM
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT @row4 := current_batch * batch_limit) r
LIMIT batch_limit
) seqs
INNER JOIN tmp_users u ON u.row_num = (seq % user_count) + 1
LEFT JOIN tmp_orders o ON o.row_num = (seq % order_count) + 1
WHERE seq <= batch_size
LIMIT batch_limit;
SET current_batch = current_batch + 1;
COMMIT;
END WHILE;
DROP TEMPORARY TABLE IF EXISTS tmp_users;
DROP TEMPORARY TABLE IF EXISTS tmp_orders;
END$$
DELIMITER ;
-- ============================================
-- 5. 批量生成聊天会话和消息
-- ============================================
DROP PROCEDURE IF EXISTS generate_chat_data_batch;
DELIMITER $$
CREATE PROCEDURE generate_chat_data_batch(IN message_count INT)
BEGIN
DECLARE batch_limit INT DEFAULT 1000;
DECLARE batches INT;
DECLARE current_batch INT DEFAULT 0;
DECLARE conversation_count INT DEFAULT 0;
DECLARE user_count INT DEFAULT 0;
-- 先生成聊天会话(基于订单)
INSERT INTO chat_conversations (order_id, type, title, status, last_message_at)
SELECT
ro.id,
'order_group',
CONCAT('订单', ro.order_no, '群聊'),
'active',
ro.created_at
FROM rental_orders ro
WHERE NOT EXISTS (SELECT 1 FROM chat_conversations WHERE order_id = ro.id)
LIMIT 1000
ON DUPLICATE KEY UPDATE order_id=order_id;
DROP TEMPORARY TABLE IF EXISTS tmp_conversations;
CREATE TEMPORARY TABLE tmp_conversations (
id BIGINT PRIMARY KEY,
row_num INT
);
INSERT INTO tmp_conversations (id, row_num)
SELECT id, (@rn := @rn + 1)
FROM chat_conversations, (SELECT @rn := 0) init
ORDER BY id;
SELECT COUNT(*) INTO conversation_count FROM tmp_conversations;
DROP TEMPORARY TABLE IF EXISTS tmp_users;
CREATE TEMPORARY TABLE tmp_users (
id BIGINT PRIMARY KEY,
row_num INT
);
INSERT INTO tmp_users (id, row_num)
SELECT id, (@rn2 := @rn2 + 1)
FROM users, (SELECT @rn2 := 0) init
ORDER BY id;
SELECT COUNT(*) INTO user_count FROM tmp_users;
SET batches = CEIL(message_count / batch_limit);
WHILE current_batch < batches DO
INSERT INTO chat_messages (
conversation_id, sender_type, sender_id, sender_role,
content_type, content, created_at
)
SELECT
c.id as conversation_id,
'user' as sender_type,
u.id as sender_id,
CASE WHEN seq % 2 = 0 THEN 'owner' ELSE 'renter' END as sender_role,
'text' as content_type,
CONCAT('这是测试消息', seq, ',内容随机生成用于压力测试') as content,
DATE_SUB(NOW(), INTERVAL (seq % 30) DAY) as created_at
FROM (
SELECT @row5 := @row5 + 1 AS seq
FROM
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT @row5 := current_batch * batch_limit) r
LIMIT batch_limit
) seqs
INNER JOIN tmp_conversations c ON c.row_num = (seq % conversation_count) + 1
INNER JOIN tmp_users u ON u.row_num = (seq % user_count) + 1
WHERE seq <= message_count
LIMIT batch_limit;
SET current_batch = current_batch + 1;
COMMIT;
END WHILE;
DROP TEMPORARY TABLE IF EXISTS tmp_conversations;
DROP TEMPORARY TABLE IF EXISTS tmp_users;
END$$
DELIMITER ;
-- ============================================
-- 本文件只创建存储过程,不直接生成数据。
-- 请使用 scripts/stress_test.sh data 按参数生成
-- ============================================
SET FOREIGN_KEY_CHECKS = 1;