Python 3.x 如何基于Django模型实例的权重字段快速获取该模型实例的加权随机实例?

Python 3.x 如何基于Django模型实例的权重字段快速获取该模型实例的加权随机实例?,python-3.x,django,algorithm,performance,random,Python 3.x,Django,Algorithm,Performance,Random,我使用Postgres作为数据库后端,但我认为这并不重要。另外,我仍然希望使用sqlite3作为本地开发数据库,因此理想情况下,任何方法都可以同时适用于这两种数据库 通过“加权”,我的意思是,该数据库表中的某些项比其他项更有可能基于从0到+inf的启发式值出现,其中0是“永远不会被拾取的”、1与任何其他实例一样,而2是”被选中的可能性是任何其他实例的两倍” 我已经讨论过随机抽取模型的实例,但就我所见,没有任何方法可以通过权重快速实现这一点 我的模型: 有数百万个实例 具有权重分码字段,可以随时

我使用Postgres作为数据库后端,但我认为这并不重要。另外,我仍然希望使用
sqlite3
作为本地开发数据库,因此理想情况下,任何方法都可以同时适用于这两种数据库

通过“加权”,我的意思是,该数据库表中的某些项比其他项更有可能基于从
0
+inf
的启发式值出现,其中
0
是“永远不会被拾取的”、
1
与任何其他实例一样,而
2
是”被选中的可能性是任何其他实例的两倍”

我已经讨论过随机抽取模型的实例,但就我所见,没有任何方法可以通过权重快速实现这一点

我的模型:

  • 有数百万个实例
  • 具有
    权重
    分码字段
    ,可以随时更新,即使在运行时也可以
  • 除了使用此随机选择算法之外,在任何地方都不会引用它(例如,可以随时删除并重新创建它,而不会出现任何问题)
我所追求的是一种比我尝试过的解决方案更快的快速方法,或者解释为什么我尝试过的一种解决方案是我能得到的最快的解决方案

避免XY问题 我想从数据库表中选择“新鲜”的内容,但仍有机会看到一些较旧的内容。如果某些内容被浏览得太频繁或不太受欢迎,则应减少其出现频率。理想情况下,我可以控制其频率:“啊,因此,这将是网站上其他内容的1.5倍。”

我试过的东西 随机选择并根据概率滚动重试
  • 计算模型的实例总数,例如:100
  • 选择模型的随机实例
  • 1*weight/instances\u count
    掷骰子,确定该物品是否应被扔回,并再次进行随机选择
这看起来很慢,“回退”的随机性可能永远不会终止。一般来说,这真的很简陋,我不想使用它。把它放在第一位,因为它非常“简单”,我很可能会忽略它

选择每个元素ID和权重,并使用随机权重算法选择ID
  • 选择所有行
  • 根据权重为每行分配一个ID范围
  • 动态添加所有权重
  • 掷一个
    所有权重之和的骰子
  • 无论选择什么,根据权重选择一个ID
问题是,对于数百万行来说,这个算法似乎很慢。这是“幼稚”的解决方案

根据权重分配一系列ID,并动态删除/重新创建实例
  • 每当添加某些内容或更改权重时,删除包含实例唯一详细信息的所有实例,并使用相同的元信息创建更多实例
  • 通常选择一个随机实例
需要注意的是,只有基于整数的权重是可能的。此外,性能问题从
SELECT
转移到
INSERT
DELETE
操作

重新思考整个模型并引入“回退”值
  • 添加一个
    throw\u back\u probability
    字段,而不是
    weight
  • 如果概率为
    0.0
    它将永远不会被退回。否则,根据
    退回概率
    滚动模具并在需要时退回
  • 将算法限制为3个“回退”(或任意数)
这最终解决了问题,但可能仍然需要更多的数据库调用,这是一个间接的解决方案



正是如此,所以我确信我忽略了一些基于
注释
的解决方案(或类似方案)。提前感谢您的帮助!

您可以将切分与您列出的任何方法相结合。选择一些切分(最好是行数/切分数明显大于log(行数)避免出现高概率的空碎片),为每一行分配一个统一的随机分片ID,并将分片ID作为主键的第一个条目,以便表按分片排序。要进行采样,请选择一个统一的随机分片,然后在分片内进行采样。这在分片总数不平衡的情况下是不准确的,但如果分片足够大,则大数定律rs会起作用。(如果碎片太大,那么这就开始破坏碎片分割的点。)

采样必须有多精确?不需要精确到@Davidisenstat,但粗略的“加权”程度更可取。不错!这应该会让事情更快,同时还允许“新鲜体验”“对于每次运行算法的用户。谢谢