定制插件

oraudb

本插件是基于orafce 的UDB定制版本,UDB在orafce的基础上对部分功能进行了增强。该插件的启用方法如下:

[root@unvdb orafce-VERSION_3_18_1]# ud_sql -c "CREATE EXTENSION oraudb;"

鉴于oraudb的一些对象建立在oracle schema下,可以根据需要在会话级、database级或实例级,设置search_path 包含oracle schema。 例如:

ALTER ROLE role_name SET search_path to "$user",public,oracle ;

或者

ALTER DATABASE database_name  SET search_path = "$user",public,oracle ;

这样就配置完成了,但是需要注意时区问题,orafce 默认使用的是UDB-TX 数据库系统的时区,由单独的参数 orafce.timezone 控制。

[root@unvdb ~]# vi unvdbsvr.conf
log_timezone = 'PRC'
timezone = 'PRC'
orafce.timezone = 'PRC'
[root@unvdb ~]# 
[root@unvdb ~]# ud_sql
unvdbsvr=# show orafce.timezone;
 orafce.timezone
-----------------
 PRC
(1 row)
unvdbsvr=# select oracle.sysdate(),now(),current_timestamp,clock_timestamp();
       sysdate       |              now              |       current_timestamp       |        clock_timestamp
---------------------+-------------------------------+-------------------------------+-------------------------------
 2022-04-01 10:32:42 | 2022-04-01 10:32:41.543877+08 | 2022-04-01 10:32:41.543877+08 | 2022-04-01 10:32:41.543979+08
(1 row)

与 Oracle 数据库兼容的特性

数据类型

