SELECT /*+ USE_HASH(plan t ash u) PARALLEL(4) NO_MERGE(t) NO_MERGE(ash) NO_MERGE(u) */
u.username,
t.owner table_owner,
t.table_name,
MAX(ash.sample_time) last_access_time
FROM (SELECT /*+ NO_MERGE */ sql_id,plan_hash_value,object_name,object_owner
FROM dba_hist_sql_plan
WHERE object_name IS NOT NULL
AND object_type = 'TABLE'
GROUP BY sql_id,plan_hash_value,object_name,object_owner) plan,
dba_tables t,
dba_hist_active_sess_history ash,
dba_users u
WHERE plan.object_owner = t.owner
AND plan.object_name = t.table_name
AND plan.sql_id = ash.sql_id
AND plan.plan_hash_value = ash.sql_plan_hash_value
AND ash.user_id = u.user_id
GROUP BY u.username,
t.owner,
t.table_name
SELECT /*+ USE_HASH(plan t ash u) PARALLEL(4) NO_MERGE(t) NO_MERGE(ash) NO_MERGE(u) */
u.username,
t.owner table_owner,
t.table_name,
MAX(ash.sample_time) last_access_time
FROM (SELECT /*+ NO_MERGE */ sql_id,plan_hash_value,object_name,object_owner
FROM gv$sql_plan
WHERE object_name IS NOT NULL
AND object_type = 'TABLE'
GROUP BY sql_id,plan_hash_value,object_name,object_owner) plan,
dba_tables t,
gv$active_session_history ash,
dba_users u
WHERE plan.object_owner = t.owner
AND plan.object_name = t.table_name
AND plan.sql_id = ash.sql_id
AND plan.plan_hash_value = ash.sql_plan_hash_value
AND ash.user_id = u.user_id
GROUP BY u.username,
t.owner,
t.table_name
1条答案
按热度按时间vs91vp4v1#
Oracle不按表或用户存储上次查询的日期。您需要启用选择审计来捕获此信息,但这会占用大量空间,对用户造成性能影响,并且在忙碌的数据库上很快变得无法管理。
但是,如果您对100%的准确性不满意,您可以通过使用**活动会话历史记录(ASH)**数据来近似您所需要的内容,至少在您的保留允许的范围内。这样做的缺点是,磁盘上的数据只存储每10个样本中的1个(每秒采样一次),因此如果查询运行时间少于10秒,则可能无法捕获。这将删除很多你可能需要的小东西,因此这可能是不可接受的:
解决10分之1问题的一个选择是每半小时运行一次作业,并从内存中的ASH版本捕获此信息,该版本的粒度为1秒,因此不太可能错过东西(它仍然会错过一些亚秒级的活动):
然后将其记录到一个表中,并在每次运行时使用每个键的最新
last_access_time
结果合并/更新它。我建议大约每半小时一次,因为内存中的ASH数据仍然需要存在(它会在一段时间后滚走),并且您需要游标仍然存在于共享池中。您可能需要根据特定数据库的行为调整此建议间隔。(我每隔10分钟在我的足迹中这样做一次,只是为了安全起见,因为共享池中游标寿命的不可预测性,因为我有几个数据库,它们的游标在短短30分钟后就老化了)。因此,如果您需要完美的准确性,您需要使用Oracle的审计功能,但您可能会发现它占用了太多的空间。这是一个轻量级的选项,不太准确,但考虑到您的情况可能会满足您的需求。