PostgreSQL表插入指定规则的100条测试数据失败,求解决方案
解决PostgreSQL插入随机测试数据的问题
你的问题出在PostgreSQL对无关联标量子查询的优化上:那些嵌套的SELECT val FROM unnest(...) ORDER BY random() LIMIT 1子查询没有和外部的generate_series关联,优化器会将其视为常量,只执行一次,所以所有行都复用同一个随机结果。
同时你的INSERT语句还漏掉了contract列的赋值,以下是两种可行的解决方案:
方案1:通过数组索引生成随机值(简洁高效)
直接利用random()计算数组的随机索引,这种方式性能最优:
INSERT INTO test (contract, amount0, amount1, price) SELECT -- 从3个contract值中随机选 (ARRAY['abc', 'klm', 'xyz'])[floor(random() * array_length(ARRAY['abc', 'klm', 'xyz'], 1)) + 1], -- 从5个amount值中随机选 (ARRAY[50, 60, 80, 100, 200])[floor(random() * array_length(ARRAY[50, 60, 80, 100, 200], 1)) + 1], (ARRAY[50, 60, 80, 100, 200])[floor(random() * array_length(ARRAY[50, 60, 80, 100, 200], 1)) + 1], -- 从4个price值中随机选 (ARRAY[1.5, 1.8, 2.1, 2.5])[floor(random() * array_length(ARRAY[1.5, 1.8, 2.1, 2.5], 1)) + 1] FROM generate_series(1, 100);
原理:floor(random() * N)生成0到N-1的整数,加1后对应数组的1-based索引(PostgreSQL数组默认从1开始)。
方案2:使用LATERAL关联子查询(更灵活)
如果需要更复杂的随机逻辑,可以用LATERAL让子查询和外部的generate_series逐行关联,确保每次循环都重新生成随机值:
INSERT INTO test (contract, amount0, amount1, price) SELECT c.val, a0.val, a1.val, p.val FROM generate_series(1, 100) AS gs -- 每个行都执行一次随机选择 CROSS JOIN LATERAL (SELECT val FROM unnest(ARRAY['abc', 'klm', 'xyz']) AS val ORDER BY random() LIMIT 1) AS c CROSS JOIN LATERAL (SELECT val FROM unnest(ARRAY[50, 60, 80, 100, 200]) AS val ORDER BY random() LIMIT 1) AS a0 CROSS JOIN LATERAL (SELECT val FROM unnest(ARRAY[50, 60, 80, 100, 200]) AS val ORDER BY random() LIMIT 1) AS a1 CROSS JOIN LATERAL (SELECT val FROM unnest(ARRAY[1.5, 1.8, 2.1, 2.5]) AS val ORDER BY random() LIMIT 1) AS p;
LATERAL关键字强制子查询为外部查询的每一行单独执行,避免了优化器将其视为常量。
内容的提问来源于stack exchange,提问作者Westcoaster
相关产品推荐
相关产品推荐

