【问题标题】:Improve view performance提高视图性能
【发布时间】:2016-04-27 14:00:44
【问题描述】:

我需要提高我的视图性能,现在生成视图的 SQL 是:

select tr.account_number , tr.actual_collection_trx_date ,s.customer_key
from   fct_collections_trx tr,
       stg_scd_customers_key s
where  tr.account_number = s.account_number
and    trunc(tr.actual_collection_trx_date) between s.start_date and s.end_date;

表 fct_collections_trx 有 170k+-(每天变化)记录。

表 stg_scd_customers_key 有 4.3 亿条记录。

表 fct_collections_trx 的索引如下: (所有这些的单一索引)(ACCOUNT_NUMBER、SUB_ACCOUNT_NUMBER、ACTUAL_COLLECTION_TRX_DATE、COLLECTION_TRX_DATE、COLLECTION_ACTION_CODE)(唯一)和ENTRY_SCHEMA_DATE(正常)。 DDL:

alter table stg_admin.FCT_COLLECTIONS_TRX
add primary key (ACCOUNT_NUMBER, SUB_ACCOUNT_NUMBER, ACTUAL_COLLECTION_TRX_DATE, COLLECTION_TRX_DATE, COLLECTION_ACTION_CODE)
  using index 
  tablespace STG_COLLECTION_DATA
  pctfree 10
  initrans 2
  maxtrans 255
  storage
   (
    initial 80K
    next 1M
    minextents 1
    maxextents unlimited
  );

表结构:

create table stg_admin.FCT_COLLECTIONS_TRX
(
  account_number              NUMBER(10) not null,
  sub_account_number          NUMBER(5) not null,
  actual_collection_trx_date  DATE not null,
  customer_key                NUMBER(10),
  sub_account_key             NUMBER(10),
  schema_key                  VARCHAR2(10) not null,
  collection_group_code       CHAR(3),
  collection_action_code      CHAR(3) not null,
  action_order                NUMBER,
  bucket                      NUMBER(5),
  collection_trx_date         DATE not null,
  days_into_cycle             NUMBER(5),
  logical_delete_date         DATE,
  balance                     NUMBER(10,2),
  abbrev                      CHAR(8),
  customer_status             CHAR(2),
  sub_account_status          CHAR(2),
  entry_schema_date           DATE,
  next_collection_action_code CHAR(3),
  next_collectin_trx_date     DATE,
  reject_key                  NUMBER(10) not null,
  dwh_update_date             DATE,
  delta_type                  VARCHAR2(1)
)

表 stg_scd_customers_key 有索引 : (SINGLE INDEX OF ALL OF THEM) (ACCOUNT_NUMBER,START_DATE,END_DATE)。 DDL:

create unique index stg_admin.STG_SCD_CUST_KEY_PKP on stg_admin.STG_SCD_CUSTOMERS_KEY (ACCOUNT_NUMBER, START_DATE, END_DATE);

这个表也是分区的:

