【问题标题】:Selecting random rows from a big table in H2 database从 H2 数据库中的大表中选择随机行
【发布时间】:2013-01-14 10:15:12
【问题描述】:

我的数据库中有一个大表(可能有数百万条记录),我需要选择 #X 个随机行(假设 #X 在 10 到 50 之间),但我需要此查询尽可能优化。

表格如下所示:

CREATE TABLE sample (
    id bigint auto_increment PRIMARY KEY,
    user_id bigint NOT NULL,
    screen_name VARCHAR NOT NULL,
    ...
);

我四处寻找,我找到了这样的答案:

SELECT * FROM sample ORDER BY RAND() limit X.

但在我看来,这将获取完整的表格然后对其进行排序,不是吗?

我认为最好生成 10 或 50 个随机整数并执行 select * from sample where rowid in (<random integer list>)。但是 afaik,H2 中缺少 rowid 概念,所以我可能会选择在我的表中使用 ID 列。

如果我能用一个 SQL 查询来完成这项任务,那就太棒了。

有更好的建议吗?

【问题讨论】:

  • H2 确实支持行 ID(select _rowid_ from sample,与 SQLite 相同)。但是使用 ID 列适用于所有数据库,因此这是首选解决方案。

标签: java sql database random h2


【解决方案1】:

以下脚本非常有效地选择每第 n 行。它假设 id 中没有间隙。如果可能存在间隙,那么您可能希望将 range(1, 100) 增加到 range(1, 200) 左右。要获得随机行,最后的公式需要稍作改动:

drop table test;

create table test(
  id bigint auto_increment primary key, 
  name varchar(255));

insert into test 
select x, 'Hello ' || x from system_range(50, 1200);

select * from test t, system_range(1, 100) range
where t.id = x * (select max(id)-min(id) from test) / 100 + 
(select min(id) from test);

【讨论】:

    【解决方案2】:

    您应该使用列id 而不是rowid。列id 存在于您的表中并且是auto_increment

    【讨论】:

      【解决方案3】:

      您可以对您的表进行排名并从中选择随机 50 个排名,避免以任何方式进行排序或分组以使其保持优化。

      【讨论】:

        【解决方案4】:

        我为此做的是创建一个临时表。在表中生成从 1 到最大标识值的随机数。然后从他们的标识值在临时表中的表中选择。

        “执行此操作的单一查询方式”

        创建临时表(我不知道这方面的 h2 语法,但它支持字段名称为 DesiredIdentity 的临时表)

        从表中选择最大标识值。

        使用 rand 命令循环将随机数插入到临时表中,从 1 到所需的随机行数。将随机范围设置为 1 到最大行数。确保不选择相同的随机数。

        然后从身份临时表中身份值所在的表中选择。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-08-23
          • 1970-01-01
          • 1970-01-01
          • 2014-02-01
          • 2013-12-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多