oracle 查找字典以查看用户上次查询的表

u5rb5r59  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(98)

我需要从那里我可以看到每个表上的用户最后查询时间的字典。我知道sys.all_objects,它显示了最后一次ddl时间,我需要看看用户是什么时候查询表的。希望你能帮我找到解决办法。先谢了。

vs91vp4v

vs91vp4v1#

Oracle不按表或用户存储上次查询的日期。您需要启用选择审计来捕获此信息,但这会占用大量空间,对用户造成性能影响,并且在忙碌的数据库上很快变得无法管理。
但是,如果您对100%的准确性不满意,您可以通过使用**活动会话历史记录(ASH)**数据来近似您所需要的内容,至少在您的保留允许的范围内。这样做的缺点是,磁盘上的数据只存储每10个样本中的1个(每秒采样一次),因此如果查询运行时间少于10秒,则可能无法捕获。这将删除很多你可能需要的小东西,因此这可能是不可接受的:

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

解决10分之1问题的一个选择是每半小时运行一次作业,并从内存中的ASH版本捕获此信息,该版本的粒度为1秒,因此不太可能错过东西(它仍然会错过一些亚秒级的活动):

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

然后将其记录到一个表中,并在每次运行时使用每个键的最新last_access_time结果合并/更新它。我建议大约每半小时一次,因为内存中的ASH数据仍然需要存在(它会在一段时间后滚走),并且您需要游标仍然存在于共享池中。您可能需要根据特定数据库的行为调整此建议间隔。(我每隔10分钟在我的足迹中这样做一次,只是为了安全起见,因为共享池中游标寿命的不可预测性,因为我有几个数据库,它们的游标在短短30分钟后就老化了)。
因此,如果您需要完美的准确性,您需要使用Oracle的审计功能,但您可能会发现它占用了太多的空间。这是一个轻量级的选项,不太准确,但考虑到您的情况可能会满足您的需求。

相关问题