暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL17random函数还可以这样用?

原创 墨竹 4天前
35

PostgreSQL17random函数还可以这样用?

random函数应该是开发人员使用频率比较高的函数。如果你想要生成1到100的随机函数,你是否有过那么一瞬间,因为它复杂的使用方式而烦恼?PostgreSQL 17的random函数让这一切变得简单,有时正是由于这些小功能的优化,反而让使用者觉得这个数据库真的不错。

在早期的版本中,对于random函数,返回的是[0,1)之间的双精度值,但是在我们真的实际操作中又何时需要这样的一个双精度随机数?这样的场景的应该是比较少见吧,在真实的操作中经常是用该值作为中间值。这个对于研发人员来说也是一个痛点。下面我们来详细的看一下PostgreSQL17中对于random函数进行了哪些方面的优化。

功能介绍

在PostgreSQL17上我们先来看看random函数的定义。

postgres=# \df random
                            List of functions
   Schema   |  Name  | Result data type |   Argument data types    | Type
------------+--------+------------------+--------------------------+------
 pg_catalog | random | double precision |                          | func
 pg_catalog | random | bigint           | min bigint, max bigint   | func
 pg_catalog | random | integer          | min integer, max integer | func
 pg_catalog | random | numeric          | min numeric, max numeric | func
(4 rows)

在PostgreSQL17的补丁新增了3个可通过SQL调用的函数,用于生成指定范围内的均匀分布随机整数或任意精度数字。random函数的返回值在[min, max]的范围内,对于numeric类型,结果的小数位数为max (scale(min), scale(max))即小数点后的位数等于“min”或“max”在小数点后的位数,以位数较多者为准,因此它可以生成超大整数及任意精度小数

应用场景

在PG17之前的版本中,如何生成1到10之间的随机整数?常规操作使用如下的方式:

SELECT floor(random()*10+1) FROM generate_series(1,10);
 floor
-------
     9
     7
     3
     1
     6
     8
     9
     8
     5
     5
(10 rows)
Time: 15.403 ms

在PG17中的使用方法,看起来更加的直观,使用也很便捷

postgres=# select random(1,10) FROM generate_series(1,10);
 random
--------
      2
      7
      9
      1
     10
      9
      7
      9
      2
      2
(10 rows)
Time: 1.072 ms

假如我们需要生成小数位为2位精度的小数,在PG17之前的版本,常规操作使用如下的方式:

testdb=# SELECT round((random()*9+1)::numeric,2) FROM generate_series(1,10);
 round
-------
  7.23
  1.38
  8.82
  5.80
  7.69
  3.07
  7.07
  8.27
  2.98
  8.43
(10 rows)
Time: 0.287 ms

在PG17中,现在只需要很贱的操作,如下:

postgres=# select random(1.0,10.00) FROM generate_series(1,10);
 random
--------
   3.94
   9.55
   6.74
   9.77
   6.93
   1.83
   3.48
   3.52
   9.82
   2.87
(10 rows)
Time: 0.183 ms

通过对random函数的参数进行限制,就可以精确的保留两位小数。即使当输入的参数小数位不同时,函数也会自动取最大值。 另外我们也可以看到不论是返回整数还是小数,从执行耗时看,返回int类型,耗时从15.403 ms降到1.072 ms,返回numeric类型耗时从0.287 ms降到0.183 ms,综合看性能提升30%以上甚至更多,而且PG17中的random函数使用更加的简洁,可读性也很强。

四大技术优势

在PG17中对于random函数新特性,不仅仅在使用上让我们更加便捷,而且从技术上来说函数也有四大优势。

  1. 支持任意范围
    • 要求满足 max ≥ min 条件,所有的边界值都可以使用
    • 传统基于random()的SQL/PLpgSQL实现可能因max-min差值过大导致整数溢出
  2. 全区间均匀分布
    • 传统实现如((max-min)*random()+min)::int会导致端点值出现的概率仅为中间值的50%,这个因为取整导致的
  3. 增强PRNG利用效率
    • 突破原有双精度浮点数52位精度限制,PRNG(Pseudo-Random Number Generator,伪随机数生成器)是 PostgreSQL 中生成确定性数值序列的核心算法机制,
  4. 高效的生成随机数
    • 替代传统需多次调用random()拼接数字字符串的低效方案
    • 生成随机数值的耗时降低50%以上(本机测试,仅供参考)

总结

PostgreSQL17中random函数有两个参数来指定返回随机数的最小值和最大值,可以是int、bigint和numeric类型指定范围,这样既简单又直观明了。说到便捷性,就不得不提到国产数据库,希望能多多的吸收这些优秀的功能点,优化自身产品。

参考

https://www.postgresonline.com/journal/index.php?/archives/419-PG-17-new-random-functions.html#newrandom

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=e6341323a

https://www.postgresql.org/message-id/CAEZATCV89Vxuq93xQdmc0t-0Y2zeeNQTdsjbmV7dyFBPykbV4Q@mail.gmail.com

– / END / –

可以通过下面的方式联系我

  • 微信公众号:@墨竹札记
  • 墨天轮:@墨竹
  • 微信:wshf395062788
  • PGFans:@墨竹

如果这篇文章为你带来了灵感或启发,就请帮忙点赞收藏转发;如果文章中不严谨或者错漏之处,请及时评论指正。非常感谢!

最后修改时间:2025-03-12 09:10:49
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论