partition by range (END_DATE)
(
  partition SCD_CUSTOMERS_20081103 values less than (TO_DATE(' 2008-11-04 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
    tablespace FCT_CUSTOMER_SERVICES_DATA
    pctfree 10
    initrans 1
    maxtrans 255
    storage
    (
      initial 8M
      next 1M
      minextents 1
      maxextents unlimited
    )

表结构:

create table stg_admin.STG_SCD_CUSTOMERS_KEY
(
  customer_key   NUMBER(18) not null,
  account_number NUMBER(10) not null,
  start_date     DATE not null,
  end_date       DATE not null,
  curr_ind       NUMBER(1) not null
)

我不能在大表上添加过滤器(需要所有日期范围),我不能使用物化视图。这个查询运行大约 20-40 分钟,我必须让它更快.. 我已经尝试过放弃 trunc,没有什么不同。

有什么建议吗?

解释计划:

【问题讨论】:

  • Probaby trunc(tr.actual_collection_trx_date) between 是弱点。
  • 已经尝试删除它,似乎没有不同的@jarlh
  • 返回多少行?传输大量数据可能需要一些时间...
  • 大约 170k,取决于较小的表大小.. @jarlh
  • 分区是如何定义的?也许这两个表及其索引的 DDL 会有所帮助。

标签: sql oracle performance select view


【解决方案1】:

首先,使用显式join 语法编写查询:

select tr.account_number , tr.actual_collection_trx_date ,s.customer_key
from fct_collections_trx tr join
     stg_scd_customers_key s
     on tr.account_number = s.account_number and
        trunc(tr.actual_collection_trx_date) between s.start_date and s.end_date;

您已经为客户表建立了适当的索引。您可以在fct_collections_trx(account_number, trunc(actual_collection_trx_date), actual_collection_trx_date) 上尝试索引。 Oracle 可能会发现这对join 很有用。

但是,如果您正在寻找单个匹配项,那么我想知道是否有另一种可能有效的方法。以下查询的性能如何工作:

select tr.account_number , tr.actual_collection_trx_date,
       (select min(s.customer_key) keep (dense_rank first order by s.start_date desc)
        from stg_scd_customers_key s
        where tr.account_number = s.account_number and
              tr.actual_collection_trx_date >= s.start_date 
       ) as customer_key
from fct_collections_trx tr ;

此查询与原始查询不完全相同,因为它没有进行任何过滤,也没有检查结束日期。不过,有时这种措辞可能更有效。

另外,我认为在这种情况下trunc() 是不必要的,因此stg_scd_customers_key(account_number, start_date, customer_key) 上的索引是最佳的。

表达式min(x) keep (dense_rank first order by) 本质上是first()——它获取列表中的第一个元素。请注意,min() 并不重要; max() 也可以。因此,此表达式获取第一个满足 where 子句中条件的客户密钥。我观察到这个函数在 Oracle 中非常快,而且通常比其他方法更快。

【讨论】:

  • 哇,花了 10 秒!你能解释一下 keep(dense_rank.... 是做什么的吗?我不熟悉这个函数,我需要确保它返回的结果与原始查询完全相同@GordonLinoff
  • 当我查看此查询的结果时,我注意到对于每个帐号,无论日期是什么,都会返回相同的密钥.. 还没有调查,但我有感觉不对
  • @sagi 。 . .糟糕,我将desc 留在了order by 之外,所以它返回的是第一个客户密钥而不是最后一个。我认为更改不会影响性能。
  • 嗯,它工作得很好,非常感谢.. 如果可以的话,我会简短解释一下子选择的作用
  • @saig 。 . .我不完全理解其中的原因。它取列表中第一个元素的最小值。我认为 Oracle 想要一种灵活的语法,所以你可以做一些事情,比如取前三个元素的平均值(尽管我从未将它用于此目的)。
【解决方案2】:

如果开始日期和结束日期没有时间元素(即它们都默认为午夜),那么您可以这样做:

select tr.account_number , tr.actual_collection_trx_date ,s.customer_key
from   fct_collections_trx tr,
       stg_scd_customers_key s
where  tr.account_number = s.account_number
and    tr.actual_collection_trx_date >= s.start_date
and    tr.actual_collection_trx_date < s.end_date + 1;

除此之外,您还可以为每个表添加一个索引,其中包含以下列:

  • 对于 fct_collections_trx:(account_number,actual_collection_trx_date)
  • 对于 stg_scd_customers_key:(account_number、start_date、end_date、customer_key)

这样,查询应该能够使用索引,而不必去表。

【讨论】:

  • trunc 没关系,没有它会花费相同的时间.. 两个表都有你所说的所有索引,除了 Customer_key,我看不出它对性能有什么帮助.. @boneist
  • 好吧,考虑一下。如果信息不在索引中,则查询现在必须转到表中。这是一个两步的过程。如果查询中引用的所有列都在索引中,那么它很可能能够跳过去表。这个查询的解释计划是什么?请更新您的问题以添加它。
  • 当您说“两个表都有所有索引”时,您是什么意思? fct_collections_trx 上是否有一个基于(ACCOUNT_NUMBER、SUB_ACCOUNT_NUMBER、ACTUAL_COLLECTION_TRX_DATE、COLLECTION_TRX_DATE、COLLECTION_ACTION_CODE)的唯一索引,还是每列都有一个索引?
  • 更新并添加了解释计划。而且它是一个单一的索引,我不能改变这个表的结构,因为它在很多其他地方都在使用(它是这样构建的,这是有原因的)@Boneist
  • 不能添加额外的索引?
【解决方案3】:

我建议您根据您的案例中最具选择性的字段进行索引

 START_DATE, END_DATE

尝试恢复(或添加适当的)索引

 START_DATE, END_DATE, ACCOUNT_NUMBER

在表中stg_scd_customers_key

【讨论】:

  • 正如我在帖子中所说,该表已经有这些索引.. @scaisEdge
  • 我看到了索引 .. 我建议您按照我发布的顺序创建和索引 .. start_date 和 end_date 在 account_numebr 之前 .. 这样索引工作得更好。 . 并在短时间内解决关系..
猜你喜欢
  • 2020-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多