【问题标题】:How to read value inside a Database View?如何读取数据库视图中的值?
【发布时间】:2021-11-07 01:30:54
【问题描述】:

我有以下视图。

CREATE OR REPLACE VIEW vw_myview AS
SELECT
emp_joining_dt,
emp_joining_dt+365 as emp_reminder_dt
FROM EMP
/

员工入职一年后,需要发送提醒。日常工作读取emp_reminder_dt 并触发它。

365 天基本上是不变的。但是,要求是公司可能希望将其更改为 183 或 730。

因此,值 365 配置在表中并从 DB 中读取。

CREATE OR REPLACE VIEW vw_myview AS
SELECT
emp_joining_dt,
emp_joining_dt+MyPackage.get_reminder_days as emp_reminder_dt
FROM EMP
/

上述方法的问题是每次查询视图时都会调用数据库 从配置表中读取值。

有人担心应该避免频繁查询数据库。

有没有办法从数据库中第一次读取值 365,然后从某个缓存中读取。 那么当值改变时,从数据库中读取第一次,然后从某个缓存中读取?

使用缓存只是我的猜测,但还有其他方法吗?

【问题讨论】:

  • 经常查询?你每天运行一次,那么频繁吗?为什么要使用包 - 只需加入存储此值的表即可。
  • 在大多数查询中查找表中的一行不应该是特别的负担。
  • 无论你做什么,它已经从表 EMP 中读取,这将比从表 MyPackage 读取单行和单列的成本要高得多。我不会再浪费一秒钟来担心它了。
  • " 需要发送提醒。",那么这显然是某些预定程序的一部分。因此,将术语作为输入参数,设置为过程调度的属性。尽管正如其他人所说,您对“频繁查询”的担忧是非常错误的。每天一次从表中获取单行的这一查询对于数据库而言并非微不足道。
  • 您拥有的查找功能似乎是合理的。它是否被声明为确定性、并行启用并带有编译指示 UDF? (关于这是否是“确定性”的滥用,可以进行长时间而有趣的对话,因为它不是,但我会在这里将它用于语句级缓存。)你可以尝试result_cache,但我不确定它比使用标准缓存查询表要快。

标签: sql oracle performance plsql view


【解决方案1】:

任何合理的应用程序都可能有几十个您不想硬编码值的 1off 项。对于这些,我通常会创建一个General_Parameters 表。这是@SayanMalakshinov 建议的概括。大致如下:

create table general_parameters(
             parm_name    varchar2(64)
           , parm_integer integer 
           , parm_date    date
           , parm_text    varchar2(4000) 
           -- other parameter types
           , constraint general_parameters_pk
                        primary key (parm_name)  
           ); 

insert into general_parameters(parm_name, parm_integer) 
     values ('emp reminder interval',365); 

然后创建视图是:

create or replace view emp_reminder_view as
   select emp_id
        , emp_joining_dt 
        , emp_joining_dt
           + (select parm_integer
                from general_parameters
               where parm_name = 'emp reminder interval'
             )
            as emp_reminder_dt
    from emp; 

更改提醒间隔是更新表条目的简单问题。
注意:添加 emp_id 以查看没有任何限定符的 2 个日期,匆忙变得无用。

【讨论】:

  • 当在SELECT 中查询emp_reminder_view 时,它会访问general_parameters 表以从数据库中获取数据。我正在寻找一种在每次查询视图时都不会访问数据库的方法。是否有可能只有在编译视图时才从数据库中获取值并进一步查询获取结果而不命中数据库?
  • 当您从视图本身中选择时,您已经点击了数据库。它击中基础表?你认为视图是如何填充的?此外,视图在编译时访问。视图不过是存储的查询。
【解决方案2】:

我会创建一个特殊的表格来更改参数。一种最简单的方法如下所示 (SCD type 2):

create table emp_reminder_dt(
   emp_reminder_dt int,
   modified_dt date default sysdate,
   active varchar2(1 byte) not null check(active in ('Y','N')),
   active_uniq varchar2(1) invisible generated always as (case when active='Y' then 'Y' end),
   constraint c_active_uniq unique (active_uniq)
);

因此您可以始终拥有一个活动记录:不可见列 active_uniq(及其唯一约束)不允许拥有超过 1 个活动记录。

然后只需插入您的当前值:

insert into emp_reminder_dt(emp_reminder_dt,active)
  values(365, 'Y');
commit;

现在您可以轻松获得活跃值:

CREATE OR REPLACE VIEW vw_myview AS
SELECT
emp_joining_dt,
emp_joining_dt
 + (select r.emp_reminder_dt 
    from emp_reminder_dt r 
    where r.active_uniq='Y'
   ) 
  as emp_reminder_dt
FROM EMP

稍后您可以轻松地将活动行更改为active='N' 并添加具有新值的新记录,这样您将拥有一个简单的更改历史记录。

此外,您可以使用其他 SCD 类型来允许不同时间间隔的不同值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多