首页 > 解决方案 > 如果视图名称不断变化但查询结构保持不变,您如何“全局”调整 SQL 查询,使其由视图中的记录驱动?

问题描述

我有一个 Crystal 报表通过一个应用程序运行,由于需要 15 分钟的低效查询,该应用程序需要很长时间才能运行。我们正在运行 Oracle 19.4。CURSOR_SHARING = FORCE 用于数据库,这是每个供应商所必需的。请参阅下面的查询。

问题是,查询中的视图名称(例如以下示例中的 TW_RPT_11263_7833_199916)会根据应用程序内部运行的查询而更改,以提供过滤的记录 ID 列表。每次根据不同的应用程序查询运行报告时,都会有不同的 SQL ID,具体取决于该特定视图的选择条件。

因此,可以生成 SQL 配置文件,但它仅适用于一个查询/一个视图。即使使用 FORCE 选项生成 SQL 配置文件,当它具有不同的视图名称 TW_RPT_####_##### 时也不会使查询更快,并且它没有使用在 v$sql 中看到的 sql_profile。

向查询添加提示效果很好;查询在 1 秒内运行(参见下面的 SQL)。但是,每个用户使用不同的视图名称,这意味着应用提示仅适用于一个视图和该特定查询 ID。我也不知道如何注入这个提示;这是水晶报表。另外我不知道是否可以使用带有模式匹配的提示,例如 /*+ USE_HASH(TW_RPT_%) */ 或使用其他一些会根据视图名称更改提示的技术。

PR 表有 200 万行,而视图只有几行,因此视图需要驱动查询。

带有提示 USE_HASH 的 QUERY 需要 <1 秒,而没有提示则需要 15 分钟:

SELECT /*+ USE_HASH(TW_RPT_11263_7833_199916)*/ "PR"."ID", "PR"."NAME", "TW_V_IMPACT_LEVEL"."S_VALUE", "PROJECT"."NAME", "PR_1"."ID", "PROJECT_1"."NAME", "PR_1"."NAME", "PR_STATUS_TYPE_1"."NAME", "PR_STATUS_TYPE"."NAME", "PR_1"."PARENT_ID", "PROJECT_2"."NAME", "TW_RPT_11263_7833_199916"."ID", "TW_V_DESCRIPTION"."TEXT", "TW_V_MATERIAL_CONTINUATION_DEC"."TEXT", "TW_V_DESCRIPTION_1"."TEXT", "TW_V_JUSTIFICATION"."TEXT", "TW_V_CLOSURE_SUMMARY"."TEXT", "TW_V_QI_CLOSURE_SUMMARY"."TEXT" FROM   (((((((((((((("TRACKWISE_OWNER"."PR" "PR" LEFT OUTER JOIN "TRACKWISE_OWNER"."PR" "PR_1" ON "PR"."ID"="PR_1"."ROOT_PARENT_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."TW_V_DESCRIPTION" "TW_V_DESCRIPTION" ON "PR"."ID"="TW_V_DESCRIPTION"."PR_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."TW_V_MATERIAL_CONTINUATION_DEC" "TW_V_MATERIAL_CONTINUATION_DEC" ON "PR"."ID"="TW_V_MATERIAL_CONTINUATION_DEC"."PR_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."TW_V_IMPACT_LEVEL" "TW_V_IMPACT_LEVEL" ON "PR"."ID"="TW_V_IMPACT_LEVEL"."PR_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."PROJECT" "PROJECT" ON "PR"."PROJECT_ID"="PROJECT"."ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."PR_STATUS_TYPE" "PR_STATUS_TYPE" ON "PR"."STATUS_TYPE"="PR_STATUS_TYPE"."ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."TW_V_CLOSURE_SUMMARY" "TW_V_CLOSURE_SUMMARY" ON "PR"."ID"="TW_V_CLOSURE_SUMMARY"."PR_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."TW_V_QI_CLOSURE_SUMMARY" "TW_V_QI_CLOSURE_SUMMARY" ON "PR"."ID"="TW_V_QI_CLOSURE_SUMMARY"."PR_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."PROJECT" "PROJECT_1" ON "PR_1"."PROJECT_ID"="PROJECT_1"."ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."TW_V_DESCRIPTION" "TW_V_DESCRIPTION_1" ON "PR_1"."ID"="TW_V_DESCRIPTION_1"."PR_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."PR_STATUS_TYPE" "PR_STATUS_TYPE_1" ON "PR_1"."STATUS_TYPE"="PR_STATUS_TYPE_1"."ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."PR" "PR_2" ON "PR_1"."PARENT_ID"="PR_2"."ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."TW_V_JUSTIFICATION" "TW_V_JUSTIFICATION" ON "PR_1"."ID"="TW_V_JUSTIFICATION"."PR_ID") LEFT OUTER JOIN "TRACKWISE_OWNER"."PROJECT" "PROJECT_2" ON "PR_2"."PROJECT_ID"="PROJECT_2"."ID") INNER JOIN "TRACKWISE_OWNER"."TW_RPT_11263_7833_199916" "TW_RPT_11263_7833_199916" ON "PR"."ID"="TW_RPT_11263_7833_199916"."ID" WHERE  ("PROJECT"."NAME"='Quality Investigation - SC' OR "PROJECT"."NAME"='Quality Issue')

我正在寻找任何想法来帮助 Oracle 找出具有这种结构的查询的最佳连接顺序,而不管视图的名称 (TW_RPT_####-######)。可以肯定地假设视图的行数总是比 PR 表少得多。

以下是应用程序根据最终用户在运行报告之前在应用程序查询中指定的内容创建的示例视图:

**TW_RPT_11263_7833_199916:**
  CREATE OR REPLACE FORCE EDITIONABLE VIEW "TRACKWISE_OWNER"."TW_RPT_11263_7833_199916" ("ID") DEFAULT COLLATION "USING_NLS_COMP"  AS 
  SELECT DISTINCT PR.id 
FROM 
    pr, project , Project_member, Group_member 
WHERE 
    project.id = pr.project_id AND 
    pr.id IN (
        SELECT 
            pr_addtl_data.pr_id 
        FROM 
            pr_addtl_data 
        WHERE 
            pr_addtl_data.pr_id = pr.id AND 
            pr_addtl_data.data_field_id = 573 AND 
            pr_addtl_data.n_value IN (6164231)
    ) AND PR.project_parent_id IN(366,279,395,396) AND Project_member.project_id = PR.project_parent_id AND Group_member.project_member_id = Project_member.id AND Project_member.person_rel_id = 13836 AND ((Project_member.view_all = 1) OR (Project_member.view_self_created = 1 and PR.created_by_rel_id = 13836) OR (Project_member.view_assigned_to = 1 and PR.responsible_rel_id = 13836) OR (Project_member.view_group_created = 1 and PR.user_group_id = Group_member.user_group_id) OR (Project_member.view_by_entity = 1 and PR.entity_id = 1251));

视图的结果是两个记录 ID,如下所示,以毫秒为单位返回:2012202 和 2012397

标签: oraclequery-optimizationcrystal-reports-2016

解决方案


一种选择是使用命令作为报告的数据源。参数可以控制命令语法中使用的表/视图。


推荐阅读