【发布时间】:2021-08-09 13:15:12
【问题描述】:
- 我尝试通过触发器从本地数据库更新远程表(dblink)。 我的成本约为 24990。表数据数接近 3032965。
UPDATE remote_table
SET ip_stats = (
CASE
WHEN :NEW.ip_stats IN (22,30,) THEN 'Non-Network'
WHEN :NEW.ip_stats IN (23,31,182) THEN 'Cancel'
WHEN :NEW.ip_stats IN (24,32) THEN 'file'
WHEN :NEW.ip_stats IN (26,34) THEN 'online'
WHEN :NEW.ip_stats IN (63) THEN 'decrease'
WHEN :NEW.ip_stats IN (64) THEN 'increase'
END) ,
ip_comments = (
CASE :NEW.ip_commts
WHEN 154 THEN 'increase'
WHEN 155 THEN 'previous'
WHEN 156 THEN 'hardware'
WHEN 157 THEN 'software'
END) ,
feedback = :NEW.feedback ,
changed_by = :NEW.changed_by ,
create_dt = :NEW.create_dt ,
status = 'Y' ,
sum_amount = NVL (:NEW.net_amount ,0)
WHERE ID = :NEW.new_key;
以下是更新语句的解释计划。
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Inst |
---------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT REMOTE| | 1 | 195 | 24990 (2)| 00:05:00 | |
| 1 | UPDATE | remote_table | | | | | rmt |
|* 2 | TABLE ACCESS FULL | remote_table | 1 | 195 | 24990 (2)| 00:05:00 | rmt |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(TO_NUMBER("A1"."ID")=123478)
Note
-----
- fully remote statement
- 此外,当我对该 remote_table 使用 count(*) 时,它的成本与 24990 相同。
注意:我在下面的选择语句中使用INDEX 提示,但它不起作用
SELECT /*+INDEX (a Column_index_name)*/ COUNT(*) FROM remote_table a WHERE a.ID = 123478;
下面是 select count(*) 语句的解释计划。
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Inst |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT REMOTE| | 1 | 9 | 24990 (2)| 00:05:00 | |
| 1 | SORT AGGREGATE | | 1 | 9 | | | |
|* 2 | TABLE ACCESS FULL | remote_table | 1 | 9 | 24990 (2)| 00:05:00 | rmt |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(TO_NUMBER("A1"."ID")=123478)
Note
-----
- fully remote statement
任何人都可以就如何处理这个问题提出建议吗?
【问题讨论】:
-
DB 链接是最糟糕的选择,它们会破坏 oracle 执行计划,让您进行全表扫描。
-
id和new_key的数据类型是什么?id是字符串吗(这可以解释为什么谓词中有to_number)? -
嗯,除了
ID列是VARCHAR2@JustinCave 之外,我没有看到任何其他可能性。数字数据类型不会导致隐式转换,DATE或其他更多exotic 数据类型(如CLOB)将引发ORA-00932: inconsistent datatypes: ... -
与您的问题无关,但在触发器中更新远程表通常是个坏主意。这是一个同步更新,因此您通过涉及诸如两阶段提交和额外网络流量之类的事情来减慢本地事务。但更重要的是,您极大地影响了可用性,因为本地系统现在依赖于远程系统的启动和可访问性。有许多专门用于处理复制的技术,几乎肯定比滚动您自己的解决方案更可取。
-
@JustinCave 感谢您的建议和解决方案。
标签: sql oracle performance query-optimization sql-execution-plan