当前位置: 首页 > 面试题库 >

来自Sql数据库的简单随机样本

姬高澹
2023-03-14
问题内容

如何在SQL中获取有效的简单随机样本?有关的数据库正在运行MySQL。我的表至少有200,000行,我想要一个大约10,000的简单随机样本。

“显而易见”的答案是:

SELECT * FROM table ORDER BY RAND() LIMIT 10000

对于大型表,这太慢了:它对每一行调用RAND()(已经将其放在O(n)),并对它们进行排序,使其充其量为O(n lg
n)。有没有办法比O(n)更快地做到这一点?

注意 :正如Andrew Mao在评论中指出的那样,如果在SQL Server上使用这种方法,则应使用T-
SQL函数NEWID(),因为RAND()可能对所有行返回相同的值。

编辑:5年后

我再次遇到了一个更大的表的问题,最终使用了@ignorant解决方案的一个版本,进行了两次调整:

  • 将行采样到我所需样本大小的2-5倍,以便宜的价格订购RAND()
  • 在每次插入/更新时,将RAND()的结果保存到索引列中。(如果您的数据集不是很重更新,则可能需要寻找另一种方法来使该列保持最新状态。)

要获取一个表的1000个项目的样本,我对数据行进行计数,并使用Frozen_rand列对结果进行平均采样,平均减少到10,000行:

SELECT COUNT(*) FROM table; -- Use this to determine rand_low and rand_high

  SELECT *
    FROM table
   WHERE frozen_rand BETWEEN %(rand_low)s AND %(rand_high)s
ORDER BY RAND() LIMIT 1000

(我的实际实现涉及更多工作,以确保我不会采样不足,并手动将rand_high包起来,但是基本思想是“将N随机减少到几千。”)

尽管这样做有所牺牲,但它允许我使用索引扫描对数据库进行采样,直到足够小以再次进行ORDER BY RAND()。


问题答案:

这里有一个关于此类问题的非常有趣的讨论: http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-
get-random-rows-from-table/

我认为在没有任何假设的情况下,您的O(n lg n)解决方案是最好的。尽管实际上使用好的优化程序或稍有不同的技术,但您列出的查询可能会更好一些,O(m * n)其中m是所需的随机行数,因为它不必对整个大型数组进行排序,它可能只搜索最小的m次。但是对于您发布的那种数字,无论如何,m大于lg n。

我们可以尝试以下三种假设:

  1. 表中有一个唯一的,已索引的主键

  2. 您要选择的随机行数(m)比表中的行数(n)小得多

  3. 唯一主键是一个整数,范围是1到n,没有空格

仅假设1和2,我认为这可以在O(n)中完成,尽管您需要向表中写入一个完整的索引以匹配假设3,因此不一定需要快速的O(n)。如果我们可以另外假设该表有其他优点,则可以在O(m
log m)中执行任务。假设3是一个易于使用的好属性。有了一个很好的随机数生成器,它可以保证在连续生成m个数时不会重复,因此O(m)解决方案是可能的。

给定这三个假设,基本思想是生成介于1和n之间的m个唯一的随机数,然后从表中选择具有这些键的行。我现在没有mysql或任何更新,所以在伪代码中看起来像这样:

create table RandomKeys (RandomKey int)
create table RandomKeysAttempt (RandomKey int)

-- generate m random keys between 1 and n
for i = 1 to m
  insert RandomKeysAttempt select rand()*n + 1

-- eliminate duplicates
insert RandomKeys select distinct RandomKey from RandomKeysAttempt

-- as long as we don't have enough, keep generating new keys,
-- with luck (and m much less than n), this won't be necessary
while count(RandomKeys) &lt m
  NextAttempt = rand()*n + 1
  if not exists (select * from RandomKeys where RandomKey = NextAttempt)
    insert RandomKeys select NextAttempt

-- get our random rows
select *
from RandomKeys r
join table t ON r.RandomKey = t.UniqueKey

如果您真的担心效率,则可以考虑使用某种过程语言来生成随机密钥,并将结果插入数据库中,因为除SQL以外,几乎任何其他方法都可能在所需的循环和随机数生成方面更好。



 类似资料:
  • /***政治动物*contentscript.js加载到manifest.json中列出的每个页面*此插件将新闻网站上的所有图像替换为*穿西装的动物的图片,作为对新闻内容的评论。为Web 2制作*2013年11月20日*/ //随机图像数组 //重定向 //确保代码符合我的要求。只要链接显示的数字大于-1,那么站点扩展就是working console.log(referer);console.l

  • 问题内容: 其实我的主机上有一个php网站。现在,我将个性化一个Wordpress主题以替换它。暂时还可以,但是旧网站具有内置功能,可以使用令牌连接到另一个数据库。此连接仅用于获取一些数据。 您能告诉我如何在新的wordpress主题中实现此功能吗? 是否存在一个wordpress插件? 谢谢 问题答案: 将wordpress连接到第二个数据库 (没有令牌) 的最简单方法是添加以下代码(用连接数据

  • 问题内容: 我想从具有存储为clob的XML列为testclob的表TRAPTABCLOB中使用sql提取Decision的值。 样本XML如下。 问题答案: 尝试 这是一个sqlfiddle演示

  • 我在这个练习中的平均距离有问题。它应该接近N步的sqrt,但它更低。你能帮我找出我的错误在哪里吗? 二维随机游动。二维随机游动模拟了一个粒子在点网格中运动的行为。在每一步中,随机步行者以1/4的概率向北、向南、向东或向西移动,与之前的移动无关。确定N步后随机步行者离起点有多远(平均)。(理论答案:按sqrt(N)的顺序)

  • 问题内容: 我们有一个应用程序被部署了120次,每个应用程序的配置略有不同。我们希望将配置存储在数据库中,以进行审核和管理。 如何不使用XML直接从数据库实例化Spring Bean? 谢谢 问题答案: 您不能有零个XML配置(除非您使用JavaConfig,这不会使情况有所不同)。您可以将其中一些外部化到数据库,并使用custom 。有关如何实现此目的,请参见本文。

  • 本文向大家介绍C/C++产生随机数函数简单介绍,包括了C/C++产生随机数函数简单介绍的使用技巧和注意事项,需要的朋友参考一下 计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535,当你取得65535个随机数后它们又重复出现了。)  我们知道rand(