数据类型 说明
VARCHAR2 可变长度字符数据类型
NVARCHAR2 可变长度国家字符数据类型
DATE 存储日期和时间的数据类型
unvdbsvr=# set search_path="$user", public, oracle;
SET
unvdbsvr=# CREATE TABLE tt (
unvdbsvr(#  name VARCHAR2(64) NOT NULL,
unvdbsvr(#  status NVARCHAR2(2000),
unvdbsvr(#  update_time DATE default (SYSDATE())
unvdbsvr(# );
CREATE TABLE
unvdbsvr=# \d tt
                        Table "public.tt"
   Column    |      Type       | Collation | Nullable |  Default
-------------+-----------------+-----------+----------+-----------
 name        | varchar2(64)    |           | not null |
 status      | nvarchar2(2000) |           |          |
 update_time | date            |           |          | sysdate()
# 测试在 date 数据类型的字段上创建分区表
create table test_range(id serial, create_time date) partition by range(create_time);
create table test_range_20220301 PARTITION of test_range FOR VALUES FROM ('2022-03-01 00:00:00') TO ('2022-03-02 00:00:00');
create table test_range_20220302 PARTITION of test_range FOR VALUES FROM ('2022-03-02 00:00:00') TO ('2022-03-03 00:00:00');
create table test_range_20220303 PARTITION of test_range FOR VALUES FROM ('2022-03-03 00:00:00') TO ('2022-03-04 00:00:00');
create table test_range_20220304 PARTITION of test_range FOR VALUES FROM ('2022-03-04 00:00:00') TO ('2022-03-05 00:00:00');
create table test_range_20220305 PARTITION of test_range FOR VALUES FROM ('2022-03-05 00:00:00') TO ('2022-03-06 00:00:00');
create table test_range_default partition of test_range default;
unvdbsvr=# \d+ test_range
                                            Partitioned table "public.test_range"
   Column    |  Type   | Collation | Nullable |                Default                 | Storage | Stats target | Description
-------------+---------+-----------+----------+----------------------------------------+---------+--------------+-------------
 id          | integer |           | not null | nextval('test_range_id_seq'::regclass) | plain   |              |
 create_time | date    |           |          |                                        | plain   |              |
Partition key: RANGE (create_time)
Partitions: test_range_20220301 FOR VALUES FROM ('2022-03-01') TO ('2022-03-02'),
            test_range_20220302 FOR VALUES FROM ('2022-03-02') TO ('2022-03-03'),
            test_range_20220303 FOR VALUES FROM ('2022-03-03') TO ('2022-03-04'),
            test_range_20220304 FOR VALUES FROM ('2022-03-04') TO ('2022-03-05'),
            test_range_20220305 FOR VALUES FROM ('2022-03-05') TO ('2022-03-06'),
            test_range_default DEFAULT
# 向分区表中插入数据
unvdbsvr=# insert into test_range (create_time) values (sysdate());
INSERT 0 1
# 查询分区表里的数据
unvdbsvr=# select * from test_range;
 id | create_time
----+-------------
  2 | 2022-07-31
(1 row)
unvdbsvr=# select to_char(create_time,'YYYY-MM-DD HH24:MI:SS') from test_range;
       to_char
---------------------
 2022-07-31 00:00:00
(1 row)

为什么这里的 date 数据类型似乎只存储 ‘年月日’,而 Oracle 的 date 数据类型会存储 ‘年月日 时分秒’。 这里就要说一下使用 orafce 的注意事项,详见后面章节<使用 orafce 的注意事项>。

支持 DUAL 表

unvdbsvr=# \d+ dual
                                  View "public.dual"
 Column |       Type        | Collation | Nullable | Default | Storage  | Description
--------+-------------------+-----------+----------+---------+----------+-------------
 dummy  | character varying |           |          |         | extended |
View definition:
 SELECT 'X'::character varying AS dummy;
unvdbsvr=# \dv public.*
               List of relations
 Schema |        Name        | Type |  Owner
--------+--------------------+------+----------
 public | dual               | view | unvdbsvr
 public | pg_stat_statements | view | unvdbsvr
(2 rows)
unvdbsvr=# select 1 from dual;
 ?column?
----------
        1
(1 row)
unvdbsvrs=# select * from dual;
 dummy
-------
 X
(1 row)
unvdbsvr=# SELECT CURRENT_DATE "date" FROM DUAL;
    date
------------
 2022-04-01

SQL 函数

数学函数

函数名称 说明 对比无插件UDB-TX22.4
BITAND Performs a bitwise AND operation 增强
COSH Calculates the hyperbolic cosine of a number 自带
SINH Calculates the hyperbolic sine of a number 自带
TANH Calculates the hyperbolic tangent of a number 自带

字符串函数

函数名称 说明 对比无插件UDB-TX22.4
INSTR Returns the position of a substring in a string 新增
LENGTH Returns the length of a string in number of characters 增强
LENGTHB Returns the length of a string in number of bytes 新增
LPAD Left-pads a string to a specified length with a sequence of characters 增强
LTRIM Removes the specified characters from the beginning of a string 增强
NLSSORT Returns a byte string used to sort strings in linguistic sort sequence based on locale 新增
REGEXP_COUNT searches a string for a regular expression, and returns a count of the matches 新增
REGEXP_INSTR returns the beginning or ending position within the string where the match for a pattern was located 新增
REGEXP_LIKE condition in the WHERE clause of a query, causing the query to return rows that match the given pattern 新增
REGEXP_SUBSTR returns the string that matches the pattern specified in the call to the function 新增
REGEXP_REPLACE replace substring(s) matching a POSIX regular expression 增强
RPAD Right-pads a string to a specified length with a sequence of characters 增强
RTRIM Removes the specified characters from the end of a string 增强
SUBSTR Extracts part of a string using characters to specify position and length 增强
SUBSTRB Extracts part of a string using bytes to specify position and length 新增

Date/time 函数

函数名称 说明 对比无插件UDB-TX22.4
ADD_MONTHS Adds months to a date 新增
DBTIMEZONE Returns the value of the database time zone 新增
LAST_DAY Returns the last day of the month in which the specified date falls 新增
MONTHS_BETWEEN Returns the number of months between two dates 新增
NEXT_DAY Returns the date of the first instance of a particular day of the week that follows the specified date 新增
ROUND Rounds a date 增强
SESSIONTIMEZONE Returns the time zone of the session 新增
SYSDATE Returns the system date 新增
TRUNC Truncates a date 增强

数据类型格式化函数

函数名称 说明 对比无插件UDB-TX22.4
TO_CHAR Converts a value to a string 增强
TO_DATE Converts a string to a date in accordance with the specified format 增强
TO_MULTI_BYTE Converts a single-byte string to a multibyte string 新增
TO_NUMBER Converts a value to a number in accordance with the specified format 增强
TO_SINGLE_BYTE Converts a multibyte string to a single-byte string 新增

条件表达式函数

函数名称 说明 对比无插件UDB-TX22.4
DECODE Compares values, and if they match, returns a corresponding value 增强
GREATEST Returns the greatest of the list of one or more expressions 增强
LEAST Returns the least of the list of one or more expressions 增强
LNNVL Evaluates if a value is false or unknown 新增
NANVL Returns a substitute value when a value is not a number (NaN) 新增
NVL Returns a substitute value when a value is NULL 新增
NVL2 Returns a substitute value based on whether a value is NULL or not NULL 新增

聚合函数

函数名称 说明 对比无插件UDB-TX22.4
LISTAGG Returns a concatenated, delimited list of string values 新增
MEDIAN Calculates the median of a set of values 新增
  • 返回内部信息的函数

函数名称 说明 对比无插件UDB-TX22.4
DUMP Returns internal information of a value 新增

SQL 运算符

名称 说明 对比无插件UDB-TX22.4
Datetime operator Datetime operator for the DATE type -

Packages 包

名称 说明 对比无插件UDB-TX22.4
DBMS_ALERT Sends alerts to multiple sessions -
DBMS_ASSERT Validates the properties of an input value -
DBMS_OUTPUT Sends messages to clients -
DBMS_PIPE Creates a pipe for inter-session communication -
DBMS_RANDOM Generates random numbers -
DBMS_UTILITY Provides various utilities -
UTL_FILE Enables text file operations -

unvdbGIS

unvdbgis 是一组基于PostGIS定制的适用于UDB-TX 数据库的GIS扩展。每个扩展提供的技术细节,可联机查询。 类似命令如下:

unvdb=# \dx+ udbgis

unvdbgis

unvdbgis的基本核心功能,仅支持地理图形(矢量要素),在其他Extension前启用。这个是基础插件,必须要安装的。

unvdbgis安装

联系技术支持获取插件包,
复制到数据库安装目录,
修改插件文件权限.
运行以下sql语句启用插件.

ud_sql
\c template1; --在template1模板上启用插件,后续创建的数据库默认启用插件.也可以进入目标数据库按需启用插件.
create extension fuzzystrmatch; 
create extension udbgis; 
create extension udbgis_tiger_geocoder; 
create extension udbgis_raster; 
create extension udbgis_topology; 
create extension udbgis_sfcgal; 
create extension address_standardizer; 
create extension address_standardizer_data_us; 
create extension pgrouting CASCADE; 
create extension pointcloud; 
create extension pointcloud_udbgis; 
create extension ogr_fdw; 
create extension udb_trajectory;

unvdbgis_raster

对栅格数据的支持。安装过unvdbgis后可直接启用该扩展,默认不启用。

unvdbgis_topology

拓扑功能的支持。安装过unvdbgis后可直接启用该扩展,默认不启用。

unvdbgis_tiger_geocoder

TIGER指的是(拓扑集成地理编码和参考),这个是美国人口普查局的GIS数据,提供了美国全国的行政区划、交通道路、水系等空间数据。这个Extension提供了TIGER数据的地理编码支持,需要注意的是这个Extension启用前,需要先启用fuzzystrmatch(字符串模糊查询)Extension(至少需要启用这个),以及可选的address_standardizer(TIGER数据地址规则化)、address_standardizer_data_us(地址规则化示例数据集)Extension。

(先安装了fuzzystrmatch后,才可以启用unvdbgis_tiger_geocoder)

unvdbgis_sfcgal

这个Extension主要是集成了CGAL(Computational Geometry Algorithms Library,计算几何算法库),来进行三维空间数据的空间运算,例如ST_3DDifference、ST_3DUnion 等,可见是通常空间运算在三维空间上的拓展。可产生各种3d模型,进而利用产生的数据进行3d渲染。

ud_trashcan-闪回回收站

简介

ud_trashcan是闪回回收站功能。在使用udbtx数据库时,可能会意外删除/truncate一些数据或数据库对象,可能是由于误操作、意外的数据丢失、或者其他不可预知的情况。为了应对这类情况,udbtx引入了闪回回收站,闪回回收站用于将删除/truncate的表临时转移到回收站,闪回回收站功能为用户提供一种误删表/truncate表后还原表的一种手段。

前提要求

  • 闪回回收站是默认关闭的,需要手动开启,参数名称:udb_flashback.db_recyclebin,参数为bool类型。 表回收站功能开关。取值范围如下: on:打开表回收站功能开关。 off(默认值):关闭表回收站功能开关 全局设置:在unvdbsvr.conf中设置udb_flashback.db_recyclebin = ‘on’;此种情况需要重启数据库使其生效。 会话设置:在会话中设置,set udb_flashback.db_recyclebin to on;

注意事项

  • 当Trash schema中存在同名的表时, 也会报错,所以尽量不要使用与回收站同名的表。

  • drop table的用户需要创建schema的权限, 以及写Trash schema的权限,如果没有创建schema的权限会报错。

安装

udb-tx-v24.2.8以后的版本,已启用 ud_trashcan, 直接使用即可。 udb-tx-v24.2.8及以前的版本,按以下步骤安装启用。

【附件】ud_trashcan.zip 如下载失败请联系技术支持获取。

启用

  • ud_trashcan.so 放到安装目录的lib/ 下

  • chown -R udb.udb 安装目录/lib/ud_trashcan.so

配置

  • 配置文件unvdbsvr.conf里面设置参数shared_preload_libraries = ‘ud_trashcan.so’

  • 重新启动数据库服务。

验证安装

unvdb=#  show udb_flashback.db_recyclebin;
udb_flashback.db_recyclebin 
-----------------------------
 off
(1 row)

使用示例

闪回回收站开关功能

-打开回收站开关。

unvdb=# show udb_flashback.db_recyclebin; 
 udb_flashback.db_recyclebin 
-----------------------------
 off
(1 row)

unvdb=# set udb_flashback.db_recyclebin to on;
SET

unvdb=# show udb_flashback.db_recyclebin;     
 udb_flashback.db_recyclebin 
-----------------------------
 on
(1 row)

闪回drop表数据

-创建表test_drop_t,并将该表删除,该表就会被放置到回收站当中,查询的时候发现test_drop_t已经被删除,但是我们可以从回收站中查询到删除之前test_drop_t的数据。

unvdb=# create table test_drop_t(no int,name text);
CREATE TABLE

unvdb=# insert into test_drop_t values (100,'test100'),(200,'test200'),(300,'test300');
INSERT 0 3

unvdb=# select * from test_drop_t;
 no  |  name   
-----+---------
 100 | test100
 200 | test200
 300 | test300
(3 rows)

unvdb=# drop table test_drop_t;
DROP TABLE

unvdb=# select * from "Trash".test_drop_t;
 no  |  name   
-----+---------
 100 | test100
 200 | test200
 300 | test300
(3 rows)

闪回truncate表数据

-创建表test_truncate_t,并将该表truncate,该表就会被放置到回收站当中,查询的时候发现test_truncate_t数据为空,但是我们可以从回收站中查询到truncate之前test_truncate_t的数据。

unvdb=# create table test_truncate_t(no int,name text);
CREATE TABLE

unvdb=# insert into test_truncate_t values (100,'test100'),(200,'test200'),(300,'test300');
INSERT 0 3

unvdb=# select * from test_truncate_t;
 no  |  name   
-----+---------
 100 | test100
 200 | test200
 300 | test300
(3 rows)

unvdb=# truncate table test_truncate_t;
TRUNCATE TABLE

unvdb=# select * from test_truncate_t;
 no  |  name   
----
(0 rows)

unvdb=# select * from "Trash".test_truncate_t;
 no  |  name   
-----+---------
 100 | test100
 200 | test200
 300 | test300
(3 rows)

清空回收站

-回收站需用户定期维护,避免回收站膨胀,用户可以通过drop…CASCADE操作对回收站进行维护,分为删除回收站中一个指定表和清空回收站。

-清空回收站,回收站中的表都将被清除。

unvdb=# SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'Trash'; 
    tablename    
-----------------
 test_truncate_t
 test_drop_t
(2 rows)

unvdb=# drop schema "Trash" CASCADE;
NOTICE:  drop cascades to 2 other objects
DETAIL:  drop cascades to table "Trash".test_truncate_t
drop cascades to table "Trash".test_drop_t
DROP SCHEMA

unvdb=# SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'Trash'; 
 tablename 
-----------
(0 rows)

-清空回收站中的表test_drop_t。

unvdb=# SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'Trash'; 
  tablename  
-------------
 test_drop_t
(1 row)

unvdb=# drop table "Trash".test_drop_t;
DROP TABLE

unvdb=# SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'Trash'; 
 tablename 
-----------
(0 rows)

关闭回收站

-关掉闪回回收站之后,删除/truncate表时,表将不会进入回收站。

unvdb=# show udb_flashback.db_recyclebin;
 udb_flashback.db_recyclebin 
-----------------------------
 on
(1 row)

unvdb=# set udb_flashback.db_recyclebin to off;
SET

unvdb=# show udb_flashback.db_recyclebin;                                      
 udb_flashback.db_recyclebin 
-----------------------------
 off
(1 row)

unvdb=# create table test_drop_t(no int,name text);
CREATE TABLE

unvdb=# insert into test_drop_t values (100,'test100'),(200,'test200'),(300,'test300');
INSERT 0 3

unvdb=# select * from test_drop_t;
 no  |  name   
-----+---------
 100 | test100
 200 | test200
 300 | test300
(3 rows)

unvdb=# drop table test_drop_t;
DROP TABLE

unvdb=# SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = 'Trash'; 
 tablename 
-----------
(0 rows)

ud_dirtyread-查看脏数据

简介

ud_dirtyread 是脏读插件,用于读取那些已经删除但未被清理的数据。当误操作delete数据时,可以使用它从脏数据中恢复出来。 不支持 DDL 操作和 truncate 操作的恢复。

前提要求

  • 未手动或自动执行 vacuum 清理操作

查询上一次 vacuum 执行时间,如已经执行了清理,则数据无法恢复。

select relname,last_vacuum, last_autovacuum, last_analyze, vacuum_count, autovacuum_count,  last_autoanalyze from pg_stat_user_tables;

注意事项

  • 不建议在生产环境直接执行本节的所有操作。

  • 建议将当前所有文件复制到一个独立的机器进行恢复操作,避免对当前环境造成更大的数据损坏。

  • 在将结果恢复到生产环境时,建议先备份生产环境当前的所有数据。

安装

udb-tx-v22.4.22及以后的版本,已启用 ud_dirtyread, 直接使用即可。 udb-tx-v22.4.22及以前的版本,按以下步骤安装启用。

【附件】ud_dirtyread.zip 如下载失败请联系技术支持获取。

启用

  • ud_dirtyread.so 放到安装目录的lib/ 下

  • ud_dirtyread.control 和 ud_dirtyread–*.sql 放到安装目录的share/extension/ 下

  • chown -R udb.udb 安装目录/lib/ud_dirtyread.so

  • chown -R udb.udb 安装目录/share/extension/ud_dirtyread*

验证安装

waltest=#  CREATE EXTENSION ud_dirtyread;
CREATE EXTENSION

使用示例

创建测试数据

waltest=# select * from tb1;
 id | name 
----+------
  1 | a
  2 | b
(2 rows)
waltest=# \dt tb1;
       List of relations
 Schema | Name | Type  | Owner 
--------+------+-------+-------
 public | tb1  | table | unvdb
(1 row)
waltest=# \d tb1;
                        Table "public.tb1"
 Column |          Type          | Collation | Nullable | Default 
--------+------------------------+-----------+----------+---------
 id     | integer                |           | not null | 
 name   | character varying(255) |           |          | 
Indexes:
    "tb1_pkey" PRIMARY KEY, btree (id)

查看当前数据元组信息

waltest=# select xmin,xmax,ctid,* from tb1;     
 xmin | xmax | ctid  | id | name 
------+------+-------+----+------
 1650 |    0 | (0,1) |  1 | a
 1651 |    0 | (0,2) |  2 | b
(2 rows)

查看是否为脏数据,dead列为f,表示非死数据

waltest=# select * from ud_dirtyread('tb1') as foo(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,id int,name varchar(255)); 
 tableoid | ctid  | xmin | xmax | cmin | cmax | dead | id | name 
----------+-------+------+------+------+------+------+----+------
    66027 | (0,1) | 1650 |    0 |    0 |    0 | f    |  1 | a
    66027 | (0,2) | 1651 |    0 |    0 |    0 | f    |  2 | b
(2 rows)

删除数据

waltest=# delete from tb1 where id=1;
DELETE 1
waltest=# select * from tb1;
 id | name 
----+------
  2 | b
(1 row)

修改数据

waltest=# update tb1 set name='bb' where id=2;
UPDATE 1

查看已删除未清理的脏数据

waltest=# select * from ud_dirtyread('tb1') as foo(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,id int,name varchar(255));
 tableoid | ctid  | xmin | xmax | cmin | cmax | dead | id | name 
----------+-------+------+------+------+------+------+----+------
    66027 | (0,1) | 1650 | 1652 |    0 |    0 | t    |  1 | a
    66027 | (0,2) | 1651 | 1653 |    0 |    0 | t    |  2 | b
    66027 | (0,3) | 1653 |    0 |    0 |    0 | f    |  2 | bb
(3 rows)

会发现id=1的那条数据状态 dead=t 更新的id=2那条数据的事务已经由1651变为1653,原来的状态变为了删除,值已经变更为bb

删除列

waltest=# alter table tb1 drop column name;
ALTER TABLE
waltest=# select * from tb1;
 id 
----
  2
(1 row)

查看已删除列的脏数据,此时要用 dropped_n 来代替

waltest=# select * from ud_dirtyread('tb1') as foo(tableoid oid, ctid tid, xmin xid, xmax xid, cmin cid, cmax cid, dead boolean,id int,dropped_2 varchar(255)); 
 tableoid | ctid  | xmin | xmax | cmin | cmax | dead | id | dropped_2 
----------+-------+------+------+------+------+------+----+-----------
    66027 | (0,1) | 1650 | 1652 |    0 |    0 | t    |  1 | a
    66027 | (0,2) | 1651 | 1653 |    0 |    0 | t    |  2 | b
    66027 | (0,3) | 1653 |    0 |    0 |    0 | f    |  2 | bb
(3 rows)

ud_walminer-从wal日志中提取sql实现数据修复

简介

ud_walminer 可以解析 wal 日志,尽可能多的获取有用信息,进一步生成undo语句,实现恢复删除或丢失的数据。 功能如下:

  • 从wal日志中提取DML和少部分DDL,并生成对应的回滚语句;

  • 磁盘部分损坏或执行了TRUNCATE等清除操作时,可以使用ud_walminer尝试从wal中提取数据,尽最大可能找回数据。不保证一定能恢复成功。

前提要求

  • 表结构需要尽可能完整,例如字段名称,字段类型等

  • wal日志文件越多越好

注意事项

  • 不建议在生产环境直接执行本节的所有操作。

  • 建议将当前所有文件复制到一个独立的机器进行恢复操作,避免对当前环境造成更大的数据损坏。

  • 在将结果恢复到生产环境时,建议先备份生产环境当前的所有数据。

  • 在一次解析开始时会首先创建或truncate walminer_contents表,当得到想要的数据时建议先导出备份它们再执行第二次解析。

安装/启用

udb-tx-v22.4.22及以后的版本,已启用 ud_walminer, 直接使用即可。 udb-tx-v22.4.22及以前的版本,按以下步骤安装启用。

安装

【附件】ud_walminer.zip 如下载失败请联系技术支持获取。

启用

  • walminer.so 放到安装目录的lib/ 下

  • walminer.control和walminer–3.0.sql 放到安装目录的share/extension/ 下

  • chown -R udb.udb 安装目录/lib/walminer.so

  • chown -R udb.udb 安装目录/share/extension/walminer.*

验证安装

[udb@0a2593d70d5b udb]$ ud_sql 
ud_sql (22.4)
Type "help" for help.
unvdb=# create extension walminer;
-- 创建扩展插件
CREATE EXTENSION
unvdb=# 

使用说明

基础操作

create extension walminer; -- 创建扩展
select walminer_wal_add('/data/udb/ud_wal'); --添加要解析的wal日志目录或单个文件名
select walminer_wal_remove('/opt/test/wal'); --移除wal日志目录或单个文件名
select walminer_wal_list(); --列出wal文件

解析操作

#普通解析
select walminer_all(); --解析已添加的全部wal日志
select walminer_by_time(starttime, endtime); --在add的wal日志中查找对应时间范围的wal记录
select walminer_by_lsn(startlsn, endlsn); --在add的wal日志中查找对应lsn范围的wal记录
select walminer_by_xid(xid); --在add的wal日志中查找对应xid的wal记录
#精确解析
select walminer_by_time(starttime, endtime,'true');  --精确查找对应时间范围的wal记录
select walminer_by_lsn(startlsn, endlsn,'true');  --精确查找对应lsn范围的wal记录
select walminer_by_xid(xid,'true'); --精确查找对应xid的wal记录
#普通解析会严格匹配给定的范围,但可能没找到之前的checkpoint点,所以会出现记录不全的情况;
#精确解析会自动查找给定范围之前的checkpoint点,更完美的解析出结果。当普通解析结果不全时可以尝试精确解析。
#当本机没有数据结构时,可以加载其它机器生成的的数据结构
select walminer_build_dictionary('/tmp/store_dictionary'); --根据当前数据库结构生成数据字典
select walminer_load_dictionary('/tmp/store_dictionary'); --加载数据字典
#reloid 参数可以查找指定表,要用表的oid
select walminer_by_time(starttime, endtime,'false',reloid); --非精确模式查找对应时间范围的reloid表oid的wal记录
select walminer_by_lsn(startlsn, endlsn,'true',reloid); --在add的wal日志中查找对应lsn范围的wal记录
select walminer_by_xid(xid,'true',reloid);--在add的wal日志中查找对应xid的wal记录
#当表结构不完整时创建临时表并使用临时表映射解析。
create table tmp_avatar(i int); --创建临时表
select walminer_table_avatar(tmp_avatar, missed_relfilenode); --映射到临时表。此时的解析结果将按临时表格式输出。
select wal2sql(); --执行解析,wal文件越多,需要的时间也越多。
select * from walminer_contents; --查看解析结果
-- 表walminer_contents 
(
 sqlno int,         --本条sql在其事务内的序号
 xid bigint,        --事务ID
 topxid bigint,        --如果为子事务,这是是其父事务;否则为0
 sqlkind int,        --sql类型1->insert;2->update;3->delete(待优化项目)
 minerd bool,        --解析结果是否完整(缺失checkpoint情况下可能无法解析出正确结果)
 timestamp timestampTz, --这个SQL所在事务提交的时间
 op_text text,        --sql
 undo_text text,    --undo sql
 complete bool,        --如果为false,说明有可能这个sql所在的事务是不完整解析的
 schema text,        --目标表所在的模式
 relation text,        --目标表表名
 start_lsn pg_lsn,    --这个记录的开始LSN
 commit_lsn pg_lsn    --这个事务的提交LSN
)
select walminer_stop(); --结束分析操作,并释放内存。

实践演示

delete 操作恢复

模拟删除操作

waltest=# select * from tb1;         
 id | name 
----+------
  1 | a
  2 | b
(2 rows)
waltest=# delete from tb1;
DELETE 2
waltest=# select * from tb1;
 id | name 
----+------
(0 rows)

配置ud_walminer

waltest=# create extension walminer;--创建扩展
CREATE EXTENSION
waltest=# select walminer_wal_add('/data/udb/ud_wal');--添加wal目录
  walminer_wal_add   
---------------------
 24 file add success
(1 row)
waltest=# select walminer_wal_list();--列出wal文件
              walminer_wal_list              
---------------------------------------------
 (/data/udb/ud_wal/00000001000000090000001C)
 (/data/udb/ud_wal/00000001000000090000001D)
 (/data/udb/ud_wal/00000001000000090000001E)
 (/data/udb/ud_wal/00000001000000090000001F)
 (/data/udb/ud_wal/000000010000000900000020)
 (/data/udb/ud_wal/000000010000000900000021)
 (/data/udb/ud_wal/000000010000000900000022)
 (/data/udb/ud_wal/000000010000000900000023)
 (/data/udb/ud_wal/000000010000000900000024)
 (/data/udb/ud_wal/000000010000000900000025)
 (/data/udb/ud_wal/000000010000000900000026)
 (/data/udb/ud_wal/000000010000000900000027)
 (/data/udb/ud_wal/000000010000000900000028)
 (/data/udb/ud_wal/000000010000000900000029)
 (/data/udb/ud_wal/00000001000000090000002A)
 (/data/udb/ud_wal/00000001000000090000002B)
 (/data/udb/ud_wal/00000001000000090000002C)
 (/data/udb/ud_wal/00000001000000090000002D)
 (/data/udb/ud_wal/00000001000000090000002E)
 (/data/udb/ud_wal/00000001000000090000002F)
 (/data/udb/ud_wal/000000010000000900000030)
 (/data/udb/ud_wal/000000010000000900000031)
 (/data/udb/ud_wal/000000010000000900000032)
 (/data/udb/ud_wal/000000010000000900000033)
(24 rows)
waltest=# select walminer_all(); --提取wal日志
NOTICE:  Switch wal to 00000001000000090000001C on time 2023-03-27 13:58:30.446893+08
NOTICE:  Switch wal to 00000001000000090000001D on time 2023-03-27 13:58:30.447915+08
NOTICE:  Switch wal to 00000001000000090000001E on time 2023-03-27 13:58:30.44841+08
    walminer_all     
---------------------
 ud_minerwal success
(1 row)
waltest=# select * from walminer_contents; --查看提取结果
 sqlno | xid  | topxid | sqlkind | minerd |           timestamp           |              op_text              |                    undo_text                    | complete | schema | relat
ion | start_lsn  | commit_lsn 
-------+------+--------+---------+--------+-------------------------------+-----------------------------------+-------------------------------------------------+----------+--------+------
----+------------+------------
     1 | 1528 |      0 |       3 | t      | 2023-03-27 13:56:45.925757+08 | DELETE FROM public.tb1 WHERE id=1 | INSERT INTO public.tb1(id ,name) VALUES(1 ,'a') | t        | public | tb1  
    | 9/1C0058F8 | 9/1C005A10
     2 | 1528 |      0 |       3 | t      | 2023-03-27 13:56:45.925757+08 | DELETE FROM public.tb1 WHERE id=2 | INSERT INTO public.tb1(id ,name) VALUES(2 ,'b') | t        | public | tb1  
    | 9/1C0059A0 | 9/1C005A10
(2 rows)
--执行undo_text修复数据
waltest=# INSERT INTO public.tb1(id ,name) VALUES(1 ,'a');
INSERT 0 1
waltest=# INSERT INTO public.tb1(id ,name) VALUES(2 ,'b');
INSERT 0 1
waltest=# select * from tb1;--验证结果                                                                                                    
 id | name 
----+------
  1 | a
  2 | b
(2 rows)
select walminer_stop();--结束分析并释放内存。

DDL操作恢复

注意:ddl删除的列,只能恢复列信息,不能恢复列数据。

模拟删除列操作

unvdb=# \c waltest;
You are now connected to database "waltest" as user "unvdb".
waltest=# select * from tb1;
 id | name | age 
----+------+-----
  1 | a    |   1
  2 | b    |   2
(2 rows)
waltest=# ALTER TABLE "public"."tb1" DROP COLUMN "age";
ALTER TABLE
waltest=# select * from tb1;                           
 id | name 
----+------
  1 | a
  2 | b
(2 rows)

恢复配置

waltest=# CREATE EXTENSION  walminer;
CREATE EXTENSION
waltest=# select walminer_wal_add('/data/udb/ud_wal');
  walminer_wal_add   
---------------------
 11 file add success
(1 row)
waltest=# select walminer_wal_list();
              walminer_wal_list              
---------------------------------------------
 (/data/udb/ud_wal/000000010000000900000029)
 (/data/udb/ud_wal/00000001000000090000002A)
 (/data/udb/ud_wal/00000001000000090000002B)
 (/data/udb/ud_wal/00000001000000090000002C)
 (/data/udb/ud_wal/00000001000000090000002D)
 (/data/udb/ud_wal/00000001000000090000002E)
 (/data/udb/ud_wal/00000001000000090000002F)
 (/data/udb/ud_wal/000000010000000900000030)
 (/data/udb/ud_wal/000000010000000900000031)
 (/data/udb/ud_wal/000000010000000900000032)
 (/data/udb/ud_wal/000000010000000900000033)
(11 rows)
waltest=# select wal2sql_with_ddl(); --开启ddl解析
 wal2sql_with_ddl 
------------------
 t
(1 row)
waltest=# select walminer_by_time('2023-03-27 15:00', '2023-03-27 15:15','true'); --必须使用精确解析
NOTICE:  Switch wal to 000000010000000900000029 on time 2023-03-27 15:12:59.812091+08
NOTICE:  Con not find relfilenode 65692 in dictionary, ignored related records
NOTICE:  Con not find relfilenode 65693 in dictionary, ignored related records
  walminer_by_time   
---------------------
 ud_minerwal success
(1 row)
waltest=# select * from walminer_contents;--检查解析结果
 sqlno | xid  | topxid | sqlkind | minerd |           timestamp           |                     op_text                     |             undo_text             | complete |   schema   |  
 relation   | start_lsn  | commit_lsn 
-------+------+--------+---------+--------+-------------------------------+-------------------------------------------------+-----------------------------------+----------+------------+--
------------+------------+------------
     1 | 1578 |      0 |       4 | t      | 2023-03-27 15:01:03.11249+08  | TRUNCATE TABLE public.tb1                       |                                   | t        | pg_catalog | p
g_class     | 9/291A7EB8 | 9/291AA7E0
     1 | 1583 |      0 |       1 | t      | 2023-03-27 15:09:24.706606+08 | INSERT INTO public.tb1(id ,name) VALUES(1 ,'a') | DELETE FROM public.tb1 WHERE id=1 | t        | public     | t
b1          | 9/291DA7F8 | 9/291DA910
     1 | 1584 |      0 |       1 | t      | 2023-03-27 15:09:27.201411+08 | INSERT INTO public.tb1(id ,name) VALUES(2 ,'b') | DELETE FROM public.tb1 WHERE id=2 | t        | public     | t
b1          | 9/291DA948 | 9/291DA9F8
     1 | 1585 |      0 |       2 | t      | 2023-03-27 15:09:31.79967+08  | UPDATE public.tb1 SET  WHERE id=2               | UPDATE public.tb1 SET  WHERE id=2 | t        | public     | t
b1          | 9/291DA9F8 | 9/291DAA78
     1 | 1586 |      0 |       4 | t      | 2023-03-27 15:10:15.078618+08 | ALTER TABLE public.tb1 DROP COLUMN age          |                                   | t        | pg_catalog | p
g_attribute | 9/291DCB98 | 9/291E0BF0
(5 rows)

修复数据

op_text列显示执行过 ALTER TABLE public.tb1 DROP COLUMN age,使用alter add 把它添加进来即可,但此列的数据无法恢复。

异常处理

cstore-列式存储(22.X版本)

简介

cstore插件是列式存储扩展,列式存储仅从磁盘读取相关的数据,可以更快速的分析统计数据。 数据大小比普通表减少4-10倍的磁盘空间,能够更快速的将数据加载到内存处理。

优点:

  • 压缩:磁盘占用空间减少4-10倍

  • 列投影:只读取和查询相关的数据,提高IO性能

  • 跳过索引:存储行组的最小最大统计信息,并使用它们跳过不相关的行

使用限制:

  • 不支持 DELETE 删除数据

  • 不支持 UPDATE 更新表

  • 不支持 INSERT INTO 单行数据,需多行批量插入。因为插入操作时会flush,如果插入一行也会占用一个条带的磁盘空间,会导致性能下降的严重的磁盘浪费。

使用

CREATE EXTENSION cstore_fdw; -- 创建扩展
CREATE SERVER cstore_server FOREIGN DATA WRAPPER cstore_fdw; -- 创建server指定外部数据
CREATE FOREIGN TABLE t1 -- 创建 FOREIGN (
    customer_id TEXT,
    review_date DATE,
    review_rating INTEGER,
    review_votes INTEGER,
    review_helpful_votes INTEGER,
    product_id CHAR(10),
    product_title TEXT,
    product_sales_rank BIGINT,
    product_group TEXT,
    product_category TEXT,
    product_subcategory TEXT,
    similar_product_ids CHAR(10)[]
) SERVER cstore_server -- 指定server
OPTIONS(filename '/data/udb/cstore/cstb1.cstore',compression 'pglz'); -- 其它选项
\COPY t1 FROM '/data/udb/file/data.csv' WITH CSV; --导入数据

OPTIONS 参数

  • filename(可选):表数据存储位置目录。 默认值为 $UDBDATA/cstore_fdw

  • compression压缩(可选):用于压缩价值流的压缩。 默认值为 none,不压缩;可选值 pglz

  • stripe_row_count(可选):每个条带的行数。 默认值为 150000。减少它会减少用于加载数据和查询的内存量,但也会降低性能。

  • block_row_count(可选):每个列块的行数。 默认值为 10000。cstore 以块粒度压缩、创建,跳过索引并从磁盘读取。增加此值有助于压缩并减少从磁盘读取的结果。但是,较高的值也会降低跳过不相关行块的可能性。

空间对比

相同数据量下,cstore 列式存储占用 磁盘空间 比普通表 减少4倍左右。

普通表大小

du -sh  /data/udb/udb22.4.21-1/data/udb/base/66354/
521M    /data/udb/udb22.4.21-1/data/udb/base/66354/
test=# SELECT pg_size_pretty(pg_table_size('t1'));
 pg_size_pretty 
----------------
 412 MB
(1 row)

列式存储表大小

du -sh  /data/udb/udb22.4.21-1/data/udb/cstore
100M    /data/udb/udb22.4.21-1/data/udb/cstore
cstore=# SELECT pg_size_pretty(cstore_table_size('t1'));
 pg_size_pretty 
----------------
 100 MB
(1 row)

查询对比

相同数据量下,cstore 列式存储查询 比普通表 性能提升 15倍 左右。

test=# select count(*) from t1 where review_date ='2023-04-06';
 count 
-------
  4024
(1 row)
Time: 59.165 ms
test=# \c cstore
You are now connected to database "cstore" as user "unvdb".
cstore=# select count(*) from t1 where review_date ='2023-04-06';
 count 
-------
  4024
(1 row)
Time: 4.758 ms

columnar-列式存储 (24.x)

使用

创建扩展以及示例表

CREATE EXTENSION "columnar";

CREATE TABLE columnar_table (
    id BIGINT,
    name TEXT,
    age INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) USING columnar;

可以在数据库的命令行界面使用命令查看当前表是否为列存表

\d+ columnar_table 
                                                       Table "public.columnar_table"
   Column   |            Type             | Collation | Nullable |      Default      | Storage  | Compression | Stats target | Description 
------------+-----------------------------+-----------+----------+-------------------+----------+-------------+--------------+-------------
 id         | bigint                      |           |          |                   | plain    |             |              | 
 name       | text                        |           |          |                   | extended |             |              | 
 age        | integer                     |           |          |                   | plain    |             |              | 
 created_at | timestamp without time zone |           |          | CURRENT_TIMESTAMP | plain    |             |              | 
Access method: columnar

使用数据库软件将列存表迁移到其他库中(因其他库没有添加列存扩展所以自动转换为行存),然后查询。 可以看到同样的结构同样的数据,其中占用的空间是不同的。

radius=# SELECT 
    (SELECT COUNT(*) FROM columnar_table) AS row_count,
    pg_size_pretty(pg_total_relation_size('columnar_table')) AS total_size;
 row_count | total_size 
-----------+------------
     10000 | 1984 kB
(1 row)

unvdb=# SELECT 
    (SELECT COUNT(*) FROM columnar_table) AS row_count,
    pg_size_pretty(pg_total_relation_size('columnar_table')) AS total_size;
 row_count | total_size 
-----------+------------
     10000 | 29 MB
(1 row)

限制

• 不支持逻辑复制 • 不支持ON CONFLICT子句 • 在某些情况下,索引可能会导致查询变慢,大部分情况下索引不是必须的 • 不支持BRIN索引

ud_similarity

介绍

ud_similarity是用于支持unvdb上的相似性查询的扩展。从某种意义上说,该实现紧密集成在 RDBMS 中,因为它定义了运算符<>,因此您可以使用 ~~~ 和 !(这些运算符中的任何一个都表示相似性函数)。

ud_similarity有三个主要组成部分:

  • 函数:实现文献中可用的相似性算法的一组函数。这些函数可以用作 UDF,并且将成为实现相似性运算符的基础;

  • 运算符:在相似性函数顶部定义的一组运算符。他们使用相似性函数来获取相似性阈值,并将其值与用户定义的阈值进行比较,以确定它是否匹配;

  • 会话变量:存储相似性函数参数的一组变量。这些变量可以在运行时定义。

安装和使用

在正式发布的unvdb中已包含ud_similarity,可直接使用:

unvdb=# CREATE EXTENSION ud_similarity;
CREATE EXTENSION
unvdb=#

如果不能创建扩展,可联系技术支持获取ud_similarity.zip:

以下为安装步骤:

$ unzip unvdb-tx-22.4.48-linux-x86_64-patch-ud_similarity.zip
$ cp unvdb-tx-22.4.48-linux-x86_64-patch-ud_similarity/lib/ud_similarity.so unvdb-tx-22.4.40-linux-x86_64/lib/
$ cp unvdb-tx-22.4.48-linux-x86_64-patch-ud_similarity/share/extension/* unvdb-tx-22.4.40-linux-x86_64/share/extension/    
$ cp unvdb-tx-22.4.48-linux-x86_64-patch-ud_similarity/share/extension/ud_similarity.conf unvdb-data/

# 修改unvdb-data/unvdbsvr.conf文件,添加如下内容:

include 'ud_similarity.conf'

# 重启unvdb服务:
$ unvdb-data/restart.sh

# 创建扩展:    
unvdb=# CREATE EXTENSION ud_similarity;
CREATE EXTENSION
unvdb=#

函数和运算符

此扩展支持一组相似性算法,每种算法都适用于特定域。

提供的算法如下:

  • L1距离(也被称为街区距离或曼哈顿距离)

  • 余弦距离(Cosine Distance)

  • Dice系数(Dice Coefficient)

  • 欧几里得距离(Euclidean Distance)

  • 汉明距离(Hamming Distance)

  • Jaccard系数(Jaccard Coefficient)

  • Jaro距离(Jaro Distance)

  • Jaro-Winkler距离(Jaro-Winkler Distance)

  • Levenshtein距离(Levenshtein Distance),也被称为编辑距离(Edit Distance)

  • 匹配系数(Matching Coefficient)

  • Monge-Elkan系数(Monge-Elkan Coefficient)

  • Needleman-Wunsch系数(Needleman-Wunsch Coefficient)

  • 重叠系数(Overlap Coefficient)

  • Q-gram距离(Q-Gram Distance)

  • Smith-Waterman系数(Smith-Waterman Coefficient)

  • Smith-Waterman-Gotoh系数(Smith-Waterman-Gotoh Coefficient)

  • Soundex距离(Soundex Distance)

算法 函数 操作符 使用索引? 参数
L1距离 block(text, text) returns float8 ~++ yes ud_similarity.block_tokenizer (enum)
ud_similarity.block_threshold (float8)
ud_similarity.block_is_normalized (bool)
余弦距离 cosine(text, text) returns float8 ~## yes ud_similarity.cosine_tokenizer (enum)
ud_similarity.cosine_threshold (float8)
ud_similarity.cosine_is_normalized (bool)
Dice系数 dice(text, text) returns float8 \~-\~ yes ud_similarity.dice_tokenizer (enum)
ud_similarity.dice_threshold (float8)
ud_similarity.dice_is_normalized (bool)
欧几里得距离 euclidean(text, text) returns float8 ~!! yes ud_similarity.euclidean_tokenizer (enum)
ud_similarity.euclidean_threshold (float8)
ud_similarity.euclidean_is_normalized (bool)
汉明距离 hamming(bit varying, bit varying) returns float8
hamming_text(text, text) returns float8
\~@\~ no ud_similarity.hamming_threshold (float8)
ud_similarity.hamming_is_normalized (bool)
Jaccard系数 jaccard(text, text) returns float8 ~?? yes ud_similarity.jaccard_tokenizer (enum)
ud_similarity.jaccard_threshold (float8)
ud_similarity.jaccard_is_normalized (bool)
Jaro距离 jaro(text, text) returns float8 ~%% no ud_similarity.jaro_threshold (float8)
ud_similarity.jaro_is_normalized (bool)
Jaro-Winkler距离 jarowinkler(text, text) returns float8 ~@@ no ud_similarity.jarowinkler_threshold (float8)
ud_similarity.jarowinkler_is_normalized (bool)
Levenshtein距离 lev(text, text) returns float8 ~== no ud_similarity.levenshtein_threshold (float8)
ud_similarity.levenshtein_is_normalized (bool)
匹配系数 matchingcoefficient(text, text) returns float8 ~^^ yes ud_similarity.matching_tokenizer (enum)
ud_similarity.matching_threshold (float8)
ud_similarity.matching_is_normalized (bool)
Monge-Elkan系数 mongeelkan(text, text) returns float8 ~|| no ud_similarity.mongeelkan_tokenizer (enum)
ud_similarity.mongeelkan_threshold (float8)
ud_similarity.mongeelkan_is_normalized (bool)
Needleman-Wunsch系数 needlemanwunsch(text, text) returns float8 \~#\~ no ud_similarity.nw_threshold (float8)
ud_similarity.nw_is_normalized (bool)
重叠系数 overlapcoefficient(text, text) returns float8 ~** yes ud_similarity.overlap_tokenizer (enum)
ud_similarity.overlap_threshold (float8)
ud_similarity.overlap_is_normalized (bool)
Q-gram距离 qgram(text, text) returns float8 ~~~ yes ud_similarity.qgram_threshold (float8)
ud_similarity.qgram_is_normalized (bool)
Smith-Waterman系数 smithwaterman(text, text) returns float8 \~=\~ no ud_similarity.sw_threshold (float8)
ud_similarity.sw_is_normalized (bool)
Smith-Waterman-Gotoh系数 smithwatermangotoh(text, text) returns float8 \~!\~ no ud_similarity.swg_threshold (float8)
ud_similarity.swg_is_normalized (bool)
Soundex距离 soundex(text, text) returns float8 \~*\~ no

这几个参数控制ud_similarity函数和运算符的行为。我没有详细解释每个参数,因为它们可以分为三类:tokenizer、 threshold 和normalized。

  • Tokenizer:控制字符串的标记化方式。有效值为 alnum、gram、word 和 camelcase。所有标记都是小写的(此选项可以在编译时设置;)。默认值为 alnum;

    • alnum:分隔符是任何非字母数字字符。这意味着标记中只接受标准 C 语言环境中的字母字符和数字 (0-9)。例如,字符串“Euler_Taveira_de_Oliveira 22/02/2011”被标记为“Euler”、“Taveira”、“de”、“Oliveira”、“22”、“02”、“2011”;

    • gram:n-gram 是长度为 n 的子序列。从字符串中提取 n 个 gram 可以通过使用 sliding-by-one 技术来完成,即将长度为 n 的窗口从字符串中滑动一个字符。例如,字符串“euler taveira”(使用 n = 3)被标记为 “eul”、“ule”、“ler”、“er ”、“r t”、“ta”、“tav”、“ave”、“vei”、“eir” 和 “ira”。有一些作者认为 n-gram 将 “ e”、“eu”、“ra ” 和 “a” 添加到标记集,称为完整的 n-gram(此选项可以在编译时设置);

    • word:分隔符是空格字符(空格、换向表单、换行符、回车符、水平制表符和垂直制表符)。例如,字符串“Euler Taveira de Oliveira 22/02/2011”被标记为“Euler”、“Taveira”、“de”、“Oliveira”和“22/02/2011”;

    • camelcase:分隔符是大写字符,但它们也作为第一个标记字符包含在内。例如,字符串“EulerTaveira de Oliveira”被标记为“Euler”、“Taveira de ”和“Oliveira”。

  • threshold:控制结果集的灵活性。运算符使用这些值来匹配字符串。对于每对字符串,如果计算值(使用相应的相似度函数)大于或等于阈值,则存在匹配项。取值范围为 0.0 到 1.0。默认值为 0.7;

  • 和normalized:控制是否归一化相似系数/距离(介于 0.0 和 1.0 之间)。运算符会自动使用规范化值来匹配字符串,也就是说,此参数仅在使用相似性函数时才有意义。默认值为 true。

示例

在运行时设置参数:

unvdb=# show ud_similarity.block_threshold;
ud_similarity.block_threshold
-------------------------------
0.7
(1 row)

unvdb=# set ud_similarity.block_threshold to 0.5;
SET
unvdb=# show ud_similarity.block_threshold;
ud_similarity.block_threshold
-------------------------------
0.5
(1 row)

unvdb=# set ud_similarity.block_tokenizer to camelcase;
SET
unvdb=# set ud_similarity.block_is_normalized to false;
SET

以简单表格为例:

unvdb=# create table foo (a text);
CREATE TABLE
unvdb=# insert into foo values('Euler'),('Oiler'),('Euler Taveira de Oliveira'),('Maria Taveira dos Santos'),('Carlos Santos Silva');
INSERT 0 5
unvdb=#
unvdb=# create table bar (b text);
CREATE TABLE
unvdb=# insert into bar values('Euler T. de Oliveira'),('Euller'),('Oliveira, Euler Taveira'),('Sr. Oliveira');
INSERT 0 4

示例1:使用相似函数cosine、jaro 和 euclidean。

unvdb=# select a, b, cosine(a,b), jaro(a, b), euclidean(a, b) from foo, bar;
            a             |            b            |       cosine        |        jaro        |      euclidean
--------------------------+-------------------------+---------------------+--------------------+---------------------
Euler                     | Euler T. de Oliveira    |                 0.5 |               0.75 |  0.5799159747915971
Euler                     | Euller                  |                   0 | 0.9444444444444444 |                   0
Euler                     | Oliveira, Euler Taveira |  0.5773502691896258 | 0.6057971014492753 |   0.552786404500042
Euler                     | Sr. Oliveira            |                   0 | 0.5055555555555555 |  0.2254033307585167
Oiler                     | Euler T. de Oliveira    |                   0 | 0.4722222222222222 | 0.45767385545335953
Oiler                     | Euller                  |                   0 |                0.7 |                   0
Oiler                     | Oliveira, Euler Taveira |                   0 |  0.672463768115942 |  0.3675444679663242
Oiler                     | Sr. Oliveira            |                   0 | 0.6722222222222223 |  0.2254033307585167
Euler Taveira de Oliveira | Euler T. de Oliveira    |                0.75 | 0.7980701754385964 |                0.75
Euler Taveira de Oliveira | Euller                  |                   0 | 0.6777777777777777 | 0.45767385545335953
Euler Taveira de Oliveira | Oliveira, Euler Taveira |  0.8660254037844387 | 0.7731884057971014 |                 0.8
Euler Taveira de Oliveira | Sr. Oliveira            | 0.35355339059327373 | 0.5922222222222222 |  0.5527864045000421
Maria Taveira dos Santos  | Euler T. de Oliveira    |                   0 | 0.6023504273504273 |                 0.5
Maria Taveira dos Santos  | Euller                  |                   0 | 0.3055555555555556 | 0.45767385545335953
Maria Taveira dos Santos  | Oliveira, Euler Taveira |  0.2886751345948129 | 0.5350241545893719 |   0.552786404500042
Maria Taveira dos Santos  | Sr. Oliveira            |                   0 | 0.6342592592592593 |   0.452277442494834
Carlos Santos Silva       | Euler T. de Oliveira    |                   0 | 0.5421052631578946 | 0.47084973778708183
Carlos Santos Silva       | Euller                  |                   0 | 0.3128654970760234 |  0.3675444679663242
Carlos Santos Silva       | Oliveira, Euler Taveira |                   0 | 0.6066615814899567 |  0.4226497308103742
Carlos Santos Silva       | Sr. Oliveira            |                   0 | 0.5077276524644945 | 0.37982632705395764
(20 rows)

示例 2:使用运算符 levenshtein (~==) 并在运行时更改其阈值。

unvdb=# show ud_similarity.levenshtein_threshold;
ud_similarity.levenshtein_threshold
-------------------------------------
0.7
(1 row)

unvdb=# select a, b, lev(a,b) from foo, bar where a ~== b;
            a             |          b           |        lev
---------------------------+----------------------+--------------------
Euler                     | Euller               | 0.8333333333333334
Euler Taveira de Oliveira | Euler T. de Oliveira |               0.76
(2 rows)

unvdb=# set ud_similarity.levenshtein_threshold to 0.5;
SET
unvdb=# select a, b, lev(a,b) from foo, bar where a ~== b;
            a             |          b           |        lev
---------------------------+----------------------+--------------------
Euler                     | Euller               | 0.8333333333333334
Oiler                     | Euller               |                0.5
Euler Taveira de Oliveira | Euler T. de Oliveira |               0.76
(3 rows)

示例 3:使用运算符 qgram (~~~) 并在运行时更改其阈值。

unvdb=# show ud_similarity.qgram_threshold;
ud_similarity.qgram_threshold
-------------------------------
0.7
(1 row)

unvdb=# select a, b,qgram(a, b) from foo, bar where a ~~~ b;
            a             |            b            |       qgram
--------------------------+-------------------------+--------------------
Euler                     | Euller                  |                0.8
Euler Taveira de Oliveira | Euler T. de Oliveira    | 0.7755102040816326
Euler Taveira de Oliveira | Oliveira, Euler Taveira | 0.8076923076923077
(3 rows)

unvdb=# set ud_similarity.qgram_threshold to 0.35;
SET
unvdb=# select a, b,qgram(a, b) from foo, bar where a ~~~ b;
            a             |            b            |        qgram
--------------------------+-------------------------+---------------------
Euler                     | Euler T. de Oliveira    | 0.41379310344827586
Euler                     | Euller                  |                 0.8
Oiler                     | Euller                  |                 0.4
Euler Taveira de Oliveira | Euler T. de Oliveira    |  0.7755102040816326
Euler Taveira de Oliveira | Oliveira, Euler Taveira |  0.8076923076923077
Euler Taveira de Oliveira | Sr. Oliveira            | 0.43902439024390244
(6 rows)

示例 4:使用一组使用相同阈值 (0.7) 的运算符来说明某些相似性函数已适用于某些数据域。

unvdb=# select * from bar where b ~@@ 'euler'; -- jaro-winkler operator
          b
----------------------
Euler T. de Oliveira
Euller
(2 rows)

unvdb=# select * from bar where b ~~~ 'euler'; -- qgram operator
b
---
(0 rows)

unvdb=# select * from bar where b ~== 'euler'; -- levenshtein operator
b
--------
Euller
(1 row)

unvdb=# select * from bar where b ~## 'euler'; -- cosine operator
b
---
(0 rows)

odbc_fdw

简介

此 unvdb 扩展为使用 Open Database Connectivity(ODBC)的远程数据库。

Linux平台安装

安装unixODBC

sudo yum install unixODBC-devel

配置unixODBC

查看unixODBC配置
[test@localhost ~]$ odbcinst -j 
unixODBC 2.3.1
DRIVERS............: /etc/odbcinst.ini
SYSTEM DATA SOURCES: /etc/odbc.ini
FILE DATA SOURCES..: /etc/ODBCDataSources
USER DATA SOURCES..: /home/test/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
[test@localhost ~]$
配置 UNVDB ODBC 驱动管理器

sudo vi /etc/odbcinst.ini 添加如下内容

Driver 路径修改为安装包实际路径

[UNVDB]
Description     = ODBC for UNDB-TX
Driver          = /home/test/unvdb-tx-24.2.11-linux-aarch64/Interface/ODBC/unvdbodbcw.so  
Setup           = /usr/lib64/libodbcpsqlS.so
Driver64        = /home/test/unvdb-tx-24.2.11-linux-aarch64/Interface/ODBC/unvdbodbcw.so
Setup64         = /usr/lib64/libodbcpsqlS.so
FileUsage       = 1

配置数据源

vi ~/.odbc.ini 添加如下内容

[REMOTE_UNVDB]
Driver = UNVDB
Description = Test on UNVDB
#以下信息根据实际修改
Database = unvdb
Servername = 127.0.0.1
UserName = unvdb
Port = 5678

测试示例

unvdb=# CREATE EXTENSION odbc_fdw;
CREATE EXTENSION
unvdb=# CREATE SERVER loopback FOREIGN DATA WRAPPER odbc_fdw OPTIONS (dsn 'REMOTE_UNVDB');
CREATE SERVER
#修改为实际用户名和密码
unvdb=# CREATE USER MAPPING FOR CURRENT_USER SERVER loopback OPTIONS (odbc_UID 'unvdb', odbc_PWD 'XXX');
CREATE USER MAPPING
unvdb=# CREATE TABLE test (c1 int NOT NULL, c2 text);
CREATE TABLE
unvdb=# CREATE FOREIGN TABLE remote_test (
 c1 int NOT NULL, c2 text
) SERVER loopback OPTIONS (schema 'public', table 'test');
CREATE FOREIGN TABLE
unvdb=# insert into test values(1,'test');
INSERT 0 1
unvdb=# select * from remote_test;
 c1 |  c2  
----+------
  1 | test
(1 row)


#清理
DROP FOREIGN TABLE remote_test;
drop table test;
DROP USER MAPPING FOR CURRENT_USER SERVER loopback;
DROP SERVER loopback;
DROP EXTENSION odbc_fdw;