【问题标题】:Select a random row from Oracle DB in a performant way以高效的方式从 Oracle DB 中选择一个随机行
【发布时间】:2018-06-18 11:37:05
【问题描述】:

使用: Oracle Database 12c 企业版 12.1.0.2.0 版

我正在尝试获取随机行。正如其他 stackoverflow 问题中所建议的那样,我像这样使用DBMS_RANDOM.VALUE -

SELECT column FROM
( SELECT column 
  FROM table
  WHERE COLUMN_VALUE = 'Y' -- value of COLUMN_VALUE
  ORDER BY dbms_random.value 
)
WHERE rownum <= 1

但是当请求数量增加时,此查询将无法执行。 所以我正在寻找替代方案。

SAMPLE 对我不起作用,因为通过该子句提取的样本没有与我的WHERE 子句匹配的数据集。查询看起来像这样 -

SELECT column FROM table SAMPLE(1) WHERE COLUMN_VALUE = 'Y'

因为SAMPLE 是在我的WHERE 子句之前应用的,所以大多数情况下这不会返回任何数据。

P.S:我可以将部分逻辑移动到应用层(尽管我绝对不是在寻找建议将所有内容加载到内存的答案)

【问题讨论】:

  • select column from (select column, row_number() over (order by column) as rw from table where column_value='Y') tb where rw = dbms_random.value(1,rw) 呢?看看它是否更好,我会把它作为答案发布(如果是的话)
  • 让我试一试。
  • @JorgeCampos 这似乎没有给我一个随机值,rw 总是 1
  • 考虑 this approach,它似乎很适合您的“内部 where 子句”要求。
  • 是的,我的错。对于子查询返回的第一个注册表,随机函数中的select column from (select column, row_number() over (order by column) as rw from table where column_value='Y') tb where rw = dbms_random.value(1,(select count(*) from table)) rw 将始终评估为 1。这个其他的解决方案可能因为数量不够好,试一试

标签: database oracle database-performance


【解决方案1】:

性能问题包括两个方面:

  • 使用column_value = 'Y'

  • 选择数据
  • 对该子集进行排序以获得随机记录

您没有说column_value = 'Y' 的表子集是大还是小。这很重要,将推动您的战略。

如果有很多记录 column_value = 'Y' 使用SAMPLE 将行限制为按排序。 你是对的,这可能会导致空结果 - 在这种情况下重复查询(你可以另外添加一个增加样本百分比的逻辑以避免大量重复)。 这将在您对数据样本进行排序时提高性能

select id from (
select id from tt SAMPLE(1) where column_value = 'Y' order by  dbms_random.value )
where rownum <= 1; 

如果只有少数记录 column_value = 'Y' 在此列(或单独的分区)上定义索引 - 这样可以有效地访问记录。使用order by dbms_random.value 方法。 排序不会降低少量行的性能。

select id from (
select id from tt where column_value = 'Y' order by  dbms_random.value )
where rownum <= 1;

基本上这两种方法都会使已排序的行保持较小的大小。第一种方法执行类似于 FULL TABLE SCAN 的表访问,第二种方法对选定的 column_value 执行 INDEX ACCESS

【讨论】:

  • 对于我的WHERE 子句,有些情况会返回 10000 行,而有些情况只返回 10 行。对于较少数量的匹配行,我将不得不花费大量时间SAMPLE 来获得随机行,我认为这将是一个开销。而且我无法索引它,因为 Y 不是唯一的。
  • 可以索引一个非唯一列(使用非唯一索引)。偏态分布并不容易,但您可以将这两种方法结合起来。简单地尝试一些小样本量来捕获具有大量结果值的情况(并避免禁止排序)。如果 SAMPLE 没有返回任何结果,您可能会认为只有少量值,您可以回退到索引访问。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 1970-01-01
  • 2017-01-03
  • 2019-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多