INSERT INTO...SELECT :NEW.FIELD FROM DUMMY

问题描述 投票:0回答:1

假设我们在 HANA 中有一个表 BASE:

CREATE COLUMN TABLE BASE
("CLIENT" NVARCHAR(3) DEFAULT '000' NOT NULL ,
 "KEY" DECIMAL(21,7) CS_FIXED DEFAULT 0 NOT NULL ,
 "VALUE_FIELD" NVARCHAR(100) DEFAULT '' NOT NULL,
 CONSTRAINT "BASE~0" PRIMARY KEY ("CLIENT", "KEY"));

然后我们创建一个日志表来捕获 BASE 表中更改记录的键:

CREATE COLUMN TABLE LOG_TABLE
("CLIENT" NVARCHAR(3) DEFAULT '000' NOT NULL ,
 "KEY" DECIMAL(21,7) CS_FIXED DEFAULT 0 NOT NULL ,
 "LOG_TIMESTAMP" DECIMAL(21,7) CS_FIXED DEFAULT 0 NOT NULL ,
 "DB_OPERATION" NVARCHAR(1) DEFAULT '' NOT NULL,
 CONSTRAINT "LOG_TABLE~0" PRIMARY KEY ("CLIENT", "KEY", "LOG_TIMESTAMP"));

这里我们不关心值字段,只关心键。我有一个触发代码生成器,具体取决于记录特定客户端或所有客户端中的更改的必要性。现在,我想出了这个解决方案:

CREATE OR REPLACE TRIGGER "trg_BASE_D"
AFTER DELETE ON "BASE"
REFERENCING OLD ROW AS R
FOR EACH ROW
BEGIN
  INSERT INTO "LOG_TABLE" (CLIENT, KEY, LOG_TIMESTAMP, DB_OPERATION)
  SELECT :R.CLIENT, :R.KEY, TO_NUMBER(TO_CHAR(CURRENT_UTCTIMESTAMP, 'YYYYMMDDHH24MISS.FF7')), 'D'
  FROM DUMMY
  WHERE :R.CLIENT IN ('010', '020');
END;

当然,为插入和更新创建了类似的触发器。 问题:这种从

dummy
中选择的解决方案比更明确的
IF
解决方案有什么优势吗?也就是说,使用
dummy
和使用
IF
时对性能有影响吗?

比较:

CREATE OR REPLACE TRIGGER "trg_BASE_D_IF"
AFTER DELETE ON "BASE"
REFERENCING OLD ROW AS R
FOR EACH ROW
BEGIN
  IF :R.CLIENT = '010' OR :R.CLIENT = '020' THEN
    INSERT INTO "LOG_TABLE" (CLIENT, KEY, LOG_TIMESTAMP, DB_OPERATION)
    VALUES (:R.CLIENT, :R.KEY, TO_NUMBER(TO_CHAR(CURRENT_UTCTIMESTAMP, 'YYYYMMDDHH24MISS.FF7')), 'D');
  END IF;
END;

IF
自动导致 SQL 脚本连续,但同时,它直接使用值,而不使用
dummy
。此外,这里没有什么可以并行的,因为触发器是基于 ROW 的;
WHERE
解决方案不使用
IF
,而是从
dummy
中进行选择。它将如何影响触发器性能?或者根本没有区别,在这种情况下取决于个人喜好?我更喜欢基于
WHERE
的解决方案,因为它更容易以编程方式生成;然而,两者都很容易实现,所以我对其中任何一个都持开放态度。

抱歉,我无法访问实际的 HANA 数据库来运行性能测试 - 我只在 ABAP 中生成触发代码...

triggers query-optimization hana
1个回答
0
投票

如果我不得不猜测,我会假设过程 IF 变体更好,因为它不需要准备和执行子查询 - 但差异可能很小,并且可能小于其他潜在影响。

我更担心的是批量插入到包含许多行的表中。为每行循环和执行单个插入可能会显着减慢速度。我猜想使用

FOR EACH STATEMENT
变体与
NEW TABLE
可能会更好,因为日志表中的插入可以批量完成:

CREATE OR REPLACE TRIGGER "trg_BASE_D"
AFTER DELETE ON "BASE"
REFERENCING OLD TABLE AS R
FOR EACH STATEMENT
BEGIN
  INSERT INTO "LOG_TABLE" (CLIENT, KEY, LOG_TIMESTAMP, DB_OPERATION)
  SELECT CLIENT, KEY, TO_NUMBER(TO_CHAR(CURRENT_UTCTIMESTAMP, 'YYYYMMDDHH24MISS.FF7')), 'D'
  FROM :R
  WHERE CLIENT IN ('010', '020');
END;
© www.soinside.com 2019 - 2024. All rights reserved.