You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何高效随机打乱数据库表行并生成新表?order by random()性能不佳

嘿,我知道用select * from table order by random()来打乱表数据虽然直观,但数据量上去后确实慢得让人头疼——毕竟它得给每一行生成随机值再做全表排序,开销不小。结合你提到的target列分0和1两类的情况,给你几个更高效的解决方案:

方案1:分批次随机排序(针对target分组优化)

如果你的数据库支持窗口函数(比如PostgreSQL、MySQL 8.0+、SQL Server),可以针对target的两类分别打乱,再合并结果。这种方式比全表排序的开销小,而且能保持同类数据内的随机分布:

WITH shuffled_groups AS (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY target ORDER BY RANDOM()) AS row_rank
    FROM your_table
)
SELECT cst_id, name, salary, fund, age, target
FROM shuffled_groups
ORDER BY target, row_rank;

要是你不需要按target分组,只是单纯全表打乱,下面这个方案性能更好:

方案2:主键关联随机数,避免全表排序

这个方法绕开了给全表生成随机值后排序的操作,而是先给主键生成随机数,再通过主键关联原表,最后按随机数排序——计算开销会小很多:

SELECT t.*
FROM your_table t
JOIN (SELECT cst_id, RANDOM() AS rand_val FROM your_table) r 
ON t.cst_id = r.cst_id
ORDER BY r.rand_val;

方案3:直接生成打乱后的新表

既然你最终要生成新表,那可以一步到位,用上面的查询直接创建新表,省去中间步骤:

CREATE TABLE new_shuffled_table AS
SELECT t.*
FROM your_table t
JOIN (SELECT cst_id, RANDOM() AS rand_val FROM your_table) r 
ON t.cst_id = r.cst_id
ORDER BY r.rand_val;

为啥order by random()这么慢?

简单说,random()会给每一行生成一个随机值,数据库随后要对所有这些值做排序操作,这是一个*O(n log n)*的耗时操作——数据量越大,等待时间越长。上面的方案要么缩小了排序的数据集,要么避免了全表排序的额外开销,性能提升会很明显。

内容的提问来源于stack exchange,提问作者Robinson

火山引擎 最新活动