【问题标题】:postgres: get random entries from table - too slowpostgres:从表中获取随机条目 - 太慢了
【发布时间】:2011-11-28 18:09:49
【问题描述】:

在我的 postgres 数据库中,我有以下关系(为了这个问题而简化了):

Objects (currently has about 250,000 records)
-------
n_id
n_store_object_id (references store.n_id, 1-to-1 relationship, some objects don't have store records)
n_media_id (references media.n_id, 1-to-1 relationship, some objects don't have media records)

Store (currently has about 100,000 records)
-----
n_id
t_name,
t_description,
n_status,
t_tag

Media
-----
n_id
t_media_path

到目前为止,一切都很好。当我需要查询数据时,我运行它(注意最后的limit 2,作为要求的一部分):

select
    o.n_id,
    s.t_name,
    s.t_description,
    me.t_media_path
from
    objects o
    join store s on (o.n_store_object_id = s.n_id and s.n_status > 0 and s.t_tag is not null)
    join media me on o.n_media_id = me.n_id
limit
    2

这工作正常,并按预期返回两个条目。执行时间约为 20 毫秒 - 很好。

现在每次查询运行时我都需要获得 2 个随机条目。我想我会添加order by random(),就像这样:

select
    o.n_id,
    s.t_name,
    s.t_description,
    me.t_media_path
from
    objects o
    join store s on (o.n_store_object_id = s.n_id and s.n_status > 0 and s.t_tag is not null)
    join media me on o.n_media_id = me.n_id
order by
    random()
limit
    2

虽然这给出了正确的结果,但现在执行时间约为 2,500 毫秒(超过 2 秒)。这显然是不可接受的,因为它是为获取 Web 应用程序中的页面数据而运行的众多查询之一。

所以,问题是:我怎样才能获得随机条目,如上所述,但仍将执行时间保持在合理的时间内(即我的目的可以接受不到 100 毫秒)?

【问题讨论】:

标签: sql postgresql optimization random


【解决方案1】:

当然,在获取第一行之前,它需要根据随机标准对整个事物进行排序。也许您可以改用offset 中的random() 来解决?

【讨论】:

  • 为了使用offset,我需要知道结果集中的记录总数——对吗?但是,仅在群组中执行 select count(1) 仍然需要 1 秒以上。
  • 是的,您可能已经缓存了它或其他什么……此外,您可以将 Alex 的方法与此结合起来。嗯,这是我能想到的最好的了;)
  • 别担心,我没有抱怨。缓存计数不是一个简单的选择,因为它是事务表之一,所以那里的数据经常变化(通常是插入和更新,但很少删除)。
  • 我只是假设因为你需要随机性,所以有点不同步并不是很糟糕(只要你不删除行)。
  • 好的,经过各种迭代和不同方法的测试,我得到了某种的东西,大致基于 Alex 的回答。感谢您的帮助
【解决方案2】:

以下是之前就该主题所做的一些工作,可能会有所帮助:

http://blog.rhodiumtoad.org.uk/2009/03/08/selecting-random-rows-from-a-table/

【讨论】:

    【解决方案3】:

    我认为您最好先选择随机对象,然后在选择这些对象后执行这些对象的连接。即,查询一次以选择随机对象,然后再次查询以仅加入那些已选择的对象。

    【讨论】:

    • 感谢您的建议。刚刚尝试过 - 更好,但仍然不够好:大约 600 毫秒。不过还是谢谢。
    • 好的,经过多次迭代等,我终于得到了有点有效的东西。由于它是基于您的建议松散的,我会接受您的回答。
    【解决方案4】:

    您的问题似乎是这样的:您有一个包含 250,000 行的表,需要两个随机行。因此,您必须生成 250,000 个随机数,然后按行数对行进行排序。两秒钟的时间对我来说似乎很快。

    唯一真正加快选择速度的方法不是必须提供 250,000 个随机数,而是通过索引查找行。

    我认为您必须更改表架构以针对这种情况进行优化。像这样的东西怎么样:

    • 1) 创建一个序列从 1 开始的新列。
    • 2) 然后每一行都会有一个number
    • 3) 在以下位置创建索引:number % 1000
    • 4) 查询number % 1000 等于随机数的行 介于 0 和 999 之间(这应该会命中索引并加载随机 数据库的一部分)
    • 5) 然后您可以将 RANDOM() 添加到您的 ORDER BY 子句中,然后 然后它将对您的数据库中的那部分进行排序并达到 1,000 倍 更快。
    • 6) 然后选择前两行。

    如果这仍然不够随机(因为行总是成对的,具有相同的“哈希”),您可以将两个随机行合并,或者在查询中使用 OR 子句并生成两个随机键.

    希望这些方面的东西可以非常快速且相当随机。

    【讨论】:

      猜你喜欢
      • 2017-06-08
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多