AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-20925

0xCAFEBABE's questions

Martin Hope
0xCAFEBABE
Asked: 2022-12-01 05:46:06 +0800 CST

PostgreSQL 中表的大小计算之间的显着大小差异

  • 5

我们正在提供 PostgreSQL 作为 Oracle 的替代品,这是我们目前唯一的数据库。为了准确预测转换后数据所需的挂载点大小,我们需要找出在转换为 PostgreSQL 时从 Oracle 中使用了多少空间。

我们有这张桌子,上面是我们的用例之一。甲骨文结构:

CREATE TABLE SAMPLETABLE
(
  REFDATE   DATE,
  ID        NUMBER(10),
  ARCVALUE  NUMBER,
  VALSTAT   NUMBER(2),
  IO        NUMBER(1),
  SOURCE    NUMBER(2),
  MODDATE   DATE                                DEFAULT sysdate
);

和 PostgreSQL 等效:

CREATE TABLE sampletable (
    refdate timestamptz NOT NULL,
    id numeric(10) NOT NULL,
    arcvalue numeric NULL,
    valstat numeric(10) NULL,
    source numeric(2) NULL,
    moddate timestamptz NULL DEFAULT clock_timestamp(),
    io numeric(1) NULL,
    CONSTRAINT sampletable_pk PRIMARY KEY (refdate, id)
);

在我们Oracle这边,对于一个具体的项目数据,4500万行的平均行长是45 bytes. 我们通过此查询计算得出:

select sum(bytes) from  DBA_EXTENTS where segment_name = 'sampletable';

除以行数(4500 万)。

查看 PostgreSQL,我们可以通过这种方式找到大小:

SELECT l.metric, l.nr AS bytes
     , CASE WHEN is_size THEN pg_size_pretty(nr) END AS bytes_pretty
     , CASE WHEN is_size THEN nr / NULLIF(x.ct, 0) END AS bytes_per_row
FROM  (
   SELECT min(tableoid)        AS tbl
        , count(*)             AS ct
        , sum(length(t::text)) AS txt_len  -- length in characters
   FROM   sampletable t                     -- provide table name *once*
   ) x
CROSS  JOIN LATERAL (
   VALUES
     (true , 'core_relation_size'               , pg_relation_size(tbl))
   , (true , 'visibility_map'                   , pg_relation_size(tbl, 'vm'))
   , (true , 'free_space_map'                   , pg_relation_size(tbl, 'fsm'))
   , (true , 'table_size_incl_toast'            , pg_table_size(tbl))
   , (true , 'indexes_size'                     , pg_indexes_size(tbl))
   , (true , 'total_size_incl_toast_and_indexes', pg_total_relation_size(tbl))
   , (true , 'live_rows_in_text_representation' , txt_len)
   , (false, '------------------------------'   , NULL)
   , (false, 'row_count'                        , ct)
   , (false, 'live_tuples'                      , pg_stat_get_live_tuples(tbl))
   , (false, 'dead_tuples'                      , pg_stat_get_dead_tuples(tbl))
   ) l(is_size, metric, nr);

由此,使用简单的数学core_relation_size/ row_count,它110 bytes在 PostgreSQL 中显示一行的大小。这是一个残酷的增长,我们试图找出数据在转换后如何变得更大。

以普通行的字节大小来看,该行似乎应该小得多:

select
refdate, id,
    pg_column_size(refdate) s_refdate,
    pg_column_size(id) s_id,
    pg_column_size(arcvalue) s_arcvalue,
    pg_column_size(valstat) s_valstat,
    pg_column_size(source) s_source,
    pg_column_size(moddate) s_moddate,
    pg_column_size(io) s_io,
    pg_column_size(refdate) + pg_column_size(tid) + pg_column_size(arcvalue) + pg_column_size(valstat) + pg_column_size(source) + pg_column_size(moddate) + coalesce (pg_column_size(io), 0) rowsize
from sampletable
order by rowsize desc;

这给出48 bytes了我们拥有的最长行,以字节为单位。我们现在所拥有的只是关于如何解释显着差异的想法:

  • 是否有明显的填充?
  • 没有精度的数字字段是否以某种方式使用了比必要的多得多的字节?
  • Oracle 大小计算有误吗?

有谁知道如何找出差异?

postgresql
  • 1 个回答
  • 24 Views
Martin Hope
0xCAFEBABE
Asked: 2022-03-25 23:24:57 +0800 CST

