我有一个Oracle大表(约5000万行)。我需要创建一个报告,该报告仅显示大表的一部分的最后/下一个值。例如,该表如下所示,自2010年以来有会话,但是我只需要介绍发生在2019年的会话,但它们的最后一个值可以是2018年或更早的值。如果我过滤表格以仅接受2019年以来的会议,那么最后的会议也将自2019年以来。我不想在整个表上运行,因为它是非常大的表,并且查询很复杂。这将花费很多时间。该表如下所示:
有什么想法如何生成它以便使其高效,快速地运行?
典型查询:
select session_id, client_id, session_date, last_session, next_session
from (
select session_id, client_id, session_date,
lag (session_date) over (partition by client_id order by session_date) last_session,
lead(session_date) over (partition by client_id order by session_date) next_session
from sessions )
where session_date >= date '2019-01-01' order by session_id;
但是它确实表访问已满。您只能过滤2019年数据,并且仅对需要它的行运行子查询:
with t as (
select session_id, client_id, session_date,
lag (session_date) over (partition by client_id
order by session_date) last_session,
lead(session_date) over (partition by client_id
order by session_date) next_session
from sessions
where session_date >= date '2019-01-01')
select session_id, client_id, session_date,
nvl(last_session, (select max(session_date)
from sessions
where client_id = t.client_id
and session_date < t.session_date)) last_session,
next_session
from t order by session_id;
[dbfiddle demo] >>
我创建了两个索引:
create index idx_sessions_date on sessions(session_date); create index idx_sessions_client_date on sessions(client_id, session_date);
和计划表看起来很有希望,使用了两个索引:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1923279194
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Byte
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 31
| 1 | SORT AGGREGATE | | 1 | 2
| 2 | FIRST ROW | | 1 | 2
|* 3 | INDEX RANGE SCAN (MIN/MAX) | IDX_SESSIONS_CLIENT_DATE | 1 | 2
| 4 | SORT ORDER BY | | 6 | 31
| 5 | VIEW | | 6 | 31
| 6 | WINDOW SORT | | 6 | 21
| 7 | TABLE ACCESS BY INDEX ROWID| SESSIONS | 6 | 21
|* 8 | INDEX RANGE SCAN | IDX_SESSIONS_DATE | 1 |
--------------------------------------------------------------------------------