我遇到了一个我很难理解的问题。我有两个运行缓慢的查询。所以我开始研究性能问题。两个查询中的所有表都有最近更新的统计信息,因此当我使用/ * + gather_plan_statistics * /提示运行两个查询时,当我使用下面的视图查看实际统计数据时,我感到非常惊讶。
select * from table(dbms_xplan.display_cursor(null, null, 'ALLSTATS LAST'));
解释计划的估计行数和实际行数之间存在很大差异。 可能的原因是什么?如果表统计数据是最新的,为什么会有很大差异?我可以开始使用提示,但我宁愿让优化器。
我已经包含了SQL查询并解释了下面的计划。
select /*+ ORDERED USE_NL(prod,tle,uh,bro) gather_plan_statistics */
prod.cre_surr_id,
tle.title ,
min(uh.performance_date) performance_date,
prod.year_of_production,
prod.production_type type_code
from wacsusers.prod_date_constraint_vw pdcv join prblk.productions prod ON prod.cre_surr_id = pdcv.cre_surr_id
inner join titles tle on tle.cre_surr_id = prod.cre_surr_id and tle.tt_code = 'R'
left join prblk.usage_headers uh on uh.prod_exploitation_cre_surr_id = prod.cre_surr_id
left join broadcasters bro on bro.tp_surr_id = uh.bro_broadcast_by_tp_surr_id
where pdcv.title like 'BELIEVE%' and uh.performance_date between to_date('01-JAN-1900','DD-MON-YYYY') and to_date('01-JAN-2900','DD-MON-YYYY')
AND prod.dn_prst_status = '4'
AND prod.medium_type = 'AV'
group by prod.cre_surr_id,
prod.production_type,
tle.title,
prod.year_of_production,
prod.music_content_indicator
HAVING (prod.music_content_indicator IN ('Y', 'N')
OR prod.music_content_indicator IS NULL
OR (prod.music_content_indicator = 'W'
AND (prod.production_type = 'COM'
AND MIN (uh.performance_date) BETWEEN (SYSDATE - 1091) AND (SYSDATE - 90))
OR (prod.production_type != 'COM' AND MIN (uh.performance_date)
BETWEEN (SYSDATE - 1091) AND (SYSDATE - 90)))) order by title asc
1 - filter(("PROD"."MUSIC_CONTENT_INDICATOR"='Y' OR "PROD"."MUSIC_CONTENT_INDICATOR"='N' OR "PROD"."MUSIC_CONTENT_INDICATOR" IS NULL OR
("PROD"."MUSIC_CONTENT_INDICATOR"='W' AND "PROD"."PRODUCTION_TYPE"='COM' AND MIN("UH"."PERFORMANCE_DATE")>=SYSDATE@!-1091 AND
MIN("UH"."PERFORMANCE_DATE")<=SYSDATE@!-90) OR ("PROD"."PRODUCTION_TYPE"<>'COM' AND MIN("UH"."PERFORMANCE_DATE")>=SYSDATE@!-1091 AND
MIN("UH"."PERFORMANCE_DATE")<=SYSDATE@!-90)))
7 - filter(("PTM"."MUSIC_CONTENT_INDICATOR" IS NULL OR "PTM"."MUSIC_CONTENT_INDICATOR"="CONSTANTS"."CONTENT_YES"() OR
"PTM"."MUSIC_CONTENT_INDICATOR"="CONSTANTS"."CONTENT_NO"() OR ("PTM"."START_DTM">=SYSDATE@!-"CONSTANTS"."FLICS_INC_STA_DYS_AGO"() AND
"PTM"."START_DTM"<=SYSDATE@!-"CONSTANTS"."FLICS_INC_END_DYS_AGO"() AND "PTM"."PRODUCTION_TYPE"<>"CONSTANTS"."PROD_TYPE_COMMERCIAL"()) OR
("PTM"."START_DTM">=SYSDATE@!-"CONSTANTS"."CLICS_INC_STA_DYS_AGO"() AND "PTM"."START_DTM"<=SYSDATE@!-"CONSTANTS"."CLICS_INC_END_DYS_AGO"() AND
"PTM"."PRODUCTION_TYPE"="CONSTANTS"."PROD_TYPE_COMMERCIAL"() AND "PTM"."MUSIC_CONTENT_INDICATOR"="CONSTANTS"."CONTENT_WAITING"())))
8 - access("PTM"."TITLE" LIKE 'BELIEVE%')
filter("PTM"."TITLE" LIKE 'BELIEVE%')
9 - filter(("PROD"."DN_PRST_STATUS"='4' AND "PROD"."MEDIUM_TYPE"='AV'))
10 - access("PROD"."CRE_SURR_ID"="PTM"."CRE_SURR_ID")
12 - access("TLE"."CRE_SURR_ID"="PROD"."CRE_SURR_ID" AND "TLE"."TT_CODE"='R')
13 - access("UH"."PROD_EXPLOITATION_CRE_SURR_ID"="PROD"."CRE_SURR_ID")
filter("UH"."PROD_EXPLOITATION_CRE_SURR_ID" IS NOT NULL)
14 - filter(("UH"."PERFORMANCE_DATE">=TO_DATE(' 1900-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "UH"."PERFORMANCE_DATE"<=TO_DATE(' 2900-01-01
00:00:00', 'syyyy-mm-dd hh24:mi:ss')))
-
SELECT /*+ gather_plan_statistics */ prod.cre_surr_id,
tle.title, prod.year_of_production,
prod.music_content_indicator
FROM prblk.productions prod
INNER JOIN titles tle ON tle.cre_surr_id = prod.cre_surr_id AND tle.tt_code = 'R'
JOIN (SELECT DISTINCT cc.prod_cre_surr_id
FROM prblk.creation_components cc
INNER JOIN works wrk ON wrk.cre_surr_id = cc.wrk_cre_surr_id
WHERE wrk.logically_deleted_y IS NULL
AND EXISTS ( SELECT 1
FROM tle_title_tokens ttt
WHERE token_type in ('E', 'N')
AND dn_wrk_cre_surr_id = wrk.cre_surr_id
AND search_token LIKE :title||'%' )
AND EXISTS ( SELECT 1
FROM works_ips wips,
ip_name_tokens ipnt
WHERE wips.ip_surr_id = ipnt.ip_surr_id
AND ipnt.search_token like :writer||'%'
AND ipnt.token_type = 'N'
AND wips.wrk_cre_surr_id = wrk.cre_surr_id)
AND cc.dn_ccst_status <> '6' ) cct ON cct.prod_cre_surr_id = prod.cre_surr_id
AND (( prod.music_content_indicator = 'W'
AND (SELECT MIN (uh.performance_date)
FROM prblk.usage_headers uh
WHERE uh.prod_exploitation_cre_surr_id = prod.cre_surr_id) BETWEEN SYSDATE - CASE prod.production_type WHEN 'COM' THEN 1091
ELSE 1091 END
AND SYSDATE - CASE prod.production_type WHEN 'COM'
THEN 90
ELSE 90
END ) OR NVL (prod.music_content_indicator, 'N') in ('Y','N') ) ORDER BY title asc
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter((NVL("SYS_ALIAS_1"."MUSIC_CONTENT_INDICATOR",'N')='Y' OR NVL("SYS_ALIAS_1"."MUSIC_CONTENT_INDICATOR",'N')='N' OR
("SYS_ALIAS_1"."MUSIC_CONTENT_INDICATOR"='W' AND >=SYSDATE@!-1091 AND <=SYSDATE@!-90)))
5 - access("CCT"."PROD_CRE_SURR_ID"="SYS_ALIAS_1"."CRE_SURR_ID")
8 - access("WRK"."CRE_SURR_ID"="CC"."WRK_CRE_SURR_ID")
9 - access("TTT"."DN_WRK_CRE_SURR_ID"="WRK"."CRE_SURR_ID")
10 - access("WIPS"."WRK_CRE_SURR_ID"="WRK"."CRE_SURR_ID")
11 - filter("WRK"."LOGICALLY_DELETED_Y" IS NULL)
12 - access("WIPS"."IP_SURR_ID"="IPNT"."IP_SURR_ID")
13 - access("IPNT"."TOKEN_TYPE"='N' AND "IPNT"."SEARCH_TOKEN" LIKE :WRITER||'%')
filter("IPNT"."SEARCH_TOKEN" LIKE :WRITER||'%')
16 - access((("TTT"."TOKEN_TYPE"='E' OR "TTT"."TOKEN_TYPE"='N')) AND "TTT"."SEARCH_TOKEN" LIKE :TITLE||'%')
filter("TTT"."SEARCH_TOKEN" LIKE :TITLE||'%')
17 - filter(("CC"."WRK_CRE_SURR_ID" IS NOT NULL AND "CC"."DN_CCST_STATUS"<>'6'))
19 - access("TLE"."CRE_SURR_ID"="SYS_ALIAS_1"."CRE_SURR_ID" AND "TLE"."TT_CODE"='R')
23 - access("UH"."PROD_EXPLOITATION_CRE_SURR_ID"=:B1)