删除 Redshift 中的循环

2023-12-20

我有一个表,其中包含有关数据库中不同表的信息。对于其中的每个表,我希望定期进行日志记录(每天)。问题是我使用 for 循环完成了此操作,并且在 Redshift 中执行需要花费大量时间。我给出了用于创建表、日志记录表和使用 for 循环的过程的查询。 请建议一种替代方法来实现这一点而不需要 for 循环。 包含不同表信息的表结构:

CREATE TABLE public.info_schema_table
(
    info_schema_name character varying(200) ENCODE lzo,
    info_object_name character varying(200) ENCODE lzo,
    info_object_type character varying(200) ENCODE lzo,
    info_object_full_name character varying(400) ENCODE lzo
)
DISTSTYLE EVEN;

这里,对象名称指的是表名称,object_type 包含表是否是视图或表,object_full_name 存储表与模式的串联名称,即如果模式名称是“test_schema”,则全名是“test_schema.table_name” 。需要存储日志记录的表结构:

CREATE TABLE public.redshift_logging_table
(
    log_schema_name character varying(30) ENCODE lzo,
    log_object_name character varying(30) ENCODE lzo,
    log_object_type character varying(30) ENCODE lzo,
    log_refresh_date date ENCODE az64,
    log_refresh_count bigint ENCODE az64,
    log_total_count bigint ENCODE az64
)
DISTSTYLE EVEN;

这里,refresh_date 存储记录日期,refresh_count 存储当天插入表中的记录数,total_count 包含截至记录日期为止表中的记录总数。

为了澄清起见,下面是 info_schema_table 的一个示例记录:

这是我用来填充日志记录表的过程:

CREATE OR REPLACE PROCEDURE public.REDSHIFT_LOGGING_PROCEDURE()
AS $$
DECLARE
var_total_count bigint;
var_records_today bigint;
my_row record;
my_cursor CURSOR  
FOR select  info_schema_name, info_object_name, info_object_type , info_object_full_name  from INFO_SCHEMA_TABLE ;
BEGIN
  open my_cursor;
  LOOP
        FETCH my_cursor INTO my_row;
        EXIT WHEN NOT FOUND;
            BEGIN

             EXECUTE ' select count(1)::bigint  from '||my_row.INFO_OBJECT_FULL_NAME INTO var_total_count;
             var_records_today=var_total_count-(select log_total_count  from REDSHIFT_LOGGING_TABLE where REFRESH_DATE=current_date-1 and LOG_OBJECT_NAME=my_row.INFO_OBJECT_NAME);
             
             insert into REDSHIFT_LOGGING_TABLE
              (LOG_SCHEMA_NAME,LOG_OBJECT_NAME,LOG_OBJECT_TYPE,LOG_REFRESH_DATE, LOG_REFRESH_COUNT, LOG_TOTAL_COUNT )
              values 
              (my_row.info_schema_name, my_row.info_object_name, my_row.info_object_type , current_date, var_records_today, var_total_count);
            END;

  END LOOP;
END;
$$ LANGUAGE plpgsql
SECURITY INVOKER;

所有表的记录数仅逐日增加,因此在任何特定日期插入的记录始终 >=0。 问题是,这个过程有效,但仅适用于小记录info_schema_table,如果我运行大约 1000 条记录,该过程即使在一小时内也无法在 Redshift 上完成。

请建议一种不使用 for 循环来执行它的替代方法。谢谢。


好的,我们开始吧。

有工作insert它展示了如何在一个语句中实现这一点:

insert into redshift_logging_table(log_schema_name, log_object_name, log_object_type, log_refresh_date, log_refresh_count, log_total_count)
select distinct 
    ist.info_schema_name, 
    ist.info_object_name, 
    ist.info_object_type, 
    current_date
    , sti.tbl_rows - last_value(log_total_count ignore nulls) over (
        partition by log_object_name order by log_refresh_date asc
        rows between unbounded preceding and unbounded following
    )
    , sti.tbl_rows
from svv_table_info sti
inner join info_schema_table ist on ist.info_schema_name = sti.schema and ist.info_object_name = sti.table
left join redshift_logging_table rlt on rlt.log_schema_name = ist.info_schema_name and rlt.log_object_name = ist.info_object_name;

您可以仅使用来验证它是如何工作的select没有insert,这很好,因为它会显示将插入的内容,而实际上却没有这样做。


这里发生了什么: 从...开始from:

  • info_schema_table加入到svv_table_info获取实际行数。它允许避免动态创建select count每行的语句;
  • 接下来,进行左连接redshift_logging_table- 对于某些对象尚不存在(新创建的等)的情况,它是左连接