PostgreSQL-Patroni-Cluster:安装oracle_fdw,依赖问题

  • 1

对于 Oracle 到 PostgreSQL 的迁移,我们目前正在研究 ora2pg。但是,使用写入文件或直接从 Oracle 读取并写入 PostgreSQL 的性能都非常差劲。关于这方面的信息并不好,虽然我发现的一些部分表明它可能与 Oracle-Perl-Driver 有关。

在新版本的 ora2pg 中,它引入了一种使用 Foreign Data Wrapper 转换数据的新方法oracle_fdw。它是用 C 语言编写的,性能基准似乎表明性能要高得多。为此,我们想使用oracle_fdw. 我们转换的目标是使用 etcd 的具有 2 个节点和第 3 个见证节点的 Patroni 集群设置。

然而,添加oracle_fdw到 Patroni 集群一直很困难,而且到目前为止还没有成功。编译 oracle_fdw 后,尝试加载它会给出以下消息:

错误:无法加载库“/usr/lib/postgresql14/lib64/oracle_fdw.so”:libclntsh.so.19.1:无法打开共享对象文件:没有这样的文件或目录

该库存在于系统上,但位于 Oracle Instantclient ( /dbdata/oracle/instantclient_19_12) 的目录中。为了找到该库,我们认为我们需要将以下标准环境变量添加到postgresPatroni 启动的进程中:

export LD_LIBRARY_PATH=/dbdata/oracle/instantclient_19_12
export ORACLE_HOME=/dbdata/oracle/instantclient_19_12
export PATH=/dbdata/oracle/instantclient_19_12:$PATH

然而,我们将这些变量注入到由 Patroni 启动的 postgress 进程中完全没有成功。该过程使用系统用户启动postgres,如下所示:

dbserver01 root 6 (/dbdata/oracle/instantclient_19_12): ps -ef|grep postgres
root      9236  9120  0 07:56 pts/0    00:00:00 su - postgres
postgres  9238  9236  0 07:56 pts/0    00:00:00 -bash
postgres  9289  9238  0 07:56 pts/0    00:00:00 psql
postgres  9290 27443  0 07:56 ?        00:00:00 postgres: pgcluster2: postgres postgres [local] idle
root      9307  9180  0 07:58 pts/1    00:00:00 grep --color=auto postgres
postgres 27423     1  0 Mar23 ?        00:01:41 /opt/patroni/bin/python3 /usr/bin/patroni /etc/patroni/postgres.yml
postgres 27443     1  0 Mar23 ?        00:00:04 postgres -D /dbdata/pgcluster --config-file=/dbdata/pgcluster/postgresql.conf --listen_addresses=0.0.0.0 --port=5432 --cluster_name=pgcluster2 --wal_level=replica --hot_standby=on --max_connections=100 --max_wal_senders=10 --max_prepared_transactions=0 --max_locks_per_transaction=64 --track_commit_timestamp=off --max_replication_slots=10 --max_worker_processes=8 --wal_log_hints=on

已尝试以下方法:

  • 将导出语句添加到.bashrc用户postgres的
  • 将导出语句添加到.bash_profile用户postgres的
  • 将导出语句添加到/etc/profile服务器的全局
  • 将/dbdata/oracle/instantclient_19_12/路径添加到/etc/ld.so.conf

每次重新启动 Patroni 时,Postgres 也是如此(由不断变化的 PID 检查),但环境总是如下所示:

dbserver01 root 7 (/dbdata/oracle/instantclient_19_12): cat /proc/27443/environ | xargs -0 -n 1
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/var/lib/pgsql
LOGNAME=postgres
USER=postgres
SHELL=/bin/bash
INVOCATION_ID=3806a21dfa52455baad431cc2bbfa533
JOURNAL_STREAM=9:5426402
dbserver01 root 8 (/dbdata/oracle/instantclient_19_12):

Patroni 文档有大量关于 Patroni 特定环境变量的信息,但到目前为止我还没有找到任何有助于将变量传递给 Postgres 进程的文档。

复制依赖关系可能会解决问题,但是,添加变量将是解决问题的首选方法。是否有正确或受支持的方式将环境变量添加到由 Patroni 启动的 postgres 进程?

编辑 1:安装过程是使用用户签出存储库完成的root,在设置上述导出后,然后使用make和编译make install。这是当前两个命令的输出:

dbserver01 root 25 (/tmp/oracle_fdw): make
make: Nothing to be done for 'all'.
goeccdb11l root 26 (/tmp/oracle_fdw): make install
/usr/bin/mkdir -p '/usr/lib/postgresql14/lib64'
/usr/bin/mkdir -p '/usr/share/postgresql14/extension'
/usr/bin/mkdir -p '/usr/share/postgresql14/extension'
/usr/bin/mkdir -p '/usr/share/doc/packages/postgresql14/extension'
/usr/bin/install -c -m 755  oracle_fdw.so '/usr/lib/postgresql14/lib64/oracle_fdw.so'
/usr/bin/install -c -m 644 .//oracle_fdw.control '/usr/share/postgresql14/extension/'
/usr/bin/install -c -m 644 .//oracle_fdw--1.2.sql .//oracle_fdw--1.0--1.1.sql .//oracle_fdw--1.1--1.2.sql  '/usr/share/postgresql14/extension/'
/usr/bin/install -c -m 644 .//README.oracle_fdw '/usr/share/doc/packages/postgresql14/extension/'
dbserver01 root 27 (/tmp/oracle_fdw): ls -la /usr/lib/postgresql14/lib64

编辑2:我再次尝试安装,使用和make clean过程:makemake install

dbserver01 root 11 (/tmp/oracle_fdw): make clean
rm -f oracle_fdw.so   liboracle_fdw.a  liboracle_fdw.pc
rm -f oracle_fdw.o oracle_utils.o oracle_gis.o oracle_fdw.bc oracle_utils.bc oracle_gis.bc
rm -rf results/ regression.diffs regression.out tmp_check/ tmp_check_iso/ log/ output_iso/
dbserver01 root 12 (/tmp/oracle_fdw): export LD_LIBRARY_PATH=/dbdata/oracle/instantclient_19_12
dbserver01 root 13 (/tmp/oracle_fdw): export ORACLE_HOME=/dbdata/oracle/instantclient_19_12
dbserver01 root 14 (/tmp/oracle_fdw): export PATH=/dbdata/oracle/instantclient_19_12:$PATH
dbserver01 root 15 (/tmp/oracle_fdw): make
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g -fPIC -I"/dbdata/oracle/instantclient_19_12/sdk/include" -I"/dbdata/oracle/instantclient_19_12/oci/include" -I"/dbdata/oracle/instantclient_19_12/rdbms/public" -I"/dbdata/oracle/instantclient_19_12/" -I/usr/include/oracle/21/client64 -I/usr/include/oracle/19.14/client64 -I/usr/include/oracle/19.12/client64 -I/usr/include/oracle/19.12/client -I/usr/include/oracle/19.11/client64 -I/usr/include/oracle/19.11/client -I/usr/include/oracle/19.10/client64 -I/usr/include/oracle/19.10/client -I/usr/include/oracle/19.9/client -I/usr/include/oracle/19.9/client64 -I/usr/include/oracle/19.8/client -I/usr/include/oracle/19.8/client64 -I/usr/include/oracle/19.6/client -I/usr/include/oracle/19.6/client64 -I/usr/include/oracle/19.3/client -I/usr/include/oracle/19.3/client64 -I/usr/include/oracle/18.5/client -I/usr/include/oracle/18.5/client64 -I/usr/include/oracle/18.3/client -I/usr/include/oracle/18.3/client64 -I/usr/include/oracle/12.2/client -I/usr/include/oracle/12.2/client64 -I/usr/include/oracle/12.1/client -I/usr/include/oracle/12.1/client64 -I/usr/include/oracle/11.2/client -I/usr/include/oracle/11.2/client64 -I. -I./ -I/usr/include/pgsql/server -I/usr/include/pgsql/internal  -D_GNU_SOURCE -I/usr/include/libxml2   -c -o oracle_fdw.o oracle_fdw.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g -fPIC -I"/dbdata/oracle/instantclient_19_12/sdk/include" -I"/dbdata/oracle/instantclient_19_12/oci/include" -I"/dbdata/oracle/instantclient_19_12/rdbms/public" -I"/dbdata/oracle/instantclient_19_12/" -I/usr/include/oracle/21/client64 -I/usr/include/oracle/19.14/client64 -I/usr/include/oracle/19.12/client64 -I/usr/include/oracle/19.12/client -I/usr/include/oracle/19.11/client64 -I/usr/include/oracle/19.11/client -I/usr/include/oracle/19.10/client64 -I/usr/include/oracle/19.10/client -I/usr/include/oracle/19.9/client -I/usr/include/oracle/19.9/client64 -I/usr/include/oracle/19.8/client -I/usr/include/oracle/19.8/client64 -I/usr/include/oracle/19.6/client -I/usr/include/oracle/19.6/client64 -I/usr/include/oracle/19.3/client -I/usr/include/oracle/19.3/client64 -I/usr/include/oracle/18.5/client -I/usr/include/oracle/18.5/client64 -I/usr/include/oracle/18.3/client -I/usr/include/oracle/18.3/client64 -I/usr/include/oracle/12.2/client -I/usr/include/oracle/12.2/client64 -I/usr/include/oracle/12.1/client -I/usr/include/oracle/12.1/client64 -I/usr/include/oracle/11.2/client -I/usr/include/oracle/11.2/client64 -I. -I./ -I/usr/include/pgsql/server -I/usr/include/pgsql/internal  -D_GNU_SOURCE -I/usr/include/libxml2   -c -o oracle_utils.o oracle_utils.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g -fPIC -I"/dbdata/oracle/instantclient_19_12/sdk/include" -I"/dbdata/oracle/instantclient_19_12/oci/include" -I"/dbdata/oracle/instantclient_19_12/rdbms/public" -I"/dbdata/oracle/instantclient_19_12/" -I/usr/include/oracle/21/client64 -I/usr/include/oracle/19.14/client64 -I/usr/include/oracle/19.12/client64 -I/usr/include/oracle/19.12/client -I/usr/include/oracle/19.11/client64 -I/usr/include/oracle/19.11/client -I/usr/include/oracle/19.10/client64 -I/usr/include/oracle/19.10/client -I/usr/include/oracle/19.9/client -I/usr/include/oracle/19.9/client64 -I/usr/include/oracle/19.8/client -I/usr/include/oracle/19.8/client64 -I/usr/include/oracle/19.6/client -I/usr/include/oracle/19.6/client64 -I/usr/include/oracle/19.3/client -I/usr/include/oracle/19.3/client64 -I/usr/include/oracle/18.5/client -I/usr/include/oracle/18.5/client64 -I/usr/include/oracle/18.3/client -I/usr/include/oracle/18.3/client64 -I/usr/include/oracle/12.2/client -I/usr/include/oracle/12.2/client64 -I/usr/include/oracle/12.1/client -I/usr/include/oracle/12.1/client64 -I/usr/include/oracle/11.2/client -I/usr/include/oracle/11.2/client64 -I. -I./ -I/usr/include/pgsql/server -I/usr/include/pgsql/internal  -D_GNU_SOURCE -I/usr/include/libxml2   -c -o oracle_gis.o oracle_gis.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g -fPIC -shared -o oracle_fdw.so oracle_fdw.o oracle_utils.o oracle_gis.o -L/usr/lib/postgresql14/lib64   -L/usr/lib64  -Wl,--as-needed  -L"/dbdata/oracle/instantclient_19_12/" -L"/dbdata/oracle/instantclient_19_12/bin" -L"/dbdata/oracle/instantclient_19_12/lib" -L"/dbdata/oracle/instantclient_19_12/lib/amd64" -lclntsh -L/usr/lib/oracle/21/client64/lib -L/usr/lib/oracle/19.14/client64/lib -L/usr/lib/oracle/19.12/client64/lib -L/usr/lib/oracle/19.12/client/lib -L/usr/lib/oracle/19.11/client64/lib -L/usr/lib/oracle/19.11/client/lib -L/usr/lib/oracle/19.10/client64/lib -L/usr/lib/oracle/19.10/client/lib -L/usr/lib/oracle/19.9/client/lib -L/usr/lib/oracle/19.9/client64/lib -L/usr/lib/oracle/19.8/client/lib -L/usr/lib/oracle/19.8/client64/lib -L/usr/lib/oracle/19.6/client/lib -L/usr/lib/oracle/19.6/client64/lib -L/usr/lib/oracle/19.3/client/lib -L/usr/lib/oracle/19.3/client64/lib -L/usr/lib/oracle/18.5/client/lib -L/usr/lib/oracle/18.5/client64/lib -L/usr/lib/oracle/18.3/client/lib -L/usr/lib/oracle/18.3/client64/lib -L/usr/lib/oracle/12.2/client/lib -L/usr/lib/oracle/12.2/client64/lib -L/usr/lib/oracle/12.1/client/lib -L/usr/lib/oracle/12.1/client64/lib -L/usr/lib/oracle/11.2/client/lib -L/usr/lib/oracle/11.2/client64/lib
dbserver01 root 16 (/tmp/oracle_fdw): make install
/usr/bin/mkdir -p '/usr/lib/postgresql14/lib64'
/usr/bin/mkdir -p '/usr/share/postgresql14/extension'
/usr/bin/mkdir -p '/usr/share/postgresql14/extension'
/usr/bin/mkdir -p '/usr/share/doc/packages/postgresql14/extension'
/usr/bin/install -c -m 755  oracle_fdw.so '/usr/lib/postgresql14/lib64/oracle_fdw.so'
/usr/bin/install -c -m 644 .//oracle_fdw.control '/usr/share/postgresql14/extension/'
/usr/bin/install -c -m 644 .//oracle_fdw--1.2.sql .//oracle_fdw--1.0--1.1.sql .//oracle_fdw--1.1--1.2.sql  '/usr/share/postgresql14/extension/'
/usr/bin/install -c -m 644 .//README.oracle_fdw '/usr/share/doc/packages/postgresql14/extension/'
dbserver01 root 17 (/tmp/oracle_fdw):

编辑 3:添加了第 4 种方法来获取进入 postgres 用户进程的路径。

postgresql environment-variables
  • 2 个回答
  • 127 Views
Martin Hope
0xCAFEBABE
Asked: 2022-02-22 03:09:37 +0800 CST

Oracle 中的系统版本表

  • 0

一些开发人员找到我,并询问将历史记录添加到包含主数据的某个表的最简单方法。作为熟悉 SQL 2011、SQL-Server(作为标准功能)和 PostgreSQL(作为提议)上下文中的系统版本表的人,我非常确定 Oracle 会支持该标准功能。

但是,在阅读和检查了一整天之后,我找不到对实际 SYSTEM VERSIONED 表的任何引用。作为参考,以下是Wikipedia关于标准和 Oracles 实施的说法:

...
使用 PERIOD FOR SYSTEM_TIME 注释和 WITH SYSTEM VERSIONING 修饰符定义系统版本表(在其他地方称为事务时间表)。系统时间段是自动维护的。系统版本表的约束不需要是临时的,只在当前行上强制执行
……
Oracle Oracle 12c 支持符合 SQL:2011 的临时功能。 [9] 版本 10g 和 11g 在他们所谓的闪回查询中实现了时间片查询,使用替代语法 AS OF TIMESTAMP。[10] 值得注意的是,Oracle 的两种实现都依赖于数据库事务日志,因此只允许对仍保留用于备份的最近更改进行临时查询。

但是,即使按照引用的链接,我也找不到显示如何让 Oracle 为我对行进行版本控制的单个参考。所有示例仅参考从列和到列有效性的手动更新。

我想我可以从 Data Warehousing 实现类似SCD2的东西,但这只是一种开发模式,没有参考有效性是如何实际更新的。我真的很想为开发人员提供一个简单的解决方案,因为手动更新有效性很容易出错(重叠是一个因素),而且我认为需要做更多的工作。

对于 SQL 2011 标准所描述的内容,Oracle 中真的没有系统版本控制吗?

oracle
  • 1 个回答
  • 143 Views
Martin Hope
0xCAFEBABE
Asked: 2021-10-26 00:40:07 +0800 CST

PostgreSQL 13.4:使用 ALTER SYSTEM 设置 synchronous_commit 不会改变它

  • 1

我们目前正在使用 PostgreSQL 13.4、Patroni、Consul 和 Confd 构建一个 PostgreSQL 集群。设置成功(Patroni 集群使用一个主服务器和一个副本进行复制),我们正在尝试使用具有不同复制设置的 pgbench 进行一些基准测试,特别是synchronous_commit.

该文档清楚地表明,synchronous_commitMaster 上的有效值为:

  • 离开
  • 当地的
  • 远程写入
  • 上
  • 远程应用

随着网络故障和崩溃(广义上)的安全性不断提高。所以这个想法是为每个设置生成一些基准(使用 pgbench)。正如文档所解释的,唯一有效的值synchronous_commit是on和off何时synchronous_standby_names为空。我们synchronous_standby_names有*.

