【发布时间】:2021-11-07 18:04:54
【问题描述】:
由于需要 15 分钟的低效查询,我有一个通过应用程序运行的 Crystal 报表需要很长时间才能运行。我们正在运行 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 的查询需要
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
【问题讨论】:
-
而不是使用提示,您应该首先问为什么 Oracle 不使用 HASH JOIN。是否经常正确地计算统计数据?如果您定期计算统计数据并且计划仍然是问题,那么 Oracle 可能出于某种原因使用 NESTED LOOPS 而不是 HASH JOIN(可能是索引?)。另一方面,虽然视图名称发生了变化,但如果后面的查询是相同的,还有其他比 SQL Profiles 更好的技术来强制执行不同的计划,而无需触及视图或 Cristal Reports 中的代码....跨度>
-
... 一个想法是使用 SQL 基线。我自己这样做是为了在不触及查询的情况下更改关闭产品的查询计划
-
您可以控制查询生成过程吗?您可以使用一些常量表别名并在提示中指定它。那么你就不需要关心表名了
-
您是否考虑过向 Crystal 的客户支持团队询问此事?这是一个昂贵的软件产品,他们确实有称职的支持人员。值得一试。
-
统计数据是最近计算的,不会过时。 8 小时长的查询 SQL 调优建议没有提供额外的推荐索引。视图后面的查询不断变化,视图名称也不断变化,因此我不知道 sql 基线是否可以在这里工作,一次只有一个查询。如果我们无法通过应用程序供应商获得支持,我喜欢询问 Crystal Reports 供应商的想法。
标签: oracle query-optimization crystal-reports-2016