In select:

  • last_value使用的窗口函数(参见https://docs.aws.amazon.com/redshift/latest/dg/r_WF_first_value.html https://docs.aws.amazon.com/redshift/latest/dg/r_WF_first_value.html)它允许从由以下描述的某些行中的特定列中查找值partition by and order by)。该值是为每个对象名称单独计算的日志表中的最后刷新计数。

你可能需要以这样或那样的方式调整它,但我认为这是一个好的开始。另外,这可以直接移到您的存储过程中。

Enjoy!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

删除 Redshift 中的循环 的相关文章

  • 如何找到多个列中的最小值

    我在我的 DB 3 col 中有一个值 我想在所有这些值中找到一个值 如下所述 表名 MyTable id col1 col2 col3 1 200 300 400 2 100 150 300 3 800 102 20 4 80 80 0
  • 如何在mysql中选择具有相同值集的列?

    我的桌子是 patients pid name city disease did dname has disease did pid 我想列出具有相同疾病组的患者 pid 和 did 分别是患者和疾病表中的主键 并且是 has diseas
  • 删除连接到另一表 SQL 的一个表中的记录

    我有两个表 一个包含 212 000 条记录 已弃用的记录 另一个包含 10 500 000 条记录 我想在 id 和 version number 字段上连接两个表 因为两个表都有这些字段 我希望从连接表中删除匹配的记录 来自连接表 即从
  • 如何查找当前数据库类型

    我们有一个 SQL 脚本可以在多种类型的数据库上执行 是否可以获取正在执行 SQL 脚本的当前数据库的类型 注意 我们不能使用非标准 SQL 即 TSQL 等 不 ANSI SQL 中没有任何关于确定数据库供应商的内容
  • MySql 5.7 ORDER BY 子句不在 GROUP BY 子句中并且包含非聚合列

    我试图在不禁用 my ini 中的 only full group by 的情况下弄清楚 这是我的查询 SELECT p title COUNT t qty AS total FROM payments t LEFT JOIN produc
  • PL/pgSQL SELECT 到数组中

    这是我的函数声明和主体的一部分 CREATE OR REPLACE FUNCTION access update RETURNS void AS DECLARE team ids bigint BEGIN SELECT INTO team
  • 如何在 DB2 AS/400 中将小数字段转换为日期字段?

    我有一个 DECIMAL 字段 其中包含 AS400 格式的日期 1100614 我努力了 cast MYDATE as DATE 但我无法将 DECIMAL 转换为 DATE 而 DATE MYDATE 返回空值 如何将此字段转换为日期字
  • SQL 查询用于计算每个客户的订单数量和总金额

    我有两张桌子Order与列 OrderID OrderDate CID EmployeeID And OrderItem与列 OrderID ItemID Quantity SalePrice 我需要返回客户 ID CID 每个客户的订单数
  • Oracle:如何获取刚刚插入的行的序列号?

    如何获取刚刚插入的行的序列号 插入 返回 declare s2 number begin insert into seqtest2 x values aaa returning seq into s2 dbms output put lin
  • 通过 osql.exe 运行脚本时出现问题

    我尝试以这种格式运行我的软件的更新脚本 osql exe i path to script U 用户 P 密码 S sqlserver 位置 d 数据库名称 n b 大多数脚本的格式相同 并且都以 GO 结尾 其中很多都运行得很好 但随机脚
  • SQL 2008全文索引填充延迟

    我的经理说 在基础表数据更改后 可能需要一段时间才能更新全文搜索索引 例如 如果我有一张桌子Products有一个柱子Description我更新了该描述 然后我可能需要一些时间才能搜索该新描述 真的吗 这需要多长时间 SQL 2008 对
  • Reporting Services 在哪里存储其日志文件

    最相关的谷歌结果似乎表明 为了访问日志 我们必须将您自己的日志表部署到数据库并制作报告服务写入它 http technet microsoft com en us library ms157403 aspx 简而言之 Reporting S
  • 在存储过程中验证用户的最简单方法?

    我需要一个存储过程 可以通过发送以下内容来检查登录尝试时他们是否是有效用户login and password查看它们在数据库中是否匹配 有没有一种简单的方法可以做到这一点 如果没有更多信息 我目前能提供的最好信息是 CREATE STOR
  • st_intersects 与 st_overlaps

    这两个查询有什么区别 select a gid sum length b the geom from polygons as a roads as b where st intersects a the geom b the geom gr
  • 如何分割字符串并在ant脚本的for循环中使用它?

    我在 ant 属性中有一个机器 IP 列表
  • 提高第一个查询的性能

    如果执行以下数据库 postgres 查询 则第二次调用要快得多 我猜第一个查询很慢 因为操作系统 linux 需要从磁盘获取数据 第二个查询受益于文件系统级别和 postgres 中的缓存 有没有一种方法可以优化数据库以快速获得结果fir
  • 获取带有计数的不同记录

    我有一张桌子personid and msg列 personid msg 1 msg1 2 msg2 2 msg3 3 msg4 1 msg2 我想得到总计msg对于每个personid 我正在尝试这个查询 select distinct
  • 解析带下划线的 SQL Server 数字文字

    我想知道它为什么有效以及为什么它不返回错误 SELECT 2015 11 Result 11 2015 第二种情况 SELECT 2 1 a a 2 1 检查元数据 SELECT name system type name FROM sys
  • SELECT max(x) 返回 null;我怎样才能让它返回0?

    运行以下命令时如何返回 0 而不是 null SELECT MAX X AS MaxX FROM tbl WHERE XID 1 假设没有XID 1的行 or SELECT coalesce MAX X 0 AS MaxX FROM tbl
  • 快速将列的副本添加到 MySQL 表

    我需要一种快速的方法来复制表中的 DATETIME 列并为其指定一个新名称 我的表中有一个名为 myDate 的列 名为 myResults 我需要一个查询来在名为 newDate 的表中创建一个新列 该列的数据与 myDate 列完全相同

随机推荐