[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

这篇具有很好参考价值的文章主要介绍了[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上篇文章是中规中矩的标准计算函数,就算不用pgrx,也是可以正常理解的,所以基本上没有什么对于pgrx框架有关系的东西(唯一有关系的东西,应该就是Rust的时间类型与pgrx的时间类型的计算了)。

这篇文章会讲一个pgrx对于postgresql或者说对于任何数据库扩展来说都比较有用的开发内容:返回序列以及表的函数的编写。

针对上篇文章,用了一个概念,就是:单值输入与单值输出,那么相对来说,这篇文章描写的就是单值输入与多值输出。

所谓的多值输出,就是可以输出超过一行的函数。

如下所示,这个Python函数,就是单值输入,多值输出的例子:我们输入1个整数,然后函数根据我们输入的整数,去生成一个list。

例如我们输入的是5,得到的结果就是[0,1,2,3,4]。

def generate_list(x:int):
    return [i for i in range(0,x)]

在本系列的第一篇文章里面,大家可能还记得我给出来的这样一个效果:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

那么在pgrx里面,如何来实现呢?

pgrx对于这种集合类型的支持,有很多种,例如Vec、range这些个类型都是支持的,但是对于数据库来说,这种返回超过一行序列的方法被称之为srf,即:Set Returning Functions。

在Postgresql里面,本身就内置了很多srf,例如generate_series()这个就是最著名的内置srf。

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

而在pgrx里面,如果要实现srf,需要包装的类型分别是:

  • SetOfIterator
  • TableIterator

注意:这两个类型是pgrx 0.7.0之后版本才推出的,如果你看的旧版本的介绍,发现是没有这两个类型的。

首先我们来看如何使用SetOfIterator来实现一个生成自定义序列的srf:

表示rust风格的代码,是这样写的:

#[pg_extern]
fn my_generate_series(start:i64,
                    end:i64,
                    step:i64)->SetOfIterator<
'static, i64
>{
    SetOfIterator::new((start..=end).step_by(step as usize).into_iter())
}

不过这种写法编程,对于没有接触过函数式编程的同学感觉非常痛苦,所以我们写成传统的过程化编程风格:

#[pg_extern] fn my_generate_series2(start:i64,end:i64,step:i64) ->SetOfIterator<'static, i64>{ //初始化一个集合 let mut series:Vec<i64> = vec![]; //迭代从start - end的所有数值 for x in start..=end{ //如果有setp,则满足条件在放入集合中 if x % step ==0{ series.push(x); } } //把生成的集合,放入SetOfIterator 包装类型中,返回出来 SetOfIterator::new(series) }

我们可以来看看两种不同的写法,实际上结果是一样的:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

生成50000个数值,效率也是差不多的:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

不过对于写过函数式编程的同学来说,第一种写法更加简洁明了……起码对于我来说,我还是喜欢第一种写法的:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

下面我们来看一个小案例:

第一个是定制一个我们自己的UUID函数:

做数据库设计的时候,最头疼的问题之一是如何设计一个有意义、高性能其能保证在一定程度上不会冲突的ID。 其中一种方案就是用UUID:UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,他可以保证生成在时间和空间上的唯一编码。

虽然从PG13的版本开始,就已经提供了uuid的生成函数,但是它只能生成UUID V4版本的序列:

常用的自增 ID 缺乏随机性,且会暴露数据细节(黑客可以通过 id 的规律爬到大量数据);UUID v4 是基于随机数的,具备足够随机性,但其最大的问题就是无法排序。

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

而最新的UUID 7版本,已经支持了排序和大小比较,所以我们想在postgresql里面使用UUID V7版本,怎么做呢?

首先在cargo里面把需要的包导入进来:

uuid7 = "0.6.2"

然后编写一个方法:

#[pg_extern]
fn my_uuid7() -> String {
    uuid7::uuid7().to_string()
}

然后可以阔以了:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

下面我们来看看效果:

生成出来的表是这样的:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

做一个查询:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

简单得让人难以置信……真是太残暴了……

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

下面来做一个数据分析中常用的操作:抽样。

例如上面那个表,我做了20万条数据数据进去,现在需要对它进行随机抽样,而且要求抽样满足各种分布,例如正态分布、均匀分布或者泊松分布以及伯努利分布……

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

如果仅仅是做随机抽样,那么SQL原生提供的RAND()函数就可以搞定了:

注意前面那么一堆代码,是我给这个表加了个行号,用来标识信息,否则uuid更本看不出效果来,ORDER BY random()的意思就是随机排序。

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

如果要做正态分布(高斯)的话,postgresql也提供了一个扩展模块:tabfunc中的normal_rand 函数:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

安装好这个扩展之后,可以看见有如下函数:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

例如我们可以用这个函数生成10个均值为10万,标准差为1万的数值:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

然后可以用于抽样:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

但是其他的分布,SQL就比较麻烦了,所以我们针对此需求,来编写一个伯努利抽样的扩展,代码如下:

  1. 直接导入Rust的随机数工具包rand(Rust的随机数包)和rand_distr(这个包用来生成泊松分布抽样),写在工程的cargo.toml配置文件里面:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

  1. 编写扩展函数,代码如下:
use rand_distr::{Poisson};
#[pg_extern]
fn my_generate_possion(lambda:f64,cnt:i64) -> SetOfIterator<'static,i64>{
    let poi = Poisson::new(lambda).unwrap();
    let v = poi.sample(&mut rand::thread_rng());

    SetOfIterator::new((0..cnt).into_iter()
    .map(move |x| poi.sample(&mut rand::thread_rng()) as i64))
}

编译运行,

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

测试结果如下:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

现在我们配合这个函数做一个泊松抽样:

[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列

打完收工文章来源地址https://www.toymoban.com/news/detail-437265.html

到了这里,关于[pgrx开发postgresql数据库扩展]6.返回序列的函数编写(1)单值序列的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据库】什么是 PostgreSQL?开源数据库系统

    PostgreSQL 是一个开源的对象关系数据库系统,本文,我们将讨论 PostgreSQL、它的用途和好处。 PostgreSQL 是由 PostgreSQL Global Development Group 开发的高级 开源关系数据库管理系统(RDBMS) 。它作为 POSTGRES 项目的一部分于 1986 年在加州大学伯克利分校启动,它最初于 1996 年 7 月 8 日发布

    2023年04月08日
    浏览(36)
  • postgresql数据库定时备份到远程数据库

    1.老规矩,服务器目录结构: conf目录无内容 profile: 其中: 最后一行 export PGPASSWORD=‘root’ 是需要备份的数据库的密码,因为直接用 pg_dump 命令备份需要输入密码交互,而我们需要达到自动备份,所以借助这种方式不需要输入密码 docker-compose.yml: 启动容器: 然后再data目录下面

    2024年02月09日
    浏览(37)
  • PostgreSQL Linux操作PostgreSQL数据库

    PostgreSQL教程 菜鸟教程:https://www.runoob.com/postgresql/postgresql-tutorial.html 登录PG数据库:psql -U 用户名(U需要大写) 登录PG数据库(指定主机、端口,并进入指定数据库): psql -U 用户名 -h 127.0.0.1 -p 5432 -d 数据库名 -U 登录的用户名 -h 连接的主机(默认127.0.0.1,可替换成远程主机

    2024年02月11日
    浏览(48)
  • [运维|数据库] docker postgresql数据库环境变量配置

    要配置Docker中的PostgreSQL数据库的环境变量,可以使用以下方法: 使用Docker命令行: 将 用户名 , 密码 , 数据库名 替换为你想要设置的实际值。这将创建一个名为 mypostgres 的容器,并将 PostgreSQL 的用户名、密码和数据库名设置为指定的值。 -p 5432:5432 指定了容器内部和主机之间

    2024年02月09日
    浏览(52)
  • 数据库新闻速递 -- POSTGRESQL 正在蚕食数据库市场 (翻译)

    开头还是介绍一下群,如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请加 liuaustin3微信号 ,在新加的朋友会分到3群(共1140人左右 1 + 2 + 3) 尽管NoSQL数据库继续蓬勃发展,但关系型数据库仍

    2024年02月13日
    浏览(50)
  • Postgresql数据库死锁

    ERROR: deadlock detected DETAIL: Process 95 waits for ShareLock on transaction 3553457; blocked by process 187. Process 187 waits for ShareLock on transaction 3553458; blocked by process 95. HINT: See server log for query details. CONTEXT: while updating tuple (0,6) in relation “deadlock_example” 其中 Process 95 在等待共享锁(ShareLock)的事务

    2024年01月20日
    浏览(52)
  • PostgreSQL-数据库命令

    一个数据库是一个或多个模式的集合,而模式包含表、函数等。因此,完整的逻辑组织结构层次是服务器实例(PostgreSQL Server)、数据库(Database)、模式(Schema)、表(Table),以及某些其他对象(如函数)。一个PostgreSQL服务器实例可以管理多个数据库。当应用程序连接到一

    2024年02月14日
    浏览(39)
  • PostgreSQL 创建数据库

    PostgreSQL 创建数据库可以用以下三种方式: CREATE DATABASE 命令需要在 PostgreSQL 命令窗口来执行,语法格式如下: 例如,我们创建一个 runoobdb 的数据库: createdb 命令创建数据库 createdb 是一个 SQL 命令 CREATE DATABASE 的封装。 参数说明: . dbname:要创建的数据库名。 . description:关

    2024年02月12日
    浏览(43)
  • 【PostgreSql】只删除整个数据库的表(不删除数据库)

    环境: windows 数据库: postgresql 前提: 此方法用来删除数据库所有的表,不包括保存的函数语句、查询语句等(可适用于需要删除整个数据库的数据却又不想删除数据库或者数据库正在连接无法被删除的情况) 查询数据库所有的表(假设表都在public模式下) 这个语句会列出

    2024年04月12日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包