然而,当改变 的值时synchronous_commit,它似乎并没有改变任何东西。例子:

gobsux59:/etc/patroni # su - postgres
postgres@gobsux59:~> psql
psql (13.4)
Type "help" for help.

postgres=# show synchronous_commit;
 synchronous_commit
--------------------
 off
(1 row)

postgres=# alter system set synchronous_commit = 'local';
ALTER SYSTEM
postgres=# show synchronous_commit;
 synchronous_commit
--------------------
 off
(1 row)

postgres=# alter system set synchronous_commit = 'remote_write';
ALTER SYSTEM
postgres=# show synchronous_commit;
 synchronous_commit
--------------------
 off
(1 row)

postgres=# alter system set synchronous_commit = 'on';
ALTER SYSTEM
postgres=# show synchronous_commit;
 synchronous_commit
--------------------
 off
(1 row)

postgres=# alter system set synchronous_commit = 'remote_apply';
ALTER SYSTEM
postgres=# show synchronous_commit;
 synchronous_commit
--------------------
 off
(1 row)

postgres=#

总是有一些系统在这里干扰的机会,所以我检查了是否synchronous_commit在适用的配置文件中的其他任何地方列出:

postgres@gobsux59:~/data> grep synchronous_commit *
postgresql.auto.conf:synchronous_commit = 'remote_apply'
postgresql.base.conf:#synchronous_commit = on           # synchronization level;
postgresql.base.conf.backup:#synchronous_commit = on            # synchronization level;

可以看到postgresql.auto.conf(PostgreSQL根据语句自动编写的配置文件ALTER SYSTEM)包含了上次使用设置的值ALTER SYSTEM,但是在查询数据库时却显示了不同的值。

我已经研究了可能存在不同的配置范围,在这些范围中我覆盖了我正在查询的范围之外的另一个范围,但似乎并非如此(尽管我认识到可以为每个连接设置许多设置,每个-事务、每个集群等)。

我不确定如何进一步理解这个问题,我将不胜感激。

postgresql replication
  • 1 个回答
  • 409 Views
Martin Hope
0xCAFEBABE
Asked: 2019-08-16 02:21:11 +0800 CST

快速获取少量行

  • -1

我不确定我的 SQL 是否有问题或问题出在 Oracle 上。我们在一个 Web 应用程序上有一个函数,它需要显示一个包含大量条目(以百万计)的表格。但是,显示一次只能获取 500 行。我的猜测是这应该非常快。

这个想法是做这样的事情:

SELECT TOP 500 <tablename> WHERE <where-clause>

WHERE 子句完全被索引覆盖。但是,Oracle 不提供TOPor LIMIT,因此使用的替代方法似乎是ROW_NUMBER()or OFFSET/FETCH FIRST。

但是,在检查执行计划时,似乎即使对于最简单的查询,Oracle 也假装它需要在应用ROW_NUMBER()和过滤之前读取完整的表。FETCH FIRST 也是如此,因为 Oracle 似乎将 FETCH FIRST 转换为一个ROW_NUMBER()构造:

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=500)
   2 - filter(ROW_NUMBER() OVER ( ORDER BY  NULL )<=500)

例子:

SELECT ID FROM <tablename> FETCH FIRST 500 ROWS ONLY;

执行计划:

-----------------------------------------------------------------------------------------------
| Id  | Operation              | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                      |  1643K|  5581M| 34399   (1)| 00:00:03 |
|*  1 |  VIEW                  |                      |  1643K|  5581M| 34399   (1)| 00:00:03 |
|*  2 |   WINDOW NOSORT STOPKEY|                      |  1643K|  1234M| 34399   (1)| 00:00:03 |
|   3 |    TABLE ACCESS FULL   | TABLENAME            |  1643K|  1234M| 34399   (1)| 00:00:03 |
-----------------------------------------------------------------------------------------------

只有一行会变得更加极端,因为执行计划是相同的。这些成本对于导致行数非常少的操作来说是残酷的。

有没有办法阻止 Oracle 在返回任何内容之前读取所有记录?

编辑1:

由于下面的@Balasz-Papp 得到完全不同的执行计划、基数和成本,我将在此处记录一个完整的示例。

这是一个刚刚组合在一起的查询(有一个仅覆盖 id 字段的索引):

SELECT * FROM <tablename> ORDER BY id FETCH FIRST 500 ROWS ONLY;

执行计划如下所示(使用 SQL Developer 和 TOAD 收集):

---------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name                 | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |                      |  1643K|  5601M|       |   204K  (1)| 00:00:16 |
|*  1 |  VIEW                    |                      |  1643K|  5601M|       |   204K  (1)| 00:00:16 |
|*  2 |   WINDOW SORT PUSHED RANK|                      |  1643K|  1234M|  1351M|   204K  (1)| 00:00:16 |
|   3 |    TABLE ACCESS FULL     | TABLE_NAME           |  1643K|  1234M|       | 34399   (1)| 00:00:03 |
---------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=500)
2 - filter(ROW_NUMBER() OVER ( ORDER BY "EVENT"."ID")<=500)

执行此语句需要 14 分钟多一点。这台机器的性能不是很好,但是选择并返回 500 行与选择近 6GB 中的 160 万行并返回前 500 行之间的区别似乎是正在发生的事情。

编辑2:

我尝试复制另一种方式来生成执行计划,在我的示例中使用这些语句:

select /*+ gather_plan_statistics */ * from TABLE_NAME order by id fetch first 500 rows only;
select * from table(dbms_xplan.display_cursor(format=>'allstats last'));

生成的计划如下所示:

Plan hash value: 4184280406                                                     

--------------------------------------------------------------------------------------------------------------------------------------                          
| Id  | Operation                | Name                 | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |                          
--------------------------------------------------------------------------------------------------------------------------------------                          
|   0 | SELECT STATEMENT         |                      |      1 |        |    500 |00:00:40.11 |   92135 |       |       |          |                          
|*  1 |  VIEW                    |                      |      1 |   1643K|    500 |00:00:40.11 |   92135 |       |       |          |                          
|*  2 |   WINDOW SORT PUSHED RANK|                      |      1 |   1643K|    500 |00:00:40.11 |   92135 |   549K|   408K|  487K (0)|                          
|   3 |    TABLE ACCESS FULL     | MTR_EVENTPROTOCOL_TA |      1 |   1643K|   1645K|00:00:36.65 |   92135 |       |       |          |                          
--------------------------------------------------------------------------------------------------------------------------------------                          


Predicate Information (identified by operation id):                             
---------------------------------------------------                             

   1 - filter("from$_subquery$_002"."rowlimit_$$_rownumber"<=500)               
   2 - filter(ROW_NUMBER() OVER ( ORDER BY "EVENT"."ID")<=500)                  

编辑 3:按要求添加按 ID 进行简单提取的执行计划:

Plan hash value: 612488378

----------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                      |     1 |   840 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| MTR_EVENTPROTOCOL_TA |     1 |   840 |     3   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | MTR_EVENTPROTOCOL_PK |     1 |       |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("ID"=23417479)
oracle oracle-12c
  • 1 个回答
  • 134 Views
Martin Hope
0xCAFEBABE
Asked: 2019-08-15 04:59:08 +0800 CST

使用窗口函数防止 COUNT() 子查询

  • 0

我的一位开发人员同事要求我为他优化语句。我对当前级别的 SQL 技术和功能进行了简要介绍,并且感觉特别是窗口函数可以帮助我。

有问题的查询目前是这样的:

SELECT
T1.FIELD1,
T1.FIELD2
...
(SELECT COUNT (T2.FIELD1) FROM OUTER_TABLE_NAME T2 WHERE T2.FOREIGN_KEY = T1.PRIMARY_KEY) AS COMMENTS
FROM T1
;

这迫使数据库对主表 T1 中的每条记录运行子查询,这通常很慢。更好的方法是如果有一个可以表达相同的窗口函数。但是,它不能与主表 T1 中的记录相乘。

我想过这样的事情:

SELECT
T1.FIELD1,
T2.FIELD2
...
COUNT(T2.FOREIGN_KEY) OVER (PARTITION BY T2.FOREIGN_KEY)
FROM T1
LEFT OUTER JOIN T2 ON T2.FOREIGN_KEY = T1.KEY
;

它必须是 OUTER JOIN 才能不过滤主表 T1 中的记录。但是,这种方式将把主表 T1 中的记录与辅助表 T2 中的每个匹配记录相乘。

有没有办法在 Oracle 12.2 中使用窗口函数或任何其他非专有方法来表达 count()?

oracle oracle-12c
  • 1 个回答
  • 